commit 3b1e713fc4ac0184419a0c8775b8916fb1265200 Author: Nathan Adams Date: Sat Jul 20 17:41:56 2013 -0500 Initial commit diff --git a/indefero/src/IDF/ActivityTaxonomy.php b/indefero/src/IDF/ActivityTaxonomy.php new file mode 100644 index 0000000..7b24370 --- /dev/null +++ b/indefero/src/IDF/ActivityTaxonomy.php @@ -0,0 +1,165 @@ + $weight) { + $sectionWeights[$section] = $weight / (float) $allWeights; + } + + // + // determine the date boundaries + // + if ($lookback < 1) { + throw new LogicException('lookback must be greater or equal to 1'); + } + $dateCopy = new DateTime(); + $dateCopy->setTimestamp($date->getTimestamp()); + $dateBoundaries = array( + $dateCopy->format('Y-m-d 23:59:59'), + $dateCopy->sub(new DateInterval('P'.$lookback.'D'))->format('Y-m-d 00:00:00') + ); + + // + // now recalculate the values for all projects + // + $projects = Pluf::factory('IDF_Project')->getList(); + foreach ($projects as $project) { + self::recalculateTaxonomy($date, $project, $dateBoundaries, $sectionWeights); + } + } + + private static function recalculateTaxonomy(DateTime $date, IDF_Project $project, array $dateBoundaries, array $sectionWeights) + { + $conf = new IDF_Conf(); + $conf->setProject($project); + + $sectionClasses = array( + 'source' => array('IDF_Commit'), + 'issues' => array('IDF_Issue'), + 'wiki' => array('IDF_Wiki_Page', 'IDF_Wiki_Resource'), + 'review' => array('IDF_Review'), + 'downloads' => array('IDF_Upload') + ); + + $value = 0; + foreach ($sectionWeights as $section => $weight) { + // skip closed / non-existant sections + if ($conf->getVal($section.'_access_rights') === 'none') + continue; + + if (!array_key_exists($section, $sectionClasses)) + continue; + + $sectionValue = self::calculateActivityValue( + $dateBoundaries, $sectionClasses[$section], $project->id); + $value = ((1 - $weight) * $value) + ($weight * $sectionValue); + } + + echo "project {$project->name} has an activity value of $value\n"; + + $sql = new Pluf_SQL('project=%s AND date=%s', array($project->id, $date->format('Y-m-d'))); + $activity = Pluf::factory('IDF_ProjectActivity')->getOne(array('filter' => $sql->gen())); + + if ($activity == null) { + $activity = new IDF_ProjectActivity(); + $activity->project = $project; + $activity->date = $date->format('Y-m-d'); + $activity->value = $value; + $activity->create(); + } else { + $activity->value = $value; + $activity->update(); + } + } + + private static function calculateActivityValue(array $dateBoundaries, array $classes, $projectId) + { + $allCount = self::countActivityFor($dateBoundaries, $classes); + if ($allCount == 0) return 0; + $prjCount = self::countActivityFor($dateBoundaries, $classes, $projectId); + return $prjCount / (float) $allCount; + } + + private static function countActivityFor(array $dateBoundaries, array $classes, $projectId = null) + { + static $cache = array(); + $argIdent = md5(serialize(func_get_args())); + if (array_key_exists($argIdent, $cache)) { + return $cache[$argIdent]; + } + + $cache[$argIdent] = 0; + list($higher, $lower) = $dateBoundaries; + $db = Pluf::db(); + $classes_esc = array(); + foreach ($classes as $class) { + $classes_esc[] = $db->esc($class); + } + $sql = new Pluf_SQL('model_class IN ('.implode(',', $classes_esc).') '. + 'AND creation_dtime >= %s AND creation_dtime <= %s', + array($lower, $higher)); + + if ($projectId !== null) { + $sql->SAnd(new Pluf_SQL('project=%s', array($projectId))); + } + + $cache[$argIdent] = Pluf::factory('IDF_Timeline')->getCount(array('filter' => $sql->gen())); + + return $cache[$argIdent]; + } +} \ No newline at end of file diff --git a/indefero/src/IDF/Commit.php b/indefero/src/IDF/Commit.php new file mode 100644 index 0000000..0060ec7 --- /dev/null +++ b/indefero/src/IDF/Commit.php @@ -0,0 +1,353 @@ +_a['table'] = 'idf_commits'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + 'blank' => true, + ), + 'project' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_Project', + 'blank' => false, + 'verbose' => __('project'), + 'relate_name' => 'commits', + ), + 'author' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'Pluf_User', + 'is_null' => true, + 'verbose' => __('submitter'), + 'relate_name' => 'submitted_commit', + 'help_text' => 'This will allow us to list the latest commits of a user in its profile.', + ), + 'origauthor' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 150, + 'help_text' => 'As we do not necessary have the mapping between the author in the database and the scm, we store the scm author commit information here. That way we can update the author info later in the process.', + ), + 'scm_id' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 50, + 'index' => true, + 'help_text' => 'The id of the commit. For git, it will be the SHA1 hash, for subversion it will be the revision id.', + ), + 'summary' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 250, + 'verbose' => __('summary'), + ), + 'fullmessage' => + array( + 'type' => 'Pluf_DB_Field_Text', + 'blank' => true, + 'verbose' => __('changelog'), + 'help_text' => 'This is the full message of the commit.', + ), + 'creation_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('creation date'), + 'index' => true, + 'help_text' => 'Date of creation by the scm', + ), + ); + } + + function __toString() + { + return $this->summary.' - ('.$this->scm_id.')'; + } + + function _toIndex() + { + $str = str_repeat($this->summary.' ', 4).' '.$this->fullmessage; + return Pluf_Text::cleanString(html_entity_decode($str, ENT_QUOTES, 'UTF-8')); + } + + function postSave($create=false) + { + IDF_Search::index($this); + if ($create) { + IDF_Timeline::insert($this, $this->get_project(), + $this->get_author(), $this->creation_dtime); + } + } + + function preDelete() + { + IDF_Timeline::remove($this); + IDF_Search::remove($this); + IDF_Gconf::dropForModel($this); + } + + /** + * Create a commit from a simple class commit info of a changelog. + * + * @param stdClass Commit info + * @param IDF_Project Current project + * @return IDF_Commit + */ + public static function getOrAdd($change, $project) + { + $sql = new Pluf_SQL('project=%s AND scm_id=%s', + array($project->id, $change->commit)); + $r = Pluf::factory('IDF_Commit')->getList(array('filter'=>$sql->gen())); + if ($r->count() > 0) { + $r[0]->extra = new IDF_Gconf(); + $r[0]->extra->serialize = true; + $r[0]->extra->setModel($r[0]); + $r[0]->extra->initCache(); + return $r[0]; + } + if (!isset($change->full_message)) { + $change->full_message = ''; + } + $scm = IDF_Scm::get($project); + $commit = new IDF_Commit(); + $commit->project = $project; + $commit->scm_id = $change->commit; + $commit->summary = self::toUTF8($change->title); + $commit->fullmessage = self::toUTF8($change->full_message); + $commit->author = $scm->findAuthor($change->author); + $commit->origauthor = self::toUTF8($change->author); + $commit->creation_dtime = $change->date; + $commit->create(); + $extra = $scm->getExtraProperties($change); + $commit->extra = new IDF_Gconf(); + $commit->extra->serialize = true; // As we can store arrays + $commit->extra->setModel($commit); + foreach ($extra as $key => $val) { + $commit->extra->setVal($key, $val); + } + $commit->notify($project->getConf()); + return $commit; + } + + /** + * Convert encoding to UTF8. + * + * If an array is given, the encoding is detected only on the + * first value and then used to convert all the strings. + * + * @param mixed String or array of string to be converted + * @param bool Returns the encoding together with the converted text (false) + * @return mixed String or array of string or array of res + encoding + */ + public static function toUTF8($text, $get_encoding=False) + { + $enc = 'ASCII, UTF-8, ISO-8859-1, JIS, EUC-JP, SJIS'; + $ref = $text; + if (is_array($text)) { + $ref = $text[0]; + } + if (Pluf_Text_UTF8::check($ref)) { + return (!$get_encoding) ? $text : array($text, 'UTF-8'); + } + $encoding = mb_detect_encoding($ref, $enc, true); + if ($encoding == false) { + $encoding = Pluf_Text_UTF8::detect_cyr_charset($ref); + } + if (is_array($text)) { + foreach ($text as $t) { + $res[] = mb_convert_encoding($t, 'UTF-8', $encoding); + } + return (!$get_encoding) ? $res : array($res, $encoding); + } else { + $res = mb_convert_encoding($text, 'UTF-8', $encoding); + return (!$get_encoding) ? $res : array($res, $encoding); + } + } + + /** + * Returns the timeline fragment for the commit. + * + * + * @param Pluf_HTTP_Request + * @return Pluf_Template_SafeString + */ + public function timelineFragment($request) + { + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::commit', + array($request->project->shortname, + $this->scm_id)); + $out = ''. + Pluf_esc(Pluf_Template_dateAgo($this->creation_dtime, 'without')). + ''; + $stag = new IDF_Template_ShowUser(); + $user = $stag->start($this->get_author(), $request, $this->origauthor, false); + $tag = new IDF_Template_IssueComment(); + $out .= $tag->start($this->summary, $request, false); + if (0 && $this->fullmessage) { + $out .= '

'.$tag->start($this->fullmessage, $request, false); + } + $out .= ' + + + +
'.sprintf(__('Commit %1$s, by %2$s'), ''.$this->scm_id.'', $user).'
'; + return Pluf_Template::markSafe($out); + } + + /** + * Returns the feed fragment for the commit. + * + * @param Pluf_HTTP_Request + * @return Pluf_Template_SafeString + */ + public function feedFragment($request) + { + $url = Pluf::f('url_base') + .Pluf_HTTP_URL_urlForView('IDF_Views_Source::commit', + array($request->project->shortname, + $this->scm_id)); + $date = Pluf_Date::gmDateToGmString($this->creation_dtime); + $author = ($this->get_author()) ? + $this->get_author() : $this->origauthor; + $cproject = $this->get_project(); + $context = new Pluf_Template_Context_Request( + $request, + array( + 'c' => $this, + 'cproject' => $cproject, + 'url' => $url, + 'date' => $date, + 'author' => $author, + ) + ); + $tmpl = new Pluf_Template('idf/source/feedfragment.xml'); + return $tmpl->render($context); + } + + /** + * Notification of change of the object. + * + * @param IDF_Conf Current configuration + * @param bool Creation (true) + */ + public function notify($conf, $create=true) + { + // Now we add to the queue, soon we will push everything in + // the queue, including email notifications and indexing. + // Even if the url is empty, we add to the queue as some + // plugins may want to do something with this information in + // an asynchronous way. + $project = $this->get_project(); + $scm = $project->getConf()->getVal('scm', 'git'); + $url = str_replace(array('%p', '%r'), + array($project->shortname, $this->scm_id), + $conf->getVal('webhook_url', '')); + + // trigger a POST instead of the standard PUT if we're asked for + $method = 'PUT'; + if (Pluf::f('webhook_processing', '') === 'compat') { + $method = 'POST'; + } + $payload = array('to_send' => array( + 'project' => $project->shortname, + 'rev' => $this->scm_id, + 'scm' => $scm, + 'summary' => $this->summary, + 'fullmessage' => $this->fullmessage, + 'author' => $this->origauthor, + 'creation_date' => $this->creation_dtime, + ), + 'project_id' => $project->id, + 'authkey' => $project->getWebHookKey(), + 'url' => $url, + 'method' => $method, + ); + $item = new IDF_Queue(); + $item->type = 'new_commit'; + $item->payload = $payload; + $item->create(); + + $current_locale = Pluf_Translation::getLocale(); + + $from_email = Pluf::f('from_email'); + $recipients = $project->getNotificationRecipientsForTab('source'); + + foreach ($recipients as $address => $language) { + + if (!empty($this->author) && $this->author->email === $address) { + continue; + } + + Pluf_Translation::loadSetLocale($language); + + $context = new Pluf_Template_Context(array( + 'commit' => $this, + 'project' => $project, + 'url_base' => Pluf::f('url_base'), + )); + + // commits are usually not updated, therefor we do not + // distinguish between create and update here + $tplfile = 'idf/source/commit-created-email.txt'; + $subject = __('New Commit %1$s - %2$s (%3$s)'); + + $tmpl = new Pluf_Template($tplfile); + $text_email = $tmpl->render($context); + + $email = new Pluf_Mail($from_email, + $address, + sprintf($subject, + $this->scm_id, $this->summary, + $project->shortname)); + $email->addTextMessage($text_email); + $email->sendMail(); + } + + Pluf_Translation::loadSetLocale($current_locale); + } +} diff --git a/indefero/src/IDF/Conf.php b/indefero/src/IDF/Conf.php new file mode 100644 index 0000000..90ad871 --- /dev/null +++ b/indefero/src/IDF/Conf.php @@ -0,0 +1,140 @@ +_a['table'] = 'idf_conf'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + //It is automatically added. + 'blank' => true, + ), + 'project' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_Project', + 'blank' => false, + 'verbose' => __('project'), + ), + 'vkey' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 50, + 'verbose' => __('key'), + ), + 'vdesc' => + array( + 'type' => 'Pluf_DB_Field_Text', + 'blank' => false, + 'verbose' => __('value'), + ), + ); + $this->_a['idx'] = array('project_vkey_idx' => + array( + 'col' => 'project, vkey', + 'type' => 'unique', + ), + ); + $this->f = new IDF_Config_DataProxy($this); + } + + function setProject($project) + { + $this->datacache = null; + $this->_project = $project; + } + + function initCache() + { + $this->datacache = array(); + $sql = new Pluf_SQL('project=%s', $this->_project->id); + foreach ($this->getList(array('filter' => $sql->gen())) as $val) { + $this->datacache[$val->vkey] = $val->vdesc; + } + } + + /** + * FIXME: This is not efficient when setting a large number of + * values in a loop. + */ + function setVal($key, $value) + { + if (!is_null($this->getVal($key, null)) + and $value == $this->getVal($key)) { + return; + } + $this->delVal($key, false); + $conf = new IDF_Conf(); + $conf->project = $this->_project; + $conf->vkey = $key; + $conf->vdesc = $value; + $conf->create(); + $this->initCache(); + } + + function getVal($key, $default='') + { + if ($this->datacache === null) { + $this->initCache(); + } + return (isset($this->datacache[$key])) ? $this->datacache[$key] : $default; + } + + function delVal($key, $initcache=true) + { + $gconf = new IDF_Conf(); + $sql = new Pluf_SQL('vkey=%s AND project=%s', array($key, $this->_project->id)); + foreach ($gconf->getList(array('filter' => $sql->gen())) as $c) { + $c->delete(); + } + if ($initcache) { + $this->initCache(); + } + } + + function getKeys() + { + if ($this->datacache === null) { + $this->initCache(); + } + return array_keys($this->datacache); + } +} diff --git a/indefero/src/IDF/Config/DataProxy.php b/indefero/src/IDF/Config/DataProxy.php new file mode 100644 index 0000000..9bfc628 --- /dev/null +++ b/indefero/src/IDF/Config/DataProxy.php @@ -0,0 +1,42 @@ +obj = $obj; + } + + public function __get($field) + { + return $this->obj->getVal($field); + } +} diff --git a/indefero/src/IDF/Diff.php b/indefero/src/IDF/Diff.php new file mode 100644 index 0000000..ac86934 --- /dev/null +++ b/indefero/src/IDF/Diff.php @@ -0,0 +1,472 @@ +path_strip_level = $path_strip_level; + $this->lines = IDF_FileUtil::splitIntoLines($diff, true); + } + + public function parse() + { + $current_file = ''; + $current_chunk = 0; + $lline = 0; + $rline = 0; + $files = array(); + $indiff = false; // Used to skip the headers in the git patches + $i = 0; // Used to skip the end of a git patch with --\nversion number + $diffsize = count($this->lines); + while ($i < $diffsize) { + // look for the potential beginning of a diff + if (substr($this->lines[$i], 0, 4) !== '--- ') { + $i++; + continue; + } + + // we're inside a diff candiate + $oldfileline = $this->lines[$i++]; + $newfileline = $this->lines[$i++]; + if (substr($newfileline, 0, 4) !== '+++ ') { + // not a valid diff here, move on + continue; + } + + // use new file name by default + preg_match("/^\+\+\+ ([^\t\n\r]+)/", $newfileline, $m); + $current_file = $m[1]; + if ($current_file === '/dev/null') { + // except if it's /dev/null, use the old one instead + // eg. mtn 0.48 and newer + preg_match("/^--- ([^\t\r\n]+)/", $oldfileline, $m); + $current_file = $m[1]; + } + if ($this->path_strip_level > 0) { + $fileparts = explode('/', $current_file, $this->path_strip_level+1); + $current_file = array_pop($fileparts); + } + $current_chunk = 0; + $files[$current_file] = array(); + $files[$current_file]['chunks'] = array(); + $files[$current_file]['chunks_def'] = array(); + + while ($i < $diffsize && substr($this->lines[$i], 0, 3) === '@@ ') { + $elems = preg_match('/@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@.*/', + $this->lines[$i++], $results); + if ($elems != 1) { + // hunk is badly formatted + break; + } + $delstart = $results[1]; + $dellines = $results[2] === '' ? 1 : $results[2]; + $addstart = $results[3]; + $addlines = $results[4] === '' ? 1 : $results[4]; + + $files[$current_file]['chunks_def'][] = array( + array($delstart, $dellines), array($addstart, $addlines) + ); + $files[$current_file]['chunks'][] = array(); + + while ($i < $diffsize && ($addlines >= 0 || $dellines >= 0)) { + $linetype = $this->lines[$i] != '' ? $this->lines[$i][0] : false; + $content = substr($this->lines[$i], 1); + switch ($linetype) { + case ' ': + $files[$current_file]['chunks'][$current_chunk][] = + array($delstart, $addstart, $content); + $dellines--; + $addlines--; + $delstart++; + $addstart++; + break; + case '+': + $files[$current_file]['chunks'][$current_chunk][] = + array('', $addstart, $content); + $addlines--; + $addstart++; + break; + case '-': + $files[$current_file]['chunks'][$current_chunk][] = + array($delstart, '', $content); + $dellines--; + $delstart++; + break; + case '\\': + // no new line at the end of this file; remove pseudo new line from last line + $cur = count($files[$current_file]['chunks'][$current_chunk]) - 1; + $files[$current_file]['chunks'][$current_chunk][$cur][2] = + rtrim($files[$current_file]['chunks'][$current_chunk][$cur][2], "\r\n"); + continue; + default: + break 2; + } + $i++; + } + $current_chunk++; + } + } + $this->files = $files; + return $files; + } + + /** + * Return the html version of a parsed diff. + */ + public function as_html() + { + $out = ''; + foreach ($this->files as $filename => $file) { + $pretty = ''; + $fileinfo = IDF_FileUtil::getMimeType($filename); + if (IDF_FileUtil::isSupportedExtension($fileinfo[2])) { + $pretty = ' prettyprint'; + } + + $cc = 1; + $offsets = array(); + $contents = array(); + + foreach ($file['chunks'] as $chunk) { + foreach ($chunk as $line) { + list($left, $right, $content) = $line; + if ($left and $right) { + $class = 'context'; + } elseif ($left) { + $class = 'removed'; + } else { + $class = 'added'; + } + + $offsets[] = sprintf('%s%s', $left, $right); + $content = IDF_FileUtil::emphasizeControlCharacters(Pluf_esc($content)); + $contents[] = sprintf('%s', $class, $pretty, $content); + } + if (count($file['chunks']) > $cc) { + $offsets[] = '......'; + $contents[] = ''; + } + $cc++; + } + + list($added, $removed) = end($file['chunks_def']); + + $added = $added[0] + $added[1]; + $leftwidth = 0; + if ($added > 0) + $leftwidth = ((ceil(log10($added)) + 1) * 8) + 17; + + $removed = $removed[0] + $removed[1]; + $rightwidth = 0; + if ($removed > 0) + $rightwidth = ((ceil(log10($removed)) + 1) * 8) + 17; + + // we need to correct the width of a single column a little + // to take less space and to hide the empty one + $class = ''; + if ($leftwidth == 0) { + $class = 'left-hidden'; + $rightwidth -= floor(log10($removed)); + } + else if ($rightwidth == 0) { + $class = 'right-hidden'; + $leftwidth -= floor(log10($added)); + } + + $inner_linecounts = + '' ."\n". + '' ."\n". + '' . + implode(''."\n".'', $offsets). + '' ."\n". + '
' ."\n"; + + + $inner_contents = + '' ."\n". + '' . + implode(''."\n".'', $contents) . + '' ."\n". + '
' ."\n"; + + $out .= '' ."\n". + '' ."\n". + ''. + ''. + '' ."\n". + '' . + ''. "\n". + ''. + '' ."\n". + '
'.Pluf_esc($filename).'
'. $inner_linecounts .'
'. $inner_contents .'
' ."\n"; + } + + return Pluf_Template::markSafe($out); + } + + /** + * Review patch. + * + * Given the original file as a string and the parsed + * corresponding diff chunks, generate a side by side view of the + * original file and new file with added/removed lines. + * + * Example of use: + * + * $diff = new IDF_Diff(file_get_contents($diff_file)); + * $orig = file_get_contents($orig_file); + * $diff->parse(); + * echo $diff->fileCompare($orig, $diff->files[$orig_file], $diff_file); + * + * @param string Original file + * @param array Chunk description of the diff corresponding to the file + * @param string Original file name + * @param int Number of lines before/after the chunk to be displayed (10) + * @return Pluf_Template_SafeString The table body + */ + public function fileCompare($orig, $chunks, $filename, $context=10) + { + $orig_lines = IDF_FileUtil::splitIntoLines($orig); + $new_chunks = $this->mergeChunks($orig_lines, $chunks, $context); + return $this->renderCompared($new_chunks, $filename); + } + + private function mergeChunks($orig_lines, $chunks, $context=10) + { + $spans = array(); + $new_chunks = array(); + $min_line = 0; + $max_line = 0; + //if (count($chunks['chunks_def']) == 0) return ''; + foreach ($chunks['chunks_def'] as $chunk) { + $start = ($chunk[0][0] > $context) ? $chunk[0][0]-$context : 0; + $end = (($chunk[0][0]+$chunk[0][1]+$context-1) < count($orig_lines)) ? $chunk[0][0]+$chunk[0][1]+$context-1 : count($orig_lines); + $spans[] = array($start, $end); + } + // merge chunks/get the chunk lines + // these are reference lines + $chunk_lines = array(); + foreach ($chunks['chunks'] as $chunk) { + foreach ($chunk as $line) { + $chunk_lines[] = $line; + } + } + $i = 0; + foreach ($chunks['chunks'] as $chunk) { + $n_chunk = array(); + // add lines before + if ($chunk[0][0] > $spans[$i][0]) { + for ($lc=$spans[$i][0];$lc<$chunk[0][0];$lc++) { + $exists = false; + foreach ($chunk_lines as $line) { + if ($lc == $line[0] + or ($chunk[0][1]-$chunk[0][0]+$lc) == $line[1]) { + $exists = true; + break; + } + } + if (!$exists) { + $orig = isset($orig_lines[$lc-1]) ? $orig_lines[$lc-1] : ''; + $n_chunk[] = array( + $lc, + $chunk[0][1]-$chunk[0][0]+$lc, + $orig + ); + } + } + } + // add chunk lines + foreach ($chunk as $line) { + $n_chunk[] = $line; + } + // add lines after + $lline = $line; + if (!empty($lline[0]) and $lline[0] < $spans[$i][1]) { + for ($lc=$lline[0];$lc<=$spans[$i][1];$lc++) { + $exists = false; + foreach ($chunk_lines as $line) { + if ($lc == $line[0] or ($lline[1]-$lline[0]+$lc) == $line[1]) { + $exists = true; + break; + } + } + if (!$exists) { + $n_chunk[] = array( + $lc, + $lline[1]-$lline[0]+$lc, + $orig_lines[$lc-1] + ); + } + } + } + $new_chunks[] = $n_chunk; + $i++; + } + // Now, each chunk has the right length, we need to merge them + // when needed + $nnew_chunks = array(); + $i = 0; + foreach ($new_chunks as $chunk) { + if ($i>0) { + $lline = end($nnew_chunks[$i-1]); + if ($chunk[0][0] <= $lline[0]+1) { + // need merging + foreach ($chunk as $line) { + if ($line[0] > $lline[0] or empty($line[0])) { + $nnew_chunks[$i-1][] = $line; + } + } + } else { + $nnew_chunks[] = $chunk; + $i++; + } + } else { + $nnew_chunks[] = $chunk; + $i++; + } + } + return $nnew_chunks; + } + + private function renderCompared($chunks, $filename) + { + $fileinfo = IDF_FileUtil::getMimeType($filename); + $pretty = ''; + if (IDF_FileUtil::isSupportedExtension($fileinfo[2])) { + $pretty = ' prettyprint'; + } + + $cc = 1; + $left_offsets = array(); + $left_contents = array(); + $right_offsets = array(); + $right_contents = array(); + + $max_lineno_left = $max_lineno_right = 0; + + foreach ($chunks as $chunk) { + foreach ($chunk as $line) { + $left = ''; + $right = ''; + $content = IDF_FileUtil::emphasizeControlCharacters(Pluf_esc($line[2])); + + if ($line[0] and $line[1]) { + $class = 'context'; + $left = $right = $content; + } elseif ($line[0]) { + $class = 'removed'; + $left = $content; + } else { + $class = 'added'; + $right = $content; + } + + $left_offsets[] = sprintf('%s', $line[0]); + $right_offsets[] = sprintf('%s', $line[1]); + $left_contents[] = sprintf('%s', $class, $pretty, $left); + $right_contents[] = sprintf('%s', $class, $pretty, $right); + + $max_lineno_left = max($max_lineno_left, $line[0]); + $max_lineno_right = max($max_lineno_right, $line[1]); + } + + if (count($chunks) > $cc) { + $left_offsets[] = '...'; + $right_offsets[] = '...'; + $left_contents[] = ''; + $right_contents[] = ''; + } + $cc++; + } + + $leftwidth = 1; + if ($max_lineno_left > 0) + $leftwidth = ((ceil(log10($max_lineno_left)) + 1) * 8) + 17; + + $rightwidth = 1; + if ($max_lineno_right > 0) + $rightwidth = ((ceil(log10($max_lineno_right)) + 1) * 8) + 17; + + $inner_linecounts_left = + '' ."\n". + '' ."\n". + '' . + implode(''."\n".'', $left_offsets). + '' ."\n". + '
' ."\n"; + + $inner_linecounts_right = + '' ."\n". + '' ."\n". + '' . + implode(''."\n".'', $right_offsets). + '' ."\n". + '
' ."\n"; + + $inner_contents_left = + '' ."\n". + '' . + implode(''."\n".'', $left_contents) . + '' ."\n". + '
' ."\n"; + + $inner_contents_right = + '' ."\n". + '' . + implode(''."\n".'', $right_contents) . + '' ."\n". + '
' ."\n"; + + $out = + '' ."\n". + '' . + '' . + '' . + '' ."\n". + ''. + ''. + '' ."\n". + '' . + '' . + ''. + '' . + ''. "\n". + ''. "\n". + ''. "\n". + ''. "\n". + '' ."\n". + '
'.Pluf_esc($filename).'
'.__('Old').''.__('New').'
'. $inner_linecounts_left .'
'. $inner_contents_left .'
'. $inner_linecounts_right .'
'. $inner_contents_right .'
' ."\n"; + + return Pluf_Template::markSafe($out); + } +} diff --git a/indefero/src/IDF/EmailAddress.php b/indefero/src/IDF/EmailAddress.php new file mode 100644 index 0000000..0220250 --- /dev/null +++ b/indefero/src/IDF/EmailAddress.php @@ -0,0 +1,96 @@ +_a['table'] = 'idf_emailaddresses'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + //It is automatically added. + 'blank' => true, + ), + 'user' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'Pluf_User', + 'blank' => false, + 'verbose' => __('user'), + ), + 'address' => + array( + 'type' => 'Pluf_DB_Field_Email', + 'blank' => false, + 'verbose' => __('email'), + 'unique' => true, + ), + ); + // WARNING: Not using getSqlTable on the Pluf_User object to + // avoid recursion. + $t_users = $this->_con->pfx.'users'; + $this->_a['views'] = array( + 'join_user' => + array( + 'join' => 'LEFT JOIN '.$t_users + .' ON '.$t_users.'.id='.$this->_con->qn('user'), + 'select' => $this->getSelect().', ' + .$t_users.'.login AS login', + 'props' => array('login' => 'login'), + ) + ); + } + + function get_email_addresses_for_user($user) + { + $addr = $user->get_idf_emailaddress_list(); + $addr[] = (object)array("address" => $user->email, "id" => -1, "user" => $user); + return $addr; + } + + function get_user_for_email_address($email) + { + $sql = new Pluf_SQL('email=%s', array($email)); + $users = Pluf::factory('Pluf_User')->getList(array('filter'=>$sql->gen())); + if ($users->count() > 0) { + return $users[0]; + } + $sql = new Pluf_SQL('address=%s', array($email)); + $matches = Pluf::factory('IDF_EmailAddress')->getList(array('filter'=>$sql->gen())); + if ($matches->count() > 0) { + return new Pluf_User($matches[0]->user); + } + return null; + } +} + diff --git a/indefero/src/IDF/FileUtil.php b/indefero/src/IDF/FileUtil.php new file mode 100644 index 0000000..222046c --- /dev/null +++ b/indefero/src/IDF/FileUtil.php @@ -0,0 +1,212 @@ +'.$i.'' + .''.self::emphasizeControlCharacters(Pluf_esc($line)).''; + $i++; + } + return Pluf_Template::markSafe(implode("\n", $table)); + } + + /** + * Find the mime type of a file. + * + * Use /etc/mime.types to find the type. + * + * @param string Filename/Filepath + * @param array Mime type found or 'application/octet-stream', basename, extension + */ + public static function getMimeType($file) + { + static $mimes = null; + if ($mimes == null) { + $mimes = array(); + $src = Pluf::f('idf_mimetypes_db', '/etc/mime.types'); + $filecontent = @file_get_contents($src); + if ($filecontent !== false) { + $mimes = preg_split("/\015\012|\015|\012/", $filecontent); + } + } + + $info = pathinfo($file); + if (isset($info['extension'])) { + foreach ($mimes as $mime) { + if ('#' != substr($mime, 0, 1)) { + $elts = preg_split('/ |\t/', $mime, -1, PREG_SPLIT_NO_EMPTY); + if (in_array($info['extension'], $elts)) { + return array($elts[0], $info['basename'], $info['extension']); + } + } + } + } else { + // we consider that if no extension and base name is all + // uppercase, then we have a text file. + if ($info['basename'] == strtoupper($info['basename'])) { + return array('text/plain', $info['basename'], 'txt'); + } + $info['extension'] = 'bin'; + } + return array('application/octet-stream', $info['basename'], $info['extension']); + } + + /** + * Find the mime type of a file using the fileinfo class. + * + * @param string Filename/Filepath + * @param string File content + * @return array Mime type found or 'application/octet-stream', basename, extension + */ + public static function getMimeTypeFromContent($file, $filedata) + { + $info = pathinfo($file); + $res = array('application/octet-stream', + $info['basename'], + isset($info['extension']) ? $info['extension'] : 'bin'); + if (function_exists('finfo_open')) { + $finfo = finfo_open(FILEINFO_MIME); + $mime = finfo_buffer($finfo, $filedata); + finfo_close($finfo); + if ($mime) { + $res[0] = $mime; + } + if (!isset($info['extension']) && $mime) { + $res[2] = (0 === strpos($mime, 'text/')) ? 'txt' : 'bin'; + } elseif (!isset($info['extension'])) { + $res[2] = 'bin'; + } + } + return $res; + } + + /** + * Splits a string into separate lines while retaining the individual + * line ending character for every line. + * + * OS 9 line endings are not supported. + * + * @param string content + * @param boolean if true, skip completely empty lines + * @return string + */ + public static function splitIntoLines($content, $skipEmpty = false) + { + $last_off = 0; + $lines = array(); + while (preg_match("/\r\n|\n/", $content, $m, PREG_OFFSET_CAPTURE, $last_off)) { + $next_off = strlen($m[0][0]) + $m[0][1]; + $line = substr($content, $last_off, $next_off - $last_off); + $last_off = $next_off; + if ($line !== $m[0][0] || !$skipEmpty) $lines[] = $line; + } + $line = substr($content, $last_off); + if ($line !== false && strlen($line) > 0) $lines[] = $line; + return $lines; + } + + /** + * This translates most of the C0 ASCII control characters into + * their visual counterparts in the 0x24## unicode plane + * (http://en.wikipedia.org/wiki/C0_and_C1_control_codes). + * + * We could add DEL (0x7F) to this set, but unfortunately this + * is not nicely mapped to 0x247F in the control plane, but 0x2421 + * and adding an if expression below just for this is a little bit + * of a hassle. And of course, the more esoteric ones from C1 are + * missing as well... + * + * @param string $content + * @return string + */ + public static function emphasizeControlCharacters($content) + { + return preg_replace( + '/([\x00-\x1F])/ue', + '"$".bin2hex("\\1").""', + $content); + } + + /** + * Find if a given mime type is a text file. + * This uses the output of the self::getMimeType function. + * + * @param array (Mime type, file name, extension) + * @return bool Is text + */ + public static function isText($fileinfo) + { + if (0 === strpos($fileinfo[0], 'text/')) { + return true; + } + $ext = 'mdtext php-dist h gitignore diff patch'; + $extra_ext = trim(Pluf::f('idf_extra_text_ext', '')); + if (!empty($extra_ext)) + $ext .= ' ' . $extra_ext; + $ext = array_merge(self::$supportedExtenstions, explode(' ' , $ext)); + return (in_array($fileinfo[2], $ext)); + } +} diff --git a/indefero/src/IDF/Forge.php b/indefero/src/IDF/Forge.php new file mode 100644 index 0000000..25416cb --- /dev/null +++ b/indefero/src/IDF/Forge.php @@ -0,0 +1,70 @@ +conf = new IDF_Gconf(); + $this->conf->setModel($this); + } + + public static function instance() { + return new IDF_Forge(); + } + + public function getProjectLabels($default = '') { + return $this->conf->getVal('project_labels', $default); + } + + public function setProjectLabels($labels) { + $this->conf->setVal('project_labels', $labels); + } + + public function setCustomForgePageEnabled($enabled) { + $this->conf->setVal('custom_forge_page_enabled', $enabled); + } + + public function isCustomForgePageEnabled($default = false) { + return $this->conf->getVal('custom_forge_page_enabled', $default); + } + + public function getCustomForgePageContent($default = '') { + return $this->conf->getVal('custom_forge_page_content', $default); + } + + public function setCustomForgePageContent($content) { + $this->conf->setVal('custom_forge_page_content', $content); + } +} diff --git a/indefero/src/IDF/Form/Admin/ForgeConf.php b/indefero/src/IDF/Form/Admin/ForgeConf.php new file mode 100644 index 0000000..669ac67 --- /dev/null +++ b/indefero/src/IDF/Form/Admin/ForgeConf.php @@ -0,0 +1,47 @@ +fields['enabled'] = new Pluf_Form_Field_Boolean( + array('required' => false, + 'label' => __('Custom forge page enabled'), + 'widget' => 'Pluf_Form_Widget_CheckboxInput', + )); + $this->fields['content'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Content'), + 'widget' => 'Pluf_Form_Widget_TextareaInput', + 'widget_attrs' => array( + 'cols' => 68, + 'rows' => 26, + ), + )); + } +} diff --git a/indefero/src/IDF/Form/Admin/LabelConf.php b/indefero/src/IDF/Form/Admin/LabelConf.php new file mode 100644 index 0000000..3230ed7 --- /dev/null +++ b/indefero/src/IDF/Form/Admin/LabelConf.php @@ -0,0 +1,62 @@ +fields['project_labels'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Predefined project labels'), + 'initial' => self::init_project_labels, + 'widget_attrs' => array('rows' => 13, + 'cols' => 75), + 'widget' => 'Pluf_Form_Widget_TextareaInput', + )); + } + + public function clean_project_labels() + { + $labels = preg_split("/\s*\n\s*/", $this->cleaned_data['project_labels'], -1, PREG_SPLIT_NO_EMPTY); + for ($i=0; $i __('git'), + 'svn' => __('Subversion'), + 'mercurial' => __('mercurial'), + 'mtn' => __('monotone'), + ); + foreach (Pluf::f('allowed_scm', array()) as $key => $class) { + $choices[$options[$key]] = $key; + } + + $this->fields['name'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Name'), + 'initial' => '', + )); + + $this->fields['private_project'] = new Pluf_Form_Field_Boolean( + array('required' => false, + 'label' => __('Private project'), + 'initial' => false, + 'widget' => 'Pluf_Form_Widget_CheckboxInput', + )); + + $this->fields['shortname'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Shortname'), + 'initial' => '', + 'help_text' => __('It must be unique for each project and composed only of letters, digits and dash (-) like "my-project".'), + )); + + $this->fields['shortdesc'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Short description'), + 'help_text' => __('A one line description of the project.'), + 'initial' => '', + 'widget_attrs' => array('size' => '35'), + )); + + $this->fields['external_project_url'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('External URL'), + 'widget_attrs' => array('size' => '35'), + 'initial' => '', + )); + + $this->fields['scm'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Repository type'), + 'initial' => 'git', + 'widget_attrs' => array('choices' => $choices), + 'widget' => 'Pluf_Form_Widget_SelectInput', + )); + + $this->fields['svn_remote_url'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Remote Subversion repository'), + 'initial' => '', + 'widget_attrs' => array('size' => '30'), + )); + + $this->fields['svn_username'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Repository username'), + 'initial' => '', + 'widget_attrs' => array('size' => '15'), + )); + + $this->fields['svn_password'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Repository password'), + 'initial' => '', + 'widget' => 'Pluf_Form_Widget_PasswordInput', + )); + + $this->fields['mtn_master_branch'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Master branch'), + 'initial' => '', + 'widget_attrs' => array('size' => '35'), + 'help_text' => __('This should be a world-wide unique identifier for your project. A reverse DNS notation like "com.my-domain.my-project" is a good idea.'), + )); + + $this->fields['owners'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Project owners'), + 'initial' => $extra['user']->login, + 'widget' => 'Pluf_Form_Widget_TextareaInput', + 'widget_attrs' => array('rows' => 5, + 'cols' => 40), + )); + + $this->fields['members'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Project members'), + 'initial' => '', + 'widget_attrs' => array('rows' => 7, + 'cols' => 40), + 'widget' => 'Pluf_Form_Widget_TextareaInput', + )); + + for ($i=1;$i<7;$i++) { + $this->fields['label'.$i] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Labels'), + 'initial' => '', + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 20, + ), + )); + } + + $projects = array('--' => '--'); + foreach (Pluf::factory('IDF_Project')->getList(array('order' => 'name ASC')) as $proj) { + $projects[$proj->name] = $proj->shortname; + } + $this->fields['template'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Project template'), + 'initial' => '--', + 'help_text' => __('Use the given project to initialize the new project. Access rights and general configuration will be taken from the template project.'), + 'widget' => 'Pluf_Form_Widget_SelectInput', + 'widget_attrs' => array('choices' => $projects), + )); + + /** + * [signal] + * + * IDF_Form_Admin_ProjectCreate::initFields + * + * [sender] + * + * IDF_Form_Admin_ProjectCreate + * + * [description] + * + * This signal allows an application to modify the form + * for the creation of a project. + * + * [parameters] + * + * array('form' => $form) + * + */ + $params = array('form' => $this); + Pluf_Signal::send('IDF_Form_Admin_ProjectCreate::initFields', + 'IDF_Form_Admin_ProjectCreate', $params); + } + + public function clean_owners() + { + return IDF_Form_MembersConf::checkBadLogins($this->cleaned_data['owners']); + } + + public function clean_members() + { + return IDF_Form_MembersConf::checkBadLogins($this->cleaned_data['members']); + } + + public function clean_svn_remote_url() + { + $this->cleaned_data['svn_remote_url'] = (!empty($this->cleaned_data['svn_remote_url'])) ? $this->cleaned_data['svn_remote_url'] : ''; + $url = trim($this->cleaned_data['svn_remote_url']); + if (strlen($url) == 0) return $url; + // we accept only starting with http(s):// to avoid people + // trying to access the local filesystem. + if (!preg_match('#^(http|https)://#', $url)) { + throw new Pluf_Form_Invalid(__('Only a remote repository available through HTTP or HTTPS is allowed. For example "http://somewhere.com/svn/trunk".')); + } + return $url; + } + + public function clean_mtn_master_branch() + { + // do not validate, but empty the field if a different + // SCM should be used + if ($this->cleaned_data['scm'] != 'mtn') + return ''; + + $mtn_master_branch = mb_strtolower($this->cleaned_data['mtn_master_branch']); + if (!preg_match('/^([\w\d]+([-][\w\d]+)*)(\.[\w\d]+([-][\w\d]+)*)*$/', + $mtn_master_branch)) { + throw new Pluf_Form_Invalid(__( + 'The master branch is empty or contains illegal characters, '. + 'please use only letters, digits, dashes and dots as separators.' + )); + } + + $sql = new Pluf_SQL('vkey=%s AND vdesc=%s', + array('mtn_master_branch', $mtn_master_branch)); + $l = Pluf::factory('IDF_Conf')->getList(array('filter'=>$sql->gen())); + if ($l->count() > 0) { + throw new Pluf_Form_Invalid(__( + 'This master branch is already used. Please select another one.' + )); + } + + return $mtn_master_branch; + } + + public function clean_shortname() + { + $shortname = mb_strtolower($this->cleaned_data['shortname']); + if (preg_match('/[^\-A-Za-z0-9]/', $shortname)) { + throw new Pluf_Form_Invalid(__('This shortname contains illegal characters, please use only letters, digits and dash (-).')); + } + if (mb_substr($shortname, 0, 1) == '-') { + throw new Pluf_Form_Invalid(__('The shortname cannot start with the dash (-) character.')); + } + if (mb_substr($shortname, -1) == '-') { + throw new Pluf_Form_Invalid(__('The shortname cannot end with the dash (-) character.')); + } + $sql = new Pluf_SQL('shortname=%s', array($shortname)); + $l = Pluf::factory('IDF_Project')->getList(array('filter'=>$sql->gen())); + if ($l->count() > 0) { + throw new Pluf_Form_Invalid(__('This shortname is already used. Please select another one.')); + } + return $shortname; + } + + public function clean_external_project_url() + { + return IDF_Form_ProjectConf::checkWebURL($this->cleaned_data['external_project_url']); + } + + public function clean() + { + if ($this->cleaned_data['scm'] != 'svn') { + foreach (array('svn_remote_url', 'svn_username', 'svn_password') + as $key) { + $this->cleaned_data[$key] = ''; + } + } + + if ($this->cleaned_data['scm'] != 'mtn') { + $this->cleaned_data['mtn_master_branch'] = ''; + } + + /** + * [signal] + * + * IDF_Form_Admin_ProjectCreate::clean + * + * [sender] + * + * IDF_Form_Admin_ProjectCreate + * + * [description] + * + * This signal allows an application to clean the form + * for the creation of a project. + * + * [parameters] + * + * array('cleaned_data' => $cleaned_data) + * + */ + $params = array('cleaned_data' => $this->cleaned_data); + Pluf_Signal::send('IDF_Form_Admin_ProjectCreate::clean', + 'IDF_Form_Admin_ProjectCreate', $params); + return $this->cleaned_data; + } + + public function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save the model from an invalid form.')); + } + + // Add a tag for each label + $tagids = array(); + for ($i=1;$i<7;$i++) { + if (strlen($this->cleaned_data['label'.$i]) > 0) { + if (strpos($this->cleaned_data['label'.$i], ':') !== false) { + list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2); + list($class, $name) = array(trim($class), trim($name)); + } else { + $class = 'Other'; + $name = trim($this->cleaned_data['label'.$i]); + } + $tag = IDF_Tag::addGlobal($name, $class); + $tagids[] = $tag->id; + } + } + + $project = new IDF_Project(); + $project->name = $this->cleaned_data['name']; + $project->shortname = $this->cleaned_data['shortname']; + $project->shortdesc = $this->cleaned_data['shortdesc']; + + $tagids = array(); + if ($this->cleaned_data['template'] != '--') { + // Find the template project + $sql = new Pluf_SQL('shortname=%s', + array($this->cleaned_data['template'])); + $tmpl = Pluf::factory('IDF_Project')->getOne(array('filter' => $sql->gen())); + $project->private = $tmpl->private; + $project->description = $tmpl->description; + + foreach ($tmpl->get_tags_list() as $tag) { + $tagids[] = $tag->id; + } + } else { + $project->private = $this->cleaned_data['private_project']; + $project->description = __('Click on the Project Management tab to set the description of your project.'); + + // Add a tag for each label + for ($i=1;$i<7;$i++) { + if (strlen($this->cleaned_data['label'.$i]) > 0) { + if (strpos($this->cleaned_data['label'.$i], ':') !== false) { + list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2); + list($class, $name) = array(trim($class), trim($name)); + } else { + $class = 'Other'; + $name = trim($this->cleaned_data['label'.$i]); + } + $tag = IDF_Tag::addGlobal($name, $class); + $tagids[] = $tag->id; + } + } + } + $project->create(); + $project->batchAssoc('IDF_Tag', $tagids); + + $conf = new IDF_Conf(); + $conf->setProject($project); + + if ($this->cleaned_data['template'] != '--') { + $tmplconf = new IDF_Conf(); + $tmplconf->setProject($tmpl); + + $allKeys = $tmplconf->getKeys(); + $scm = $this->cleaned_data['scm']; + $ignoreKeys = array('scm', 'external_project_url', 'logo'); + + // copy over all existing variables, except scm-related data and + // the project url / logo + foreach ($allKeys as $key) { + if (in_array($key, $ignoreKeys) || strpos($key, $scm.'_') === 0) { + continue; + } + $conf->setVal($key, $tmplconf->getVal($key)); + } + } + + $keys = array( + 'scm', 'svn_remote_url', 'svn_username', + 'svn_password', 'mtn_master_branch', + 'external_project_url' + ); + foreach ($keys as $key) { + $this->cleaned_data[$key] = !empty($this->cleaned_data[$key]) ? + $this->cleaned_data[$key] : ''; + $conf->setVal($key, $this->cleaned_data[$key]); + } + $project->created(); + + if ($this->cleaned_data['template'] == '--') { + IDF_Form_MembersConf::updateMemberships($project, + $this->cleaned_data); + } else { + // Get the membership of the template $tmpl + IDF_Form_MembersConf::updateMemberships($project, + $tmpl->getMembershipData('string')); + } + $project->membershipsUpdated(); + return $project; + } + + /** + * Check that the template project exists. + */ + public function clean_template() + { + if ($this->cleaned_data['template'] == '--') { + return $this->cleaned_data['template']; + } + $sql = new Pluf_SQL('shortname=%s', array($this->cleaned_data['template'])); + if (Pluf::factory('IDF_Project')->getOne(array('filter' => $sql->gen())) == null) { + throw new Pluf_Form_Invalid(__('This project is not available.')); + } + return $this->cleaned_data['template']; + } +} + + diff --git a/indefero/src/IDF/Form/Admin/ProjectDelete.php b/indefero/src/IDF/Form/Admin/ProjectDelete.php new file mode 100644 index 0000000..4b7cb5d --- /dev/null +++ b/indefero/src/IDF/Form/Admin/ProjectDelete.php @@ -0,0 +1,88 @@ +project = $extra['project']; + $this->user = $extra['user']; + $this->fields['code'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Confirmation code'), + 'initial' => '', + )); + $this->fields['agree'] = new Pluf_Form_Field_Boolean( + array('required' => true, + 'label' => __('I have made a backup of all the important data of this project.'), + 'initial' => '', + )); + } + + public function clean_code() + { + $code = $this->cleaned_data['code']; + if ($code != $this->getCode()) { + throw new Pluf_Form_Invalid(__('The confirmation code does not match. Please provide a valid confirmation code to delete the project.')); + } + return $code; + } + + public function clean_agree() + { + if (!$this->cleaned_data['agree']) { + throw new Pluf_Form_Invalid(__('Sorry, you really need to backup your data before deletion.')); + } + return $this->cleaned_data['agree']; + } + + public function getCode() + { + return substr(md5(Pluf::f('secret_key').$this->user->id.'.'.$this->project->id), + 0, 8); + } + + + public function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save the model from an invalid form.')); + } + // So, we drop the project, it will cascade and delete all the + // elements of the project. For large projects, this may use + // quite some memory. + $this->project->delete(); + return true; + } +} + + diff --git a/indefero/src/IDF/Form/Admin/ProjectUpdate.php b/indefero/src/IDF/Form/Admin/ProjectUpdate.php new file mode 100644 index 0000000..f579381 --- /dev/null +++ b/indefero/src/IDF/Form/Admin/ProjectUpdate.php @@ -0,0 +1,196 @@ +project = $extra['project']; + $members = $this->project->getMembershipData('string'); + $conf = $this->project->getConf(); + + $this->fields['name'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Name'), + 'initial' => $this->project->name, + )); + + $this->fields['shortdesc'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Short description'), + 'help_text' => __('A one line description of the project.'), + 'initial' => $this->project->shortdesc, + 'widget_attrs' => array('size' => '35'), + )); + + $this->fields['external_project_url'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('External URL'), + 'widget_attrs' => array('size' => '35'), + 'initial' => $conf->getVal('external_project_url'), + )); + + if ($this->project->getConf()->getVal('scm') == 'mtn') { + $this->fields['mtn_master_branch'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Master branch'), + 'initial' => $conf->getVal('mtn_master_branch'), + 'widget_attrs' => array('size' => '35'), + 'help_text' => __('This should be a world-wide unique identifier for your project. A reverse DNS notation like "com.my-domain.my-project" is a good idea.'), + )); + } + + $tags = $this->project->get_tags_list(); + for ($i=1;$i<7;$i++) { + $initial = ''; + if (isset($tags[$i-1])) { + if ($tags[$i-1]->class != 'Other') { + $initial = (string) $tags[$i-1]; + } else { + $initial = $tags[$i-1]->name; + } + } + $this->fields['label'.$i] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Labels'), + 'initial' => $initial, + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 20, + ), + )); + } + $this->fields['owners'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Project owners'), + 'initial' => $members['owners'], + 'widget' => 'Pluf_Form_Widget_TextareaInput', + 'widget_attrs' => array('rows' => 5, + 'cols' => 40), + )); + $this->fields['members'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Project members'), + 'initial' => $members['members'], + 'widget_attrs' => array('rows' => 7, + 'cols' => 40), + 'widget' => 'Pluf_Form_Widget_TextareaInput', + )); + } + + public function clean_mtn_master_branch() + { + $mtn_master_branch = mb_strtolower($this->cleaned_data['mtn_master_branch']); + if (!preg_match('/^([\w\d]+([-][\w\d]+)*)(\.[\w\d]+([-][\w\d]+)*)*$/', + $mtn_master_branch)) { + throw new Pluf_Form_Invalid(__( + 'The master branch is empty or contains illegal characters, '. + 'please use only letters, digits, dashes and dots as separators.' + )); + } + + $sql = new Pluf_SQL('vkey=%s AND vdesc=%s AND project!=%s', + array('mtn_master_branch', $mtn_master_branch, + (string)$this->project->id)); + $l = Pluf::factory('IDF_Conf')->getList(array('filter'=>$sql->gen())); + if ($l->count() > 0) { + throw new Pluf_Form_Invalid(__( + 'This master branch is already used. Please select another one.' + )); + } + + return $mtn_master_branch; + } + + public function clean_owners() + { + return IDF_Form_MembersConf::checkBadLogins($this->cleaned_data['owners']); + } + + public function clean_members() + { + return IDF_Form_MembersConf::checkBadLogins($this->cleaned_data['members']); + } + + public function clean_external_project_url() + { + return IDF_Form_ProjectConf::checkWebURL($this->cleaned_data['external_project_url']); + } + + public function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save the model from an invalid form.')); + } + + // Add a tag for each label + $tagids = array(); + for ($i=1;$i<7;$i++) { + if (strlen($this->cleaned_data['label'.$i]) > 0) { + if (strpos($this->cleaned_data['label'.$i], ':') !== false) { + list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2); + list($class, $name) = array(trim($class), trim($name)); + } else { + $class = 'Other'; + $name = trim($this->cleaned_data['label'.$i]); + } + $tag = IDF_Tag::addGlobal($name, $class); + $tagids[] = $tag->id; + } + } + $this->project->batchAssoc('IDF_Tag', $tagids); + + IDF_Form_MembersConf::updateMemberships($this->project, + $this->cleaned_data); + $this->project->membershipsUpdated(); + + $this->project->name = $this->cleaned_data['name']; + $this->project->shortdesc = $this->cleaned_data['shortdesc']; + $this->project->update(); + + $conf = $this->project->getConf(); + $keys = array('mtn_master_branch', 'external_project_url'); + foreach ($keys as $key) { + if (array_key_exists($key, $this->cleaned_data)) { + if (!empty($this->cleaned_data[$key])) { + $conf->setVal($key, $this->cleaned_data[$key]); + } + else { + $conf->delVal($key); + } + } + } + } +} + + diff --git a/indefero/src/IDF/Form/Admin/UserCreate.php b/indefero/src/IDF/Form/Admin/UserCreate.php new file mode 100644 index 0000000..cda4431 --- /dev/null +++ b/indefero/src/IDF/Form/Admin/UserCreate.php @@ -0,0 +1,215 @@ +request = $extra['request']; + $this->fields['first_name'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('First name'), + 'initial' => '', + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 15, + ), + )); + $this->fields['last_name'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Last name'), + 'initial' => '', + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 20, + ), + )); + + $this->fields['login'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Login'), + 'max_length' => 15, + 'min_length' => 3, + 'initial' => '', + 'help_text' => __('The login must be between 3 and 15 characters long and contains only letters and digits.'), + 'widget_attrs' => array( + 'maxlength' => 15, + 'size' => 10, + ), + )); + + $this->fields['email'] = new Pluf_Form_Field_Email( + array('required' => true, + 'label' => __('Email'), + 'initial' => '', + 'help_text' => __('Double check the email address as the password is sent directly to the user.'), + )); + + $this->fields['language'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Language'), + 'initial' => '', + 'widget' => 'Pluf_Form_Widget_SelectInput', + 'widget_attrs' => array( + 'choices' => + Pluf_L10n::getInstalledLanguages() + ), + )); + + $this->fields['public_key'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Add a public key'), + 'initial' => '', + 'widget_attrs' => array('rows' => 3, + 'cols' => 40), + 'widget' => 'Pluf_Form_Widget_TextareaInput', + 'help_text' => __('Paste a SSH or monotone public key. Be careful to not provide your private key here!') + )); + } + + /** + * Save the model in the database. + * + * @param bool Commit in the database or not. If not, the object + * is returned but not saved in the database. + * @return Object Model with data set from the form. + */ + function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save the model from an invalid form.')); + } + $password = Pluf_Utils::getPassword(); + $user = new Pluf_User(); + $user->setFromFormData($this->cleaned_data); + $user->active = true; + $user->staff = false; + $user->administrator = false; + $user->setPassword(base64_encode(sha1($password,TRUE))); + $user->create(); + /** + * [signal] + * + * Pluf_User::passwordUpdated + * + * [sender] + * + * IDF_Form_Admin_UserCreate + * + * [description] + * + * This signal is sent when a user is created + * by the staff. + * + * [parameters] + * + * array('user' => $user) + * + */ + $params = array('user' => $user); + Pluf_Signal::send('Pluf_User::passwordUpdated', + 'IDF_Form_Admin_UserCreate', $params); + // Create the public key as needed + if ('' !== $this->cleaned_data['public_key']) { + $key = new IDF_Key(); + $key->user = $user; + $key->content = $this->cleaned_data['public_key']; + $key->create(); + } + // Send an email to the user with the password + Pluf::loadFunction('Pluf_HTTP_URL_urlForView'); + $url = Pluf::f('url_base').Pluf_HTTP_URL_urlForView('IDF_Views::login', array(), array(), false); + $context = new Pluf_Template_Context( + array('password' => Pluf_Template::markSafe($password), + 'user' => $user, + 'url' => Pluf_Template::markSafe($url), + 'admin' => $this->request->user, + )); + $tmpl = new Pluf_Template('idf/gadmin/users/createuser-email.txt'); + $text_email = $tmpl->render($context); + $email = new Pluf_Mail(Pluf::f('from_email'), $user->email, + __('Your details to access your forge.')); + $email->addTextMessage($text_email); + $email->sendMail(); + return $user; + } + + function clean_last_name() + { + $last_name = trim($this->cleaned_data['last_name']); + if ($last_name == mb_strtoupper($last_name)) { + return mb_convert_case(mb_strtolower($last_name), + MB_CASE_TITLE, 'UTF-8'); + } + return $last_name; + } + + function clean_first_name() + { + $first_name = trim($this->cleaned_data['first_name']); + if ($first_name == mb_strtoupper($first_name)) { + return mb_convert_case(mb_strtolower($first_name), + MB_CASE_TITLE, 'UTF-8'); + } + return $first_name; + } + + function clean_email() + { + $this->cleaned_data['email'] = mb_strtolower(trim($this->cleaned_data['email'])); + $guser = new Pluf_User(); + $sql = new Pluf_SQL('email=%s', array($this->cleaned_data['email'])); + if ($guser->getCount(array('filter' => $sql->gen())) > 0) { + throw new Pluf_Form_Invalid(sprintf(__('The email "%s" is already used.'), $this->cleaned_data['email'])); + } + return $this->cleaned_data['email']; + } + + public function clean_login() + { + $this->cleaned_data['login'] = mb_strtolower(trim($this->cleaned_data['login'])); + if (preg_match('/[^a-z0-9]/', $this->cleaned_data['login'])) { + throw new Pluf_Form_Invalid(sprintf(__('The login "%s" can only contain letters and digits.'), $this->cleaned_data['login'])); + } + $guser = new Pluf_User(); + $sql = new Pluf_SQL('login=%s', $this->cleaned_data['login']); + if ($guser->getCount(array('filter' => $sql->gen())) > 0) { + throw new Pluf_Form_Invalid(sprintf(__('The login "%s" is already used, please find another one.'), $this->cleaned_data['login'])); + } + return $this->cleaned_data['login']; + } + + public function clean_public_key() + { + $this->cleaned_data['public_key'] = + IDF_Form_UserAccount::checkPublicKey($this->cleaned_data['public_key']); + + return $this->cleaned_data['public_key']; + } +} diff --git a/indefero/src/IDF/Form/Admin/UserUpdate.php b/indefero/src/IDF/Form/Admin/UserUpdate.php new file mode 100644 index 0000000..fa2da76 --- /dev/null +++ b/indefero/src/IDF/Form/Admin/UserUpdate.php @@ -0,0 +1,321 @@ +user = $extra['user']; + $user_data = IDF_UserData::factory($this->user); + + $this->fields['first_name'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('First name'), + 'initial' => $this->user->first_name, + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 15, + ), + )); + $this->fields['last_name'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Last name'), + 'initial' => $this->user->last_name, + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 20, + ), + )); + + $this->fields['email'] = new Pluf_Form_Field_Email( + array('required' => true, + 'label' => __('Email'), + 'initial' => $this->user->email, + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 20, + ), + )); + + $this->fields['language'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Language'), + 'initial' => $this->user->language, + 'widget' => 'Pluf_Form_Widget_SelectInput', + 'widget_attrs' => array( + 'choices' => + Pluf_L10n::getInstalledLanguages() + ), + )); + + $this->fields['password'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Password'), + 'initial' => '', + 'widget' => 'Pluf_Form_Widget_PasswordInput', + 'help_text' => Pluf_Template::markSafe(__('Leave blank if you do not want to change the password.').'
'.__('The password must be hard for other people to guess, but easy for the user to remember.')), + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 15, + ), + )); + $this->fields['password2'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Confirm password'), + 'initial' => '', + 'widget' => 'Pluf_Form_Widget_PasswordInput', + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 15, + ), + )); + + $this->fields['description'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Description'), + 'initial' => $user_data->description, + 'widget_attrs' => array('rows' => 3, + 'cols' => 40), + 'widget' => 'Pluf_Form_Widget_TextareaInput', + )); + + $this->fields['twitter'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Twitter username'), + 'initial' => $user_data->twitter, + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 15, + ), + )); + + $this->fields['public_email'] = new Pluf_Form_Field_Email( + array('required' => false, + 'label' => __('Public email address'), + 'initial' => $user_data->public_email, + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 15, + ), + )); + + $this->fields['website'] = new Pluf_Form_Field_Url( + array('required' => false, + 'label' => __('Website URL'), + 'initial' => $user_data->website, + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 15, + ), + )); + + $this->fields['custom_avatar'] = new Pluf_Form_Field_File( + array('required' => false, + 'label' => __('Upload custom avatar'), + 'initial' => '', + 'max_size' => Pluf::f('max_upload_size', 2097152), + 'move_function_params' => array('upload_path' => Pluf::f('upload_path').'/avatars', + 'upload_path_create' => true, + 'upload_overwrite' => true, + 'file_name' => 'user_'.$this->user->id.'_%s'), + 'help_text' => __('An image file with a width and height not larger than 60 pixels (bigger images are scaled down).'), + )); + + $this->fields['remove_custom_avatar'] = new Pluf_Form_Field_Boolean( + array('required' => false, + 'label' => __('Remove custom avatar'), + 'initial' => false, + 'widget' => 'Pluf_Form_Widget_CheckboxInput', + 'widget_attrs' => array(), + 'help_text' => __('Tick this to delete the custom avatar.'), + )); + + if ($extra['request']->user->administrator) { + $this->fields['staff'] = new Pluf_Form_Field_Boolean( + array('required' => false, + 'label' => __('Staff'), + 'initial' => $this->user->staff, + 'widget' => 'Pluf_Form_Widget_CheckboxInput', + 'help_text' => __('If you give staff rights to a user, you really need to trust him.'), + )); + } + + $attrs = ($extra['request']->user->id == $this->user->id) ? + array('readonly' => 'readonly') : array(); + $this->fields['active'] = new Pluf_Form_Field_Boolean( + array('required' => false, + 'label' => __('Active'), + 'initial' => $this->user->active, + 'widget' => 'Pluf_Form_Widget_CheckboxInput', + 'widget_attrs' => $attrs, + 'help_text' => __('If the user is not getting the confirmation email or is abusing the system, you can directly enable or disable their account here.'), + )); + } + + + /** + * Save the model in the database. + * + * @param bool Commit in the database or not. If not, the object + * is returned but not saved in the database. + * @return Object Model with data set from the form. + */ + function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save the model from an invalid form.')); + } + unset($this->cleaned_data['password2']); + $update_pass = false; + if (strlen($this->cleaned_data['password']) == 0) { + unset($this->cleaned_data['password']); + } else { + $update_pass = true; + } + $this->user->setFromFormData($this->cleaned_data); + + if ($commit) { + $this->user->update(); + + // FIXME: go the extra mile and check the input lengths for + // all fields here! + // FIXME: this is all doubled in UserAccount! + + $user_data = IDF_UserData::factory($this->user); + + // Add or remove avatar - we need to do this here because every + // single setter directly leads to a save in the database + if ($user_data->avatar != '' && + ($this->cleaned_data['remove_custom_avatar'] == 1 || + $this->cleaned_data['custom_avatar'] != '')) { + $avatar_path = Pluf::f('upload_path').'/avatars/'.basename($user_data->avatar); + if (basename($avatar_path) != '' && is_file($avatar_path)) { + unlink($avatar_path); + } + $user_data->avatar = ''; + } + + if ($this->cleaned_data['custom_avatar'] != '') { + $user_data->avatar = $this->cleaned_data['custom_avatar']; + } + + $user_data->description = $this->cleaned_data['description']; + $user_data->twitter = $this->cleaned_data['twitter']; + $user_data->public_email = $this->cleaned_data['public_email']; + $user_data->website = $this->cleaned_data['website']; + + if ($update_pass) { + /** + * [signal] + * + * Pluf_User::passwordUpdated + * + * [sender] + * + * IDF_Form_UserAccount + * + * [description] + * + * This signal is sent when the user updated his + * password from his account page. + * + * [parameters] + * + * array('user' => $user) + * + */ + $params = array('user' => $this->user); + Pluf_Signal::send('Pluf_User::passwordUpdated', + 'IDF_Form_Admin_UserUpdate', $params); + } + } + return $this->user; + } + + function clean_last_name() + { + $last_name = trim($this->cleaned_data['last_name']); + if ($last_name == mb_strtoupper($last_name)) { + return mb_convert_case(mb_strtolower($last_name), + MB_CASE_TITLE, 'UTF-8'); + } + return $last_name; + } + + function clean_first_name() + { + $first_name = trim($this->cleaned_data['first_name']); + if ($first_name == '---') { + throw new Pluf_Form_Invalid(__('--- is not a valid first name.')); + } + if ($first_name == mb_strtoupper($first_name)) { + $first_name = mb_convert_case(mb_strtolower($first_name), + MB_CASE_TITLE, 'UTF-8'); + } + return $first_name; + } + + function clean_email() + { + $email = mb_strtolower(trim($this->cleaned_data['email'])); + $sql = new Pluf_SQL('email=%s AND id!=%s', + array($email, $this->user->id)); + $users = Pluf::factory('Pluf_User')->getList(array('filter'=>$sql->gen())); + if ($users->count() > 0) { + throw new Pluf_Form_Invalid(__('A user with this email already exists, please provide another email address.')); + } + return $email; + } + + function clean_custom_avatar() + { + // Just png, jpeg/jpg or gif + if (!preg_match('/\.(png|jpg|jpeg|gif)$/i', $this->cleaned_data['custom_avatar']) && + $this->cleaned_data['custom_avatar'] != '') { + @unlink(Pluf::f('upload_path').'/avatars/'.$this->cleaned_data['custom_avatar']); + throw new Pluf_Form_Invalid(__('For security reason, you cannot upload a file with this extension.')); + } + return $this->cleaned_data['custom_avatar']; + } + + /** + * Check to see if the two passwords are the same. + */ + public function clean() + { + if (!isset($this->errors['password']) + && !isset($this->errors['password2'])) { + $password1 = $this->cleaned_data['password']; + $password2 = $this->cleaned_data['password2']; + if ($password1 != $password2) { + throw new Pluf_Form_Invalid(__('The passwords do not match. Please give them again.')); + } + } + return $this->cleaned_data; + } +} diff --git a/indefero/src/IDF/Form/Field/EmailList.php b/indefero/src/IDF/Form/Field/EmailList.php new file mode 100644 index 0000000..ebb58bf --- /dev/null +++ b/indefero/src/IDF/Form/Field/EmailList.php @@ -0,0 +1,51 @@ +empty_values)) { + $value = ''; + } + if ($value == '') { + return $value; + } + $emails = preg_split('/\s*,\s*/', $value, -1, PREG_SPLIT_NO_EMPTY); + foreach ($emails as $email) { + if (!Pluf_Utils::isValidEmail($email)) { + throw new Pluf_Form_Invalid(__( + 'Please enter one or more valid email addresses.' + )); + } + } + return implode(',', $emails); + } +} diff --git a/indefero/src/IDF/Form/IssueCreate.php b/indefero/src/IDF/Form/IssueCreate.php new file mode 100644 index 0000000..f6b2d84 --- /dev/null +++ b/indefero/src/IDF/Form/IssueCreate.php @@ -0,0 +1,473 @@ +user = $extra['user']; + $this->project = $extra['project']; + if ($this->user->hasPerm('IDF.project-owner', $this->project) + or $this->user->hasPerm('IDF.project-member', $this->project)) { + $this->show_full = true; + } + $this->relation_types = $this->project->getRelationsFromConfig(); + + $contentTemplate = $this->project->getConf()->getVal( + 'labels_issue_template', IDF_Form_IssueTrackingConf::init_template + ); + + $this->fields['summary'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Summary'), + 'initial' => '', + 'widget_attrs' => array( + 'maxlength' => 200, + 'size' => 67, + ), + )); + $this->fields['content'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Description'), + 'initial' => $contentTemplate, + 'widget' => 'Pluf_Form_Widget_TextareaInput', + 'widget_attrs' => array( + 'cols' => 58, + 'rows' => 13, + ), + )); + $upload_path = Pluf::f('upload_issue_path', false); + if (false === $upload_path) { + throw new Pluf_Exception_SettingError(__('The "upload_issue_path" configuration variable was not set.')); + } + $md5 = md5(rand().microtime().Pluf_Utils::getRandomString()); + // We add .dummy to try to mitigate security issues in the + // case of someone allowing the upload path to be accessible + // to everybody. + for ($i=1;$i<4;$i++) { + $filename = substr($md5, 0, 2).'/'.substr($md5, 2, 2).'/'.substr($md5, 4).'/%s.dummy'; + $this->fields['attachment'.$i] = new Pluf_Form_Field_File( + array('required' => false, + 'label' => __('Attach a file'), + 'move_function_params' => + array('upload_path' => $upload_path, + 'upload_path_create' => true, + 'file_name' => $filename, + ) + ) + ); + } + + if ($this->show_full) { + $this->fields['status'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Status'), + 'initial' => 'New', + 'widget_attrs' => array( + 'maxlength' => 20, + 'size' => 15, + ), + )); + $this->fields['owner'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Owner'), + 'initial' => '', + 'widget_attrs' => array( + 'maxlength' => 20, + 'size' => 15, + ), + )); + + $this->fields['relation_type0'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('This issue'), + 'initial' => current($this->relation_types), + 'widget_attrs' => array('size' => 15), + )); + + $this->fields['relation_issue0'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => null, + 'initial' => '', + 'widget_attrs' => array('size' => 10), + )); + + /* + * get predefined tags for issues from current project + * + * first Type:<...> and Priority:<...> will be used + * + */ + $predefined = preg_split("/[\r\n]+/", $extra['project']->getConf()->getVal( + 'labels_issue_predefined' + )); + $predefined_type = 'Type:Defect'; + foreach ($predefined as $tag) { + if (strpos($tag, 'Type:') === 0) { + $predefined_type = explode('=', $tag, 2); + $predefined_type = trim($predefined_type[0]); + break; + } + } + $predefined_priority = 'Priority:Medium'; + foreach ($predefined as $tag) { + if (strpos($tag, 'Priority:') === 0) { + $predefined_priority = explode('=', $tag, 2); + $predefined_priority = trim($predefined_priority[0]); + break; + } + } + + for ($i=1;$i<7;$i++) { + $initial = ''; + switch ($i) { + case 1: + $initial = $predefined_type; + break; + case 2: + $initial = $predefined_priority; + break; + } + $this->fields['label'.$i] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Labels'), + 'initial' => $initial, + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 20, + ), + )); + } + } + } + + /** + * Validate the interconnection in the form. + */ + public function clean() + { + // We need to check that no label with the 'Status' class is + // given. + if (!$this->show_full) { + return $this->cleaned_data; + } + $conf = new IDF_Conf(); + $conf->setProject($this->project); + $onemax = array(); + foreach (explode(',', $conf->getVal('labels_issue_one_max', IDF_Form_IssueTrackingConf::init_one_max)) as $class) { + if (trim($class) != '') { + $onemax[] = mb_strtolower(trim($class)); + } + } + $count = array(); + for ($i=1;$i<7;$i++) { + $this->cleaned_data['label'.$i] = trim($this->cleaned_data['label'.$i]); + if (strpos($this->cleaned_data['label'.$i], ':') !== false) { + list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2); + list($class, $name) = array(mb_strtolower(trim($class)), + trim($name)); + } else { + $class = 'other'; + $name = $this->cleaned_data['label'.$i]; + } + if ($class == 'status') { + if (!isset($this->errors['label'.$i])) $this->errors['label'.$i] = array(); + $this->errors['label'.$i][] = __('You cannot add a label with the "Status" prefix to an issue.'); + throw new Pluf_Form_Invalid(__('You provided an invalid label.')); + } + if (!isset($count[$class])) $count[$class] = 1; + else $count[$class] += 1; + if (in_array($class, $onemax) and $count[$class] > 1) { + if (!isset($this->errors['label'.$i])) $this->errors['label'.$i] = array(); + $this->errors['label'.$i][] = sprintf(__('You cannot provide more than one label from the %s class to an issue.'), $class); + throw new Pluf_Form_Invalid(__('You provided an invalid label.')); + } + } + return $this->cleaned_data; + } + + function clean_content() + { + $content = trim($this->cleaned_data['content']); + if (strlen($content) == 0) { + throw new Pluf_Form_Invalid(__('You need to provide a description of the issue.')); + } + return $content; + } + + function clean_status() + { + // Check that the status is in the list of official status + $tags = $this->project->getTagsFromConfig('labels_issue_open', + IDF_Form_IssueTrackingConf::init_open, + 'Status'); + $tags = array_merge($this->project->getTagsFromConfig('labels_issue_closed', + IDF_Form_IssueTrackingConf::init_closed, + 'Status') + , $tags); + $found = false; + foreach ($tags as $tag) { + if ($tag->name == trim($this->cleaned_data['status'])) { + $found = true; + break; + } + } + if (!$found) { + throw new Pluf_Form_Invalid(__('You provided an invalid status.')); + } + return $this->cleaned_data['status']; + } + + // this method is not called from Pluf_Form directly, but shared for + // among all similar fields + function clean_relation_type($value) + { + $relation_type = trim($value); + if (empty($relation_type)) + return ''; + + $found = false; + foreach ($this->relation_types as $type) { + if ($type == $relation_type) { + $found = true; + break; + } + } + if (!$found) { + throw new Pluf_Form_Invalid(__('You provided an invalid relation type.')); + } + return $relation_type; + } + + function clean_relation_type0() + { + return $this->clean_relation_type($this->cleaned_data['relation_type0']); + } + + // this method is not called from Pluf_Form directly, but shared for + // among all similar fields + function clean_relation_issue($value) + { + $issues = trim($value); + if (empty($issues)) + return ''; + + $issue_ids = preg_split('/\s*,\s*/', $issues, -1, PREG_SPLIT_NO_EMPTY); + foreach ($issue_ids as $issue_id) { + if (!ctype_digit($issue_id) || (int)$issue_id < 1) { + throw new Pluf_Form_Invalid(sprintf( + __('The value "%s" is not a valid issue id.'), $issue_id + )); + } + $issue = new IDF_Issue($issue_id); + if ($issue->id != $issue_id || $issue->project != $this->project->id) { + throw new Pluf_Form_Invalid(sprintf( + __('The issue "%s" does not exist.'), $issue_id + )); + } + } + + return implode(', ', $issue_ids); + } + + function clean_relation_issue0() + { + return $this->clean_relation_issue($this->cleaned_data['relation_issue0']); + } + + /** + * Clean the attachments post failure. + */ + function failed() + { + $upload_path = Pluf::f('upload_issue_path', false); + if ($upload_path == false) return; + for ($i=1;$i<4;$i++) { + if (!empty($this->cleaned_data['attachment'.$i]) and + file_exists($upload_path.'/'.$this->cleaned_data['attachment'.$i])) { + @unlink($upload_path.'/'.$this->cleaned_data['attachment'.$i]); + } + } + } + + /** + * Save the model in the database. + * + * @param bool Commit in the database or not. If not, the object + * is returned but not saved in the database. + * @return Object Model with data set from the form. + */ + function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save the model from an invalid form.')); + } + // Add a tag for each label + $tags = array(); + if ($this->show_full) { + for ($i=1;$i<7;$i++) { + if (strlen($this->cleaned_data['label'.$i]) > 0) { + if (strpos($this->cleaned_data['label'.$i], ':') !== false) { + list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2); + list($class, $name) = array(trim($class), trim($name)); + } else { + $class = 'Other'; + $name = trim($this->cleaned_data['label'.$i]); + } + $tags[] = IDF_Tag::add($name, $this->project, $class); + } + } + } else { + $tags[] = IDF_Tag::add('Medium', $this->project, 'Priority'); + $tags[] = IDF_Tag::add('Defect', $this->project, 'Type'); + } + // Create the issue + $issue = new IDF_Issue(); + $issue->project = $this->project; + $issue->submitter = $this->user; + if ($this->show_full) { + $issue->status = IDF_Tag::add(trim($this->cleaned_data['status']), $this->project, 'Status'); + $issue->owner = self::findUser($this->cleaned_data['owner']); + } else { + $_t = $this->project->getTagIdsByStatus('open'); + $issue->status = new IDF_Tag($_t[0]); // first one is the default + $issue->owner = null; + } + $issue->summary = trim($this->cleaned_data['summary']); + $issue->create(); + foreach ($tags as $tag) { + $issue->setAssoc($tag); + } + // add relations (if any) + if (!empty($this->cleaned_data['relation_type0'])) { + $verb = $this->cleaned_data['relation_type0']; + $other_verb = $this->relation_types[$verb]; + $related_issues = preg_split('/\s*,\s*/', $this->cleaned_data['relation_issue0'], -1, PREG_SPLIT_NO_EMPTY); + + foreach ($related_issues as $related_issue_id) { + $related_issue = new IDF_Issue($related_issue_id); + $rel = new IDF_IssueRelation(); + $rel->issue = $issue; + $rel->verb = $verb; + $rel->other_issue = $related_issue; + $rel->submitter = $this->user; + $rel->create(); + + $other_rel = new IDF_IssueRelation(); + $other_rel->issue = $related_issue; + $other_rel->verb = $other_verb; + $other_rel->other_issue = $issue; + $other_rel->submitter = $this->user; + $other_rel->create(); + } + } + + // add the first comment + $comment = new IDF_IssueComment(); + $comment->issue = $issue; + $comment->content = $this->cleaned_data['content']; + $comment->submitter = $this->user; + $comment->create(); + // If we have a file, create the IDF_IssueFile and attach + // it to the comment. + $created_files = array(); + for ($i=1;$i<4;$i++) { + if ($this->cleaned_data['attachment'.$i]) { + $file = new IDF_IssueFile(); + $file->attachment = $this->cleaned_data['attachment'.$i]; + $file->submitter = $this->user; + $file->comment = $comment; + $file->create(); + $created_files[] = $file; + } + } + /** + * [signal] + * + * IDF_Issue::create + * + * [sender] + * + * IDF_Form_IssueCreate + * + * [description] + * + * This signal allows an application to perform a set of tasks + * just after the creation of an issue. The comment contains + * the description of the issue. + * + * [parameters] + * + * array('issue' => $issue, + * 'comment' => $comment, + * 'files' => $attached_files); + * + */ + $params = array('issue' => $issue, + 'comment' => $comment, + 'files' => $created_files); + Pluf_Signal::send('IDF_Issue::create', 'IDF_Form_IssueCreate', + $params); + return $issue; + } + + /** + * Based on the given string, try to find the matching user. + * + * Search order is: email, login, last_name. + * + * If no user found, simply returns null. + * + * @param string User + * @return Pluf_User or null + */ + public static function findUser($string) + { + $string = trim($string); + if (strlen($string) == 0) return null; + $guser = new Pluf_User(); + foreach (array('email', 'login', 'last_name') as $what) { + $sql = new Pluf_SQL($what.'=%s', $string); + $users = $guser->getList(array('filter' => $sql->gen())); + if ($users->count() > 0) { + return $users[0]; + } + } + return null; + } +} diff --git a/indefero/src/IDF/Form/IssueTrackingConf.php b/indefero/src/IDF/Form/IssueTrackingConf.php new file mode 100644 index 0000000..e17b1d7 --- /dev/null +++ b/indefero/src/IDF/Form/IssueTrackingConf.php @@ -0,0 +1,150 @@ +fields['labels_issue_template'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Define an issue template to hint the reporter to provide certain information'), + 'initial' => self::init_template, + 'widget_attrs' => array('rows' => 7, + 'cols' => 75), + 'widget' => 'Pluf_Form_Widget_TextareaInput', + )); + + $this->fields['labels_issue_open'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Open issue status values'), + 'initial' => self::init_open, + 'widget' => 'Pluf_Form_Widget_TextareaInput', + 'widget_attrs' => array('rows' => 5, + 'cols' => 75), + )); + $this->fields['labels_issue_closed'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Closed issue status values'), + 'initial' => self::init_closed, + 'widget_attrs' => array('rows' => 7, + 'cols' => 75), + 'widget' => 'Pluf_Form_Widget_TextareaInput', + )); + + $this->fields['labels_issue_predefined'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Predefined issue labels'), + 'initial' => self::init_predefined, + 'help_text' => __('The first "Type:" and "Priority:" entries found in this list are automatically chosen as defaults for new issues.'), + 'widget_attrs' => array('rows' => 7, + 'cols' => 75), + 'widget' => 'Pluf_Form_Widget_TextareaInput', + )); + + $this->fields['labels_issue_one_max'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Each issue may have at most one label with each of these classes.'), + 'initial' => self::init_one_max, + 'widget_attrs' => array('size' => 60), + )); + + $this->fields['issue_relations'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Issue relations'), + 'initial' => self::init_relations, + 'help_text' => __('You can define bidirectional relations like "is related to" or "blocks, is blocked by". For standard relations pre-configured translations exist, new relations should however be defined in a language that is understood by all project members.'), + 'widget_attrs' => array('rows' => 7, + 'cols' => 75), + 'widget' => 'Pluf_Form_Widget_TextareaInput', + )); + } +} + + diff --git a/indefero/src/IDF/Form/IssueUpdate.php b/indefero/src/IDF/Form/IssueUpdate.php new file mode 100644 index 0000000..0362eb3 --- /dev/null +++ b/indefero/src/IDF/Form/IssueUpdate.php @@ -0,0 +1,488 @@ +user = $extra['user']; + $this->project = $extra['project']; + $this->issue = $extra['issue']; + if ($this->user->hasPerm('IDF.project-owner', $this->project) + or $this->user->hasPerm('IDF.project-member', $this->project)) { + $this->show_full = true; + } + $this->relation_types = $this->project->getRelationsFromConfig(); + if ($this->show_full) { + $this->fields['summary'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Summary'), + 'initial' => $this->issue->summary, + 'widget_attrs' => array( + 'maxlength' => 200, + 'size' => 67, + ), + )); + } + $this->fields['content'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Comment'), + 'initial' => '', + 'widget' => 'Pluf_Form_Widget_TextareaInput', + 'widget_attrs' => array( + 'cols' => 58, + 'rows' => 9, + ), + )); + $upload_path = Pluf::f('upload_issue_path', false); + if (false === $upload_path) { + throw new Pluf_Exception_SettingError(__('The "upload_issue_path" configuration variable was not set.')); + } + $md5 = md5(rand().microtime().Pluf_Utils::getRandomString()); + // We add .dummy to try to mitigate security issues in the + // case of someone allowing the upload path to be accessible + // to everybody. + for ($i=1;$i<4;$i++) { + $filename = substr($md5, 0, 2).'/'.substr($md5, 2, 2).'/'.substr($md5, 4).'/%s.dummy'; + $this->fields['attachment'.$i] = new Pluf_Form_Field_File( + array('required' => false, + 'label' => __('Attach a file'), + 'move_function_params' => + array('upload_path' => $upload_path, + 'upload_path_create' => true, + 'file_name' => $filename, + ) + ) + ); + } + + if ($this->show_full) { + $this->fields['status'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Status'), + 'initial' => $this->issue->get_status()->name, + 'widget_attrs' => array( + 'maxlength' => 20, + 'size' => 15, + ), + )); + $initial = ($this->issue->get_owner() == null) ? '' : $this->issue->get_owner()->login; + $this->fields['owner'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Owner'), + 'initial' => $initial, + 'widget_attrs' => array( + 'maxlength' => 20, + 'size' => 15, + ), + )); + + $idx = 0; + // note: clean_relation_type0 and clean_relation_issue0 already + // exist in the base class + $this->fields['relation_type'.$idx] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('This issue'), + 'initial' => current($this->relation_types), + 'widget_attrs' => array('size' => 15), + )); + + $this->fields['relation_issue'.$idx] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => null, + 'initial' => '', + 'widget_attrs' => array('size' => 10), + )); + + ++$idx; + $relatedIssues = $this->issue->getGroupedRelatedIssues(array(), true); + foreach ($relatedIssues as $verb => $ids) { + $this->fields['relation_type'.$idx] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('This issue'), + 'initial' => $verb, + 'widget_attrs' => array('size' => 15), + )); + $m = 'clean_relation_type'.$idx; + $this->$m = create_function('$form', ' + return $form->clean_relation_type($form->cleaned_data["relation_type'.$idx.'"]); + '); + + $this->fields['relation_issue'.$idx] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => null, + 'initial' => implode(', ', $ids), + 'widget_attrs' => array('size' => 10), + )); + $m = 'clean_relation_issue'.$idx; + $this->$m = create_function('$form', ' + return $form->clean_relation_issue($form->cleaned_data["relation_issue'.$idx.'"]); + '); + + ++$idx; + } + + $tags = $this->issue->get_tags_list(); + for ($i=1;$i<7;$i++) { + $initial = ''; + if (isset($tags[$i-1])) { + if ($tags[$i-1]->class != 'Other') { + $initial = (string) $tags[$i-1]; + } else { + $initial = $tags[$i-1]->name; + } + } + $this->fields['label'.$i] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Labels'), + 'initial' => $initial, + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 20, + ), + )); + } + } + } + + /** + * Clean the attachments post failure. + */ + function failed() + { + $upload_path = Pluf::f('upload_issue_path', false); + if ($upload_path == false) return; + for ($i=1;$i<4;$i++) { + if (!empty($this->cleaned_data['attachment'.$i]) and + file_exists($upload_path.'/'.$this->cleaned_data['attachment'.$i])) { + @unlink($upload_path.'/'.$this->cleaned_data['attachment'.$i]); + } + } + } + + function clean_content() + { + $content = trim($this->cleaned_data['content']); + if (!$this->show_full and strlen($content) == 0) { + throw new Pluf_Form_Invalid(__('You need to provide a description of the issue.')); + } + return $content; + } + + /** + * We check that something is really changed. + */ + public function clean() + { + $this->cleaned_data = parent::clean(); + + // normalize the user's input by removing dublettes and by combining + // ids from identical verbs in different input fields into one array + $normRelatedIssues = array(); + for ($idx = 0; isset($this->cleaned_data['relation_type'.$idx]); ++$idx) { + $verb = $this->cleaned_data['relation_type'.$idx]; + if (empty($verb)) + continue; + + $ids = preg_split('/\s*,\s*/', $this->cleaned_data['relation_issue'.$idx], + -1, PREG_SPLIT_NO_EMPTY); + if (count($ids) == 0) + continue; + + if (!array_key_exists($verb, $normRelatedIssues)) + $normRelatedIssues[$verb] = array(); + foreach ($ids as $id) { + if (!in_array($id, $normRelatedIssues[$verb])) + $normRelatedIssues[$verb][] = $id; + } + } + + // now look at any added / removed ids + $added = $removed = array(); + $relatedIssues = $this->issue->getGroupedRelatedIssues(array(), true); + $added = array_diff_key($normRelatedIssues, $relatedIssues); + $removed = array_diff_key($relatedIssues, $normRelatedIssues); + + $keysToLookAt = array_keys( + array_intersect_key($relatedIssues, $normRelatedIssues) + ); + foreach ($keysToLookAt as $key) { + $a = array_diff($normRelatedIssues[$key], $relatedIssues[$key]); + if (count($a) > 0) + $added[$key] = $a; + $r = array_diff($relatedIssues[$key], $normRelatedIssues[$key]); + if (count($r) > 0) + $removed[$key] = $r; + } + + // cache the added / removed data, so we do not have to + // calculate that again + $this->cleaned_data['_added_issue_relations'] = $added; + $this->cleaned_data['_removed_issue_relations'] = $removed; + + // As soon as we know that at least one change was done, we + // return the cleaned data and do not go further. + if (strlen(trim($this->cleaned_data['content']))) { + return $this->cleaned_data; + } + if ($this->show_full) { + $status = $this->issue->get_status(); + if (trim($this->cleaned_data['status']) != $status->name) { + return $this->cleaned_data; + } + if (trim($this->issue->summary) != trim($this->cleaned_data['summary'])) { + return $this->cleaned_data; + } + $owner = self::findUser($this->cleaned_data['owner']); + if ((is_null($owner) and !is_null($this->issue->get_owner())) + or (!is_null($owner) and is_null($this->issue->get_owner())) + or ((!is_null($owner) and !is_null($this->issue->get_owner())) and $owner->id != $this->issue->get_owner()->id)) { + return $this->cleaned_data; + } + $tags = array(); + for ($i=1;$i<7;$i++) { + if (strlen($this->cleaned_data['label'.$i]) > 0) { + if (strpos($this->cleaned_data['label'.$i], ':') !== false) { + list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2); + list($class, $name) = array(trim($class), trim($name)); + } else { + $class = 'Other'; + $name = trim($this->cleaned_data['label'.$i]); + } + $tags[] = array($class, $name); + } + } + $oldtags = $this->issue->get_tags_list(); + foreach ($tags as $tag) { + $found = false; + foreach ($oldtags as $otag) { + if ($otag->class == $tag[0] and $otag->name == $tag[1]) { + $found = true; + break; + } + } + if (!$found) { + // new tag not found in the old tags + return $this->cleaned_data; + } + } + foreach ($oldtags as $otag) { + $found = false; + foreach ($tags as $tag) { + if ($otag->class == $tag[0] and $otag->name == $tag[1]) { + $found = true; + break; + } + } + if (!$found) { + // old tag not found in the new tags + return $this->cleaned_data; + } + } + + if (count($this->cleaned_data['_added_issue_relations']) != 0 || + count($this->cleaned_data['_removed_issue_relations']) != 0) { + return $this->cleaned_data; + } + } + // no changes! + throw new Pluf_Form_Invalid(__('No changes were entered.')); + } + + /** + * Save the model in the database. + * + * @param bool Commit in the database or not. If not, the object + * is returned but not saved in the database. + * @return Object Model with data set from the form. + */ + function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save the model from an invalid form.')); + } + if ($this->show_full) { + // Add a tag for each label + $tags = array(); + $tagids = array(); + for ($i=1;$i<7;$i++) { + if (strlen($this->cleaned_data['label'.$i]) > 0) { + if (strpos($this->cleaned_data['label'.$i], ':') !== false) { + list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2); + list($class, $name) = array(trim($class), trim($name)); + } else { + $class = 'Other'; + $name = trim($this->cleaned_data['label'.$i]); + } + $tag = IDF_Tag::add($name, $this->project, $class); + $tags[] = $tag; + $tagids[] = $tag->id; + } + } + // Compare between the old and the new data + $changes = array(); + $oldtags = $this->issue->get_tags_list(); + foreach ($tags as $tag) { + if (!Pluf_Model_InArray($tag, $oldtags)) { + if (!isset($changes['lb'])) $changes['lb'] = array(); + if (!isset($changes['lb']['add'])) $changes['lb']['add'] = array(); + if ($tag->class != 'Other') { + $changes['lb']['add'][] = (string) $tag; //new tag + } else { + $changes['lb']['add'][] = (string) $tag->name; + } + } + } + foreach ($oldtags as $tag) { + if (!Pluf_Model_InArray($tag, $tags)) { + if (!isset($changes['lb'])) $changes['lb'] = array(); + if (!isset($changes['lb']['rem'])) $changes['lb']['rem'] = array(); + if ($tag->class != 'Other') { + $changes['lb']['rem'][] = (string) $tag; //new tag + } else { + $changes['lb']['rem'][] = (string) $tag->name; + } + } + } + // Status, summary and owner + $status = IDF_Tag::add(trim($this->cleaned_data['status']), $this->project, 'Status'); + if ($status->id != $this->issue->status) { + $changes['st'] = $status->name; + } + if (trim($this->issue->summary) != trim($this->cleaned_data['summary'])) { + $changes['su'] = trim($this->cleaned_data['summary']); + } + $owner = self::findUser($this->cleaned_data['owner']); + if ((is_null($owner) and !is_null($this->issue->get_owner())) + or (!is_null($owner) and is_null($this->issue->get_owner())) + or ((!is_null($owner) and !is_null($this->issue->get_owner())) and $owner->id != $this->issue->get_owner()->id)) { + $changes['ow'] = (is_null($owner)) ? '---' : $owner->login; + } + // Issue relations - additions + foreach ($this->cleaned_data['_added_issue_relations'] as $verb => $ids) { + $other_verb = $this->relation_types[$verb]; + foreach ($ids as $id) { + $related_issue = new IDF_Issue($id); + $rel = new IDF_IssueRelation(); + $rel->issue = $this->issue; + $rel->verb = $verb; + $rel->other_issue = $related_issue; + $rel->submitter = $this->user; + $rel->create(); + + $other_rel = new IDF_IssueRelation(); + $other_rel->issue = $related_issue; + $other_rel->verb = $other_verb; + $other_rel->other_issue = $this->issue; + $other_rel->submitter = $this->user; + $other_rel->create(); + } + if (!isset($changes['rel'])) $changes['rel'] = array(); + if (!isset($changes['rel']['add'])) $changes['rel']['add'] = array(); + $changes['rel']['add'][] = $verb.' '.implode(', ', $ids); + } + // Issue relations - removals + foreach ($this->cleaned_data['_removed_issue_relations'] as $verb => $ids) { + foreach ($ids as $id) { + $db = &Pluf::db(); + $table = Pluf::factory('IDF_IssueRelation')->getSqlTable(); + $sql = new Pluf_SQL('verb=%s AND ( + (issue=%s AND other_issue=%s) OR + (other_issue=%s AND issue=%s))', + array($verb, + $this->issue->id, $id, + $this->issue->id, $id)); + $db->execute('DELETE FROM '.$table.' WHERE '.$sql->gen()); + } + + if (!isset($changes['rel'])) $changes['rel'] = array(); + if (!isset($changes['rel']['rem'])) $changes['rel']['rem'] = array(); + $changes['rel']['rem'][] = $verb.' '.implode(', ', $ids); + } + // Update the issue + $this->issue->batchAssoc('IDF_Tag', $tagids); + $this->issue->summary = trim($this->cleaned_data['summary']); + $this->issue->status = $status; + $this->issue->owner = $owner; + } + // Create the comment + $comment = new IDF_IssueComment(); + $comment->issue = $this->issue; + $comment->content = $this->cleaned_data['content']; + $comment->submitter = $this->user; + if (!$this->show_full) $changes = array(); + $comment->changes = $changes; + $comment->create(); + $this->issue->update(); + if ($this->issue->owner != $this->user->id and + $this->issue->submitter != $this->user->id) { + $this->issue->setAssoc($this->user); // interested user. + } + $attached_files = array(); + for ($i=1;$i<4;$i++) { + if ($this->cleaned_data['attachment'.$i]) { + $file = new IDF_IssueFile(); + $file->attachment = $this->cleaned_data['attachment'.$i]; + $file->submitter = $this->user; + $file->comment = $comment; + $file->create(); + $attached_files[] = $file; + } + } + /** + * [signal] + * + * IDF_Issue::update + * + * [sender] + * + * IDF_Form_IssueUpdate + * + * [description] + * + * This signal allows an application to perform a set of tasks + * just after the update of an issue. + * + * [parameters] + * + * array('issue' => $issue, + * 'comment' => $comment, + * 'files' => $attached_files); + * + */ + $params = array('issue' => $this->issue, + 'comment' => $comment, + 'files' => $attached_files); + Pluf_Signal::send('IDF_Issue::update', 'IDF_Form_IssueUpdate', + $params); + + return $this->issue; + } +} diff --git a/indefero/src/IDF/Form/MembersConf.php b/indefero/src/IDF/Form/MembersConf.php new file mode 100644 index 0000000..b2c541a --- /dev/null +++ b/indefero/src/IDF/Form/MembersConf.php @@ -0,0 +1,138 @@ +project = $extra['project']; + + $this->fields['owners'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Project owners'), + 'initial' => '', + 'widget' => 'Pluf_Form_Widget_TextareaInput', + 'widget_attrs' => array('rows' => 5, + 'cols' => 40), + )); + $this->fields['members'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Project members'), + 'widget_attrs' => array('rows' => 7, + 'cols' => 40), + 'widget' => 'Pluf_Form_Widget_TextareaInput', + )); + } + + public function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save the model from an invalid form.')); + } + self::updateMemberships($this->project, $this->cleaned_data); + $this->project->membershipsUpdated(); + } + + public function clean_owners() + { + return self::checkBadLogins($this->cleaned_data['owners']); + } + + public function clean_members() + { + return self::checkBadLogins($this->cleaned_data['members']); + } + + /** + * From the input, find the bad logins. + * + * @throws Pluf_Form_Invalid exception when bad logins are found + * @param string Comma, new line delimited list of logins + * @return string Comma, new line delimited list of logins + */ + public static function checkBadLogins($logins) + { + $bad = array(); + foreach (preg_split("/\015\012|\015|\012|\,/", $logins, -1, PREG_SPLIT_NO_EMPTY) as $login) { + $sql = new Pluf_SQL('login=%s', array(trim($login))); + try { + $user = Pluf::factory('Pluf_User')->getOne(array('filter'=>$sql->gen())); + if (null == $user) { + $bad[] = $login; + } + } catch (Exception $e) { + $bad[] = $login; + } + } + $n = count($bad); + if ($n) { + $badlogins = Pluf_esc(implode(', ', $bad)); + throw new Pluf_Form_Invalid(sprintf(_n('The following login is invalid: %s.', 'The following logins are invalid: %s.', $n), $badlogins)); + } + return $logins; + } + + /** + * The update of the memberships is done in different places. This + * avoids duplicating code. + * + * @param IDF_Project The project + * @param array The new memberships data in 'owners' and 'members' keys + */ + public static function updateMemberships($project, $cleaned_data) + { + // remove all the permissions + $cm = $project->getMembershipData(); + $def = array('owners' => Pluf_Permission::getFromString('IDF.project-owner'), + 'members' => Pluf_Permission::getFromString('IDF.project-member')); + $guser = new Pluf_User(); + foreach ($def as $key=>$perm) { + foreach ($cm[$key] as $user) { + Pluf_RowPermission::remove($user, $project, $perm); + } + foreach (preg_split("/\015\012|\015|\012|\,/", $cleaned_data[$key], -1, PREG_SPLIT_NO_EMPTY) as $login) { + $sql = new Pluf_SQL('login=%s', array(trim($login))); + $users = $guser->getList(array('filter'=>$sql->gen())); + if ($users->count() == 1) { + Pluf_RowPermission::add($users[0], $project, $perm); + } + } + } + } +} + + diff --git a/indefero/src/IDF/Form/Password.php b/indefero/src/IDF/Form/Password.php new file mode 100644 index 0000000..c913492 --- /dev/null +++ b/indefero/src/IDF/Form/Password.php @@ -0,0 +1,112 @@ +fields['account'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Your login or email'), + 'help_text' => __('Provide either your login or your email to recover your password.'), + )); + } + + /** + * Validate that a user with this login or email exists. + */ + public function clean_account() + { + $account = mb_strtolower(trim($this->cleaned_data['account'])); + $sql = new Pluf_SQL('email=%s OR login=%s', + array($account, $account)); + $users = Pluf::factory('Pluf_User')->getList(array('filter'=>$sql->gen())); + if ($users->count() == 0) { + throw new Pluf_Form_Invalid(__('Sorry, we cannot find a user with this email address or login. Feel free to try again.')); + } + $ok = false; + foreach ($users as $user) { + if ($user->active) { + $ok = true; + continue; + } + if (!$user->active and $user->first_name == '---') { + $ok = true; + continue; + } + $ok = false; // This ensures an all or nothing ok. + } + if (!$ok) { + throw new Pluf_Form_Invalid(__('Sorry, we cannot find a user with this email address or login. Feel free to try again.')); + } + return $account; + } + + /** + * Send the reminder email. + * + */ + function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save the model from an invalid form.')); + } + $account = $this->cleaned_data['account']; + $sql = new Pluf_SQL('email=%s OR login=%s', + array($account, $account)); + $users = Pluf::factory('Pluf_User')->getList(array('filter'=>$sql->gen())); + + $return_url = ''; + foreach ($users as $user) { + if ($user->active) { + $return_url = Pluf_HTTP_URL_urlForView('IDF_Views::passwordRecoveryInputCode'); + $tmpl = new Pluf_Template('idf/user/passrecovery-email.txt'); + $cr = new Pluf_Crypt(md5(Pluf::f('secret_key'))); + $code = trim($cr->encrypt($user->email.':'.$user->id.':'.time().':primary'), + '~'); + $code = substr(md5(Pluf::f('secret_key').$code), 0, 2).$code; + $url = Pluf::f('url_base').Pluf_HTTP_URL_urlForView('IDF_Views::passwordRecovery', array($code), array(), false); + $urlic = Pluf::f('url_base').Pluf_HTTP_URL_urlForView('IDF_Views::passwordRecoveryInputCode', array(), array(), false); + $context = new Pluf_Template_Context( + array('url' => Pluf_Template::markSafe($url), + 'urlik' => Pluf_Template::markSafe($urlic), + 'user' => Pluf_Template::markSafe($user), + 'key' => Pluf_Template::markSafe($code))); + $email = new Pluf_Mail(Pluf::f('from_email'), $user->email, + __('Password Recovery - InDefero')); + $email->setReturnPath(Pluf::f('bounce_email', Pluf::f('from_email'))); + $email->addTextMessage($tmpl->render($context)); + $email->sendMail(); + } + if (!$user->active and $user->first_name == '---') { + $return_url = Pluf_HTTP_URL_urlForView('IDF_Views::registerInputKey'); + IDF_Form_Register::sendVerificationEmail($user); + } + } + return $return_url; + } +} diff --git a/indefero/src/IDF/Form/PasswordInputKey.php b/indefero/src/IDF/Form/PasswordInputKey.php new file mode 100644 index 0000000..433b3ac --- /dev/null +++ b/indefero/src/IDF/Form/PasswordInputKey.php @@ -0,0 +1,104 @@ +fields['key'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Your verification key'), + 'initial' => '', + 'widget_attrs' => array( + 'size' => 50, + ), + )); + } + + /** + * Validate the key. + */ + public function clean_key() + { + $this->cleaned_data['key'] = trim($this->cleaned_data['key']); + $error = __('We are sorry but this validation key is not valid. Maybe you should directly copy/paste it from your validation email.'); + if (false === ($cres=self::checkKeyHash($this->cleaned_data['key']))) { + throw new Pluf_Form_Invalid($error); + } + $guser = new Pluf_User(); + $sql = new Pluf_SQL('email=%s AND id=%s', + array($cres[0], $cres[1])); + if ($guser->getCount(array('filter' => $sql->gen())) != 1) { + throw new Pluf_Form_Invalid($error); + } + if ((time() - $cres[2]) > 86400) { + throw new Pluf_Form_Invalid(__('Sorry, but this verification key has expired, please restart the password recovery sequence. For security reasons, the verification key is only valid 24h.')); + } + return $this->cleaned_data['key']; + } + + /** + * Save the model in the database. + * + * @param bool Commit in the database or not. If not, the object + * is returned but not saved in the database. + * @return string Url to redirect to the form. + */ + function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save an invalid form.')); + } + return Pluf_HTTP_URL_urlForView('IDF_Views::passwordRecovery', + array($this->cleaned_data['key'])); + } + + /** + * Return false or an array with the email, id and timestamp. + * + * This is a static function to be reused by other forms. + * + * @param string Confirmation key + * @return mixed Either false or array(email, id, timestamp) + */ + public static function checkKeyHash($key) + { + $hash = substr($key, 0, 2); + $encrypted = substr($key, 2); + if ($hash != substr(md5(Pluf::f('secret_key').$encrypted), 0, 2)) { + return false; + } + $cr = new Pluf_Crypt(md5(Pluf::f('secret_key'))); + $f = explode(':', $cr->decrypt($encrypted), 3); + if (count($f) != 3) { + return false; + } + return $f; + } +} diff --git a/indefero/src/IDF/Form/PasswordReset.php b/indefero/src/IDF/Form/PasswordReset.php new file mode 100644 index 0000000..9e85d9c --- /dev/null +++ b/indefero/src/IDF/Form/PasswordReset.php @@ -0,0 +1,138 @@ +user = $extra['user']; + $this->fields['key'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Your verification key'), + 'initial' => $extra['key'], + 'widget' => 'Pluf_Form_Widget_HiddenInput', + )); + $this->fields['password'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Your password'), + 'initial' => '', + 'widget' => 'Pluf_Form_Widget_PasswordInput', + 'help_text' => __('Your password must be hard for other people to find it, but easy for you to remember.'), + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 15, + ), + )); + $this->fields['password2'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Confirm your password'), + 'initial' => '', + 'widget' => 'Pluf_Form_Widget_PasswordInput', + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 15, + ), + )); + + + } + + /** + * Check the passwords. + */ + public function clean() + { + if ($this->cleaned_data['password'] != $this->cleaned_data['password2']) { + throw new Pluf_Form_Invalid(__('The two passwords must be the same.')); + } + if (!$this->user->active) { + throw new Pluf_Form_Invalid(__('This account is not active. Please contact the forge administrator to activate it.')); + } + return $this->cleaned_data; + } + + + /** + * Validate the key. + */ + public function clean_key() + { + $this->cleaned_data['key'] = trim($this->cleaned_data['key']); + $error = __('We are sorry but this validation key is not valid. Maybe you should directly copy/paste it from your validation email.'); + if (false === ($cres=IDF_Form_PasswordInputKey::checkKeyHash($this->cleaned_data['key']))) { + throw new Pluf_Form_Invalid($error); + } + $guser = new Pluf_User(); + $sql = new Pluf_SQL('email=%s AND id=%s', + array($cres[0], $cres[1])); + if ($guser->getCount(array('filter' => $sql->gen())) != 1) { + throw new Pluf_Form_Invalid($error); + } + if ((time() - $cres[2]) > 86400) { + throw new Pluf_Form_Invalid(__('Sorry, but this verification key has expired, please restart the password recovery sequence. For security reasons, the verification key is only valid 24h.')); + } + return $this->cleaned_data['key']; + } + + function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save an invalid form.')); + } + $this->user->setFromFormData($this->cleaned_data); + if ($commit) { + $this->user->update(); + /** + * [signal] + * + * Pluf_User::passwordUpdated + * + * [sender] + * + * IDF_Form_PasswordReset + * + * [description] + * + * This signal is sent when the user reset his + * password from the password recovery page. + * + * [parameters] + * + * array('user' => $user) + * + */ + $params = array('user' => $this->user); + Pluf_Signal::send('Pluf_User::passwordUpdated', + 'IDF_Form_PasswordReset', $params); + } + return $this->user; + } +} diff --git a/indefero/src/IDF/Form/ProjectConf.php b/indefero/src/IDF/Form/ProjectConf.php new file mode 100644 index 0000000..6f1901a --- /dev/null +++ b/indefero/src/IDF/Form/ProjectConf.php @@ -0,0 +1,231 @@ +project = $extra['project']; + $this->user = $extra["user"]; + $conf = $this->project->getConf(); + + // Basic part + $this->fields['name'] = new Pluf_Form_Field_Varchar(array('required' => true, + 'label' => __('Name'), + 'initial' => $this->project->name, + )); + $this->fields['shortdesc'] = new Pluf_Form_Field_Varchar(array('required' => true, + 'label' => __('Short Description'), + 'initial' => $this->project->shortdesc, + 'widget_attrs' => array('size' => '68'), + )); + $this->fields['description'] = new Pluf_Form_Field_Varchar(array('required' => true, + 'label' => __('Description'), + 'initial' => $this->project->description, + 'widget_attrs' => array('cols' => 68, + 'rows' => 26, + ), + 'widget' => 'Pluf_Form_Widget_TextareaInput', + )); + $this->fields['external_project_url'] = new Pluf_Form_Field_Varchar(array('required' => false, + 'label' => __('External URL'), + 'widget_attrs' => array('size' => '68'), + 'initial' => $conf->getVal('external_project_url'), + + )); + if ($this->user->administrator) + { + $this->fields['enableads'] = new Pluf_Form_Field_Boolean( + array('required' => false, + 'label' => __('Enable advertising'), + 'initial' => $this->project->enableads, + 'widget' => 'Pluf_Form_Widget_CheckboxInput', + )); + } else { + $this->fields['enableads'] = new Pluf_Form_Field_Boolean( + array('required' => false, + 'label' => __('Enable advertising'), + 'initial' => $this->project->enableads, + 'widget' => 'Pluf_Form_Widget_CheckboxInput', + 'widget_attrs' => array('disabled' => 'disabled') + )); + } + $tags = $this->project->get_tags_list(); + for ($i=1;$i<7;$i++) { + $initial = ''; + if (isset($tags[$i-1])) { + if ($tags[$i-1]->class != 'Other') { + $initial = (string) $tags[$i-1]; + } else { + $initial = $tags[$i-1]->name; + } + } + $this->fields['label'.$i] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Labels'), + 'initial' => $initial, + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 20, + ), + )); + } + + // Logo part + $upload_path = Pluf::f('upload_path', false); + if (false === $upload_path) { + throw new Pluf_Exception_SettingError(__('The "upload_path" configuration variable was not set.')); + } + $upload_path .= '/' . $this->project->shortname; + $filename = '/%s'; + $this->fields['logo'] = new Pluf_Form_Field_File(array('required' => false, + 'label' => __('Update the logo'), + 'initial' => '', + 'help_text' => __('The logo must be a picture with a size of 32 by 32.'), + 'max_size' => Pluf::f('max_upload_size', 5 * 1024), + 'move_function_params' => + array('upload_path' => $upload_path, + 'upload_path_create' => true, + 'upload_overwrite' => true, + 'file_name' => $filename, + ) + )); + + $this->fields['logo_remove'] = new Pluf_Form_Field_Boolean(array('required' => false, + 'label' => __('Remove the current logo'), + 'initial' => false, + 'widget' => 'Pluf_Form_Widget_CheckboxInput', + )); + } + + /** + * If we have uploaded a file, but the form failed remove it. + * + */ + function failed() + { + if (!empty($this->cleaned_data['logo']) + && file_exists(Pluf::f('upload_path').'/'.$this->cleaned_data['logo'])) { + unlink(Pluf::f('upload_path').'/'.$this->cleaned_data['logo']); + } + } + + public function clean() + { + if (!isset($this->cleaned_data['logo_remove'])) { + $this->cleaned_data['logo_remove'] = false; + } + + return $this->cleaned_data; + } + + public function clean_logo() + { + if (empty($this->cleaned_data['logo'])) { + return ''; + } + + $meta = getimagesize(Pluf::f('upload_path') . '/' . $this->project->shortname . $this->cleaned_data['logo']); + + if ($meta === false) { + throw new Pluf_Form_Invalid(__('Could not determine the size of the uploaded picture.')); + } + + if ($meta[0] !== 32 || $meta[1] !== 32) { + throw new Pluf_Form_Invalid(__('The picture must have a size of 32 by 32.')); + } + + return $this->cleaned_data['logo']; + } + + public function clean_external_project_url() + { + return self::checkWebURL($this->cleaned_data['external_project_url']); + } + + public static function checkWebURL($url) + { + $url = trim($url); + if (empty($url)) { + return ''; + } + + $parsed = parse_url($url); + if ($parsed === false || !array_key_exists('scheme', $parsed) || + ($parsed['scheme'] != 'http' && $parsed['scheme'] != 'https')) { + throw new Pluf_Form_Invalid(__('The entered URL is invalid. Only http and https URLs are allowed.')); + } + + return $url; + } + + public function save($commit=true) + { + // Add a tag for each label + $tagids = array(); + for ($i=1;$i<7;$i++) { + if (strlen($this->cleaned_data['label'.$i]) > 0) { + if (strpos($this->cleaned_data['label'.$i], ':') !== false) { + list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2); + list($class, $name) = array(trim($class), trim($name)); + } else { + $class = 'Other'; + $name = trim($this->cleaned_data['label'.$i]); + } + $tag = IDF_Tag::addGlobal($name, $class); + $tagids[] = $tag->id; + } + } + + // Basic part + $this->project->name = $this->cleaned_data['name']; + $this->project->shortdesc = $this->cleaned_data['shortdesc']; + $this->project->description = $this->cleaned_data['description']; + $this->project->batchAssoc('IDF_Tag', $tagids); + if ($this->user->administrator) + $this->project->enableads = $this->cleaned_data['enableads']; + $this->project->update(); + + $conf = $this->project->getConf(); + if (!empty($this->cleaned_data['logo'])) { + $conf->setVal('logo', $this->cleaned_data['logo']); + } + if (!empty($this->cleaned_data['external_project_url'])) { + $conf->setVal('external_project_url', $this->cleaned_data['external_project_url']); + } + else { + $conf->delVal('external_project_url'); + } + + if ($this->cleaned_data['logo_remove'] === true) { + @unlink(Pluf::f('upload_path') . '/' . $this->project->shortname . $conf->getVal('logo')); + $conf->delVal('logo'); + } + } +} diff --git a/indefero/src/IDF/Form/Register.php b/indefero/src/IDF/Form/Register.php new file mode 100644 index 0000000..085cd7e --- /dev/null +++ b/indefero/src/IDF/Form/Register.php @@ -0,0 +1,165 @@ +request = $extra['request']; + $login = ''; + if (isset($extra['initial']['login'])) { + $login = $extra['initial']['login']; + } + $this->fields['login'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Your login'), + 'max_length' => 15, + 'min_length' => 3, + 'initial' => $login, + 'help_text' => __('The login must be between 3 and 15 characters long and contain only letters and digits.'), + 'widget_attrs' => array( + 'maxlength' => 15, + 'size' => 10, + ), + )); + $this->fields['email'] = new Pluf_Form_Field_Email( + array('required' => true, + 'label' => __('Your email'), + 'initial' => '', + 'help_text' => __('We will never send you any unsolicited emails. We hate spam too!'), + )); + + $this->fields['regkey'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Registration Key'), + 'initial' => '', + 'help_text' => __('Please enter the key given to you by adamsna[at]datanethost.net'), + )); + + $this->fields['terms'] = new Pluf_Form_Field_Boolean( + array('required' => true, + 'label' => __('I agree to the terms and conditions.'), + 'initial' => '', + )); + } + + public function clean_regkey() + { + if ($this->cleaned_data['regkey'] != "2rv9o4nb5") + throw new Pluf_Form_Invalid("The regkey was incorrect - please contact Nathan for the key!"); + } + + /** + * Validate the interconnection in the form. + */ + public function clean_login() + { + $this->cleaned_data['login'] = mb_strtolower(trim($this->cleaned_data['login'])); + if (preg_match('/[^A-Za-z0-9]/', $this->cleaned_data['login'])) { + throw new Pluf_Form_Invalid(sprintf(__('The login "%s" can only contain letters and digits.'), $this->cleaned_data['login'])); + } + $guser = new Pluf_User(); + $sql = new Pluf_SQL('login=%s', $this->cleaned_data['login']); + if ($guser->getCount(array('filter' => $sql->gen())) > 0) { + throw new Pluf_Form_Invalid(sprintf(__('The login "%s" is already used, please find another one.'), $this->cleaned_data['login'])); + } + return $this->cleaned_data['login']; + } + + /** + * Check the terms. + */ + public function clean_terms() + { + if (!$this->cleaned_data['terms']) { + throw new Pluf_Form_Invalid(__('We know, this is boring, but you need to agree with the terms and conditions.')); + } + return $this->cleaned_data['terms']; + } + + function clean_email() + { + $this->cleaned_data['email'] = mb_strtolower(trim($this->cleaned_data['email'])); + if (Pluf::factory('IDF_EmailAddress')->get_user_for_email_address($this->cleaned_data['email']) != null) { + throw new Pluf_Form_Invalid(sprintf(__('The email "%1$s" is already used. If you need to, you can recover your password.'), $this->cleaned_data['email'], Pluf_HTTP_URL_urlForView('IDF_Views::passwordRecoveryAsk'))); + } + return $this->cleaned_data['email']; + } + + /** + * Save the model in the database. + * + * @param bool Commit in the database or not. If not, the object + * is returned but not saved in the database. + * @return Object Model with data set from the form. + */ + function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save the model from an invalid form.')); + } + $user = new Pluf_User(); + $user->first_name = '---'; // with both this set and + // active==false we can find later + // on, all the unconfirmed accounts + // that could be purged. + $user->last_name = $this->cleaned_data['login']; + $user->login = $this->cleaned_data['login']; + $user->email = $this->cleaned_data['email']; + $user->language = $this->request->language_code; + $user->active = false; + $user->create(); + self::sendVerificationEmail($user); + return $user; + } + + public static function sendVerificationEmail($user) + { + Pluf::loadFunction('Pluf_HTTP_URL_urlForView'); + $from_email = Pluf::f('from_email'); + $cr = new Pluf_Crypt(md5(Pluf::f('secret_key'))); + $encrypted = trim($cr->encrypt($user->email.':'.$user->id), '~'); + $key = substr(md5(Pluf::f('secret_key').$encrypted), 0, 2).$encrypted; + $url = Pluf::f('url_base').Pluf_HTTP_URL_urlForView('IDF_Views::registerConfirmation', array($key), array(), false); + $urlik = Pluf::f('url_base').Pluf_HTTP_URL_urlForView('IDF_Views::registerInputKey', array(), array(), false); + $context = new Pluf_Template_Context( + array('key' => $key, + 'url' => $url, + 'urlik' => $urlik, + 'user'=> $user, + ) + ); + $tmpl = new Pluf_Template('idf/register/confirmation-email.txt'); + $text_email = $tmpl->render($context); + $email = new Pluf_Mail($from_email, $user->email, + __('Confirm the creation of your account.')); + $email->addTextMessage($text_email); + $email->sendMail(); + } +} diff --git a/indefero/src/IDF/Form/RegisterConfirmation.php b/indefero/src/IDF/Form/RegisterConfirmation.php new file mode 100644 index 0000000..bfdf77e --- /dev/null +++ b/indefero/src/IDF/Form/RegisterConfirmation.php @@ -0,0 +1,170 @@ +_user = $extra['user']; + + $this->fields['key'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Your confirmation key'), + 'initial' => $extra['key'], + 'widget' => 'Pluf_Form_Widget_HiddenInput', + 'widget_attrs' => array( + 'readonly' => 'readonly', + ), + + )); + $this->fields['first_name'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('First name'), + 'initial' => '', + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 15, + ), + )); + $this->fields['last_name'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Last name'), + 'initial' => '', + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 15, + ), + )); + + $this->fields['password'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Your password'), + 'initial' => '', + 'widget' => 'Pluf_Form_Widget_PasswordInput', + 'help_text' => __('Your password must be hard for other people to guess, but easy for you to remember.'), + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 15, + ), + )); + $this->fields['password2'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Confirm your password'), + 'initial' => '', + 'widget' => 'Pluf_Form_Widget_PasswordInput', + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 15, + ), + )); + + + + } + + /** + * Just a simple control. + */ + public function clean_key() + { + $this->cleaned_data['key'] = trim($this->cleaned_data['key']); + $error = __('We are sorry but this confirmation key is not valid. Maybe you should directly copy/paste it from your confirmation email.'); + if (false === ($email_id=IDF_Form_RegisterInputKey::checkKeyHash($this->cleaned_data['key']))) { + throw new Pluf_Form_Invalid($error); + } + $guser = new Pluf_User(); + $sql = new Pluf_SQL('email=%s AND id=%s', $email_id); + $users = $guser->getList(array('filter' => $sql->gen())); + if ($users->count() != 1) { + throw new Pluf_Form_Invalid($error); + } + if ($users[0]->active) { + throw new Pluf_Form_Invalid(sprintf(__('This account has already been confirmed. Maybe should you try to recover your password.'), Pluf_HTTP_URL_urlForView('IDF_Views::passwordRecoveryAsk'))); + } + $this->_user_id = $email_id[1]; + return $this->cleaned_data['key']; + } + + /** + * Check the passwords. + */ + public function clean() + { + if ($this->cleaned_data['password'] != $this->cleaned_data['password2']) { + throw new Pluf_Form_Invalid(__('The two passwords must be the same.')); + } + return $this->cleaned_data; + } + + /** + * Save the model in the database. + * + * @param bool Commit in the database or not. If not, the object + * is returned but not saved in the database. + * @return Object Model with data set from the form. + */ + function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save an invalid form.')); + } + $this->_user->setFromFormData($this->cleaned_data); + $this->_user->active = true; + $this->_user->administrator = false; + $this->_user->staff = false; + if ($commit) { + $this->_user->update(); + /** + * [signal] + * + * Pluf_User::passwordUpdated + * + * [sender] + * + * IDF_Form_RegisterConfirmation + * + * [description] + * + * This signal is sent when the user updated his + * password from his account page. + * + * [parameters] + * + * array('user' => $user) + * + */ + $params = array('user' => $this->_user); + Pluf_Signal::send('Pluf_User::passwordUpdated', + 'IDF_Form_RegisterConfirmation', $params); + } + return $this->_user; + } +} diff --git a/indefero/src/IDF/Form/RegisterInputKey.php b/indefero/src/IDF/Form/RegisterInputKey.php new file mode 100644 index 0000000..8b5a7a9 --- /dev/null +++ b/indefero/src/IDF/Form/RegisterInputKey.php @@ -0,0 +1,96 @@ +fields['key'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Your confirmation key'), + 'initial' => '', + 'widget_attrs' => array( + 'size' => 50, + ), + )); + } + + /** + * Validate the key. + */ + public function clean_key() + { + $this->cleaned_data['key'] = trim($this->cleaned_data['key']); + $error = __('We are sorry but this confirmation key is not valid. Maybe you should directly copy/paste it from your confirmation email.'); + if (false === ($email_id=self::checkKeyHash($this->cleaned_data['key']))) { + throw new Pluf_Form_Invalid($error); + } + $guser = new Pluf_User(); + $sql = new Pluf_SQL('email=%s AND id=%s', $email_id); + if ($guser->getCount(array('filter' => $sql->gen())) != 1) { + throw new Pluf_Form_Invalid($error); + } + return $this->cleaned_data['key']; + } + + /** + * Save the model in the database. + * + * @param bool Commit in the database or not. If not, the object + * is returned but not saved in the database. + * @return string Url to redirect to the form. + */ + function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save an invalid form.')); + } + return Pluf_HTTP_URL_urlForView('IDF_Views::registerConfirmation', + array($this->cleaned_data['key'])); + } + + /** + * Return false or an array with the email and id. + * + * This is a static function to be reused by other forms. + * + * @param string Confirmation key + * @return mixed Either false or array(email, id) + */ + public static function checkKeyHash($key) + { + $hash = substr($key, 0, 2); + $encrypted = substr($key, 2); + if ($hash != substr(md5(Pluf::f('secret_key').$encrypted), 0, 2)) { + return false; + } + $cr = new Pluf_Crypt(md5(Pluf::f('secret_key'))); + return explode(':', $cr->decrypt($encrypted), 2); + } +} diff --git a/indefero/src/IDF/Form/ReviewCreate.php b/indefero/src/IDF/Form/ReviewCreate.php new file mode 100644 index 0000000..889ace5 --- /dev/null +++ b/indefero/src/IDF/Form/ReviewCreate.php @@ -0,0 +1,255 @@ +user = $extra['user']; + $this->project = $extra['project']; + if ($this->user->hasPerm('IDF.project-owner', $this->project) + or $this->user->hasPerm('IDF.project-member', $this->project)) { + $this->show_full = true; + } + $this->fields['summary'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Summary'), + 'initial' => '', + 'widget_attrs' => array( + 'maxlength' => 200, + 'size' => 67, + ), + )); + $this->fields['description'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Description'), + 'initial' => '', + 'widget' => 'Pluf_Form_Widget_TextareaInput', + 'widget_attrs' => array( + 'cols' => 58, + 'rows' => 7, + ), + )); + $sql = new Pluf_SQL('project=%s', array($this->project->id)); + $commits = Pluf::factory('IDF_Commit')->getList(array('order' => 'creation_dtime DESC', + 'nb' => 10, + 'filter' => $sql->gen())); + $choices = array(); + foreach ($commits as $c) { + $id = (strlen($c->scm_id) > 10) ? substr($c->scm_id, 0, 10) : $c->scm_id; + $ext = (mb_strlen($c->summary) > 50) ? mb_substr($c->summary, 0, 47).'...' : $c->summary; + $choices[$id.' - '.$ext] = $c->scm_id; + } + $this->fields['commit'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Commit'), + 'initial' => '', + 'widget' => 'Pluf_Form_Widget_SelectInput', + 'widget_attrs' => array( + 'choices' => $choices, + ), + )); + $upload_path = Pluf::f('upload_issue_path', false); + if (false === $upload_path) { + throw new Pluf_Exception_SettingError(__('The "upload_issue_path" configuration variable was not set.')); + } + $md5 = md5(rand().microtime().Pluf_Utils::getRandomString()); + // We add .dummy to try to mitigate security issues in the + // case of someone allowing the upload path to be accessible + // to everybody. + $filename = substr($md5, 0, 2).'/'.substr($md5, 2, 2).'/'.substr($md5, 4).'/%s.dummy'; + $this->fields['patch'] = new Pluf_Form_Field_File( + array('required' => true, + 'label' => __('Patch'), + 'move_function_params' => + array('upload_path' => $upload_path, + 'upload_path_create' => true, + 'file_name' => $filename, + ) + ) + ); + if ($this->show_full) { + $this->fields['status'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Status'), + 'initial' => 'New', + 'widget_attrs' => array( + 'maxlength' => 20, + 'size' => 15, + ), + )); + } + } + + public function clean_patch() + { + $diff = new IDF_Diff(file_get_contents(Pluf::f('upload_issue_path').'/' + .$this->cleaned_data['patch'])); + $diff->parse(); + if (count($diff->files) == 0) { + throw new Pluf_Form_Invalid(__('We were not able to parse your patch. Please provide a valid patch.')); + } + return $this->cleaned_data['patch']; + } + + public function clean_commit() + { + $commit = self::findCommit($this->cleaned_data['commit']); + if (null == $commit) { + throw new Pluf_Form_Invalid(__('You provided an invalid commit.')); + } + return $this->cleaned_data['commit']; + } + + /** + * Validate the interconnection in the form. + */ + public function clean() + { + return $this->cleaned_data; + } + + function clean_status() + { + // Check that the status is in the list of official status + $tags = $this->project->getTagsFromConfig('labels_issue_open', + IDF_Form_IssueTrackingConf::init_open, + 'Status'); + $tags = array_merge($this->project->getTagsFromConfig('labels_issue_closed', + IDF_Form_IssueTrackingConf::init_closed, + 'Status') + , $tags); + $found = false; + foreach ($tags as $tag) { + if ($tag->name == trim($this->cleaned_data['status'])) { + $found = true; + break; + } + } + if (!$found) { + throw new Pluf_Form_Invalid(__('You provided an invalid status.')); + } + return $this->cleaned_data['status']; + } + + /** + * Clean the attachments post failure. + */ + function failed() + { + $upload_path = Pluf::f('upload_issue_path', false); + if ($upload_path == false) return; + if (!empty($this->cleaned_data['patch']) and + file_exists($upload_path.'/'.$this->cleaned_data['patch'])) { + @unlink($upload_path.'/'.$this->cleaned_data['patch']); + } + } + + /** + * Save the model in the database. + * + * @param bool Commit in the database or not. If not, the object + * is returned but not saved in the database. + * @return Object Model with data set from the form. + */ + function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save the model from an invalid form.')); + } + // Create the review + $review = new IDF_Review(); + $review->project = $this->project; + $review->summary = $this->cleaned_data['summary']; + $review->submitter = $this->user; + if (!isset($this->cleaned_data['status'])) { + $this->cleaned_data['status'] = 'New'; + } + $review->status = IDF_Tag::add(trim($this->cleaned_data['status']), $this->project, 'Status'); + $review->create(); + // add the first patch + $patch = new IDF_Review_Patch(); + $patch->review = $review; + $patch->summary = __('Initial patch to be reviewed.'); + $patch->description = $this->cleaned_data['description']; + $patch->commit = self::findCommit($this->cleaned_data['commit']); + $patch->patch = $this->cleaned_data['patch']; + $patch->create(); + $patch->notify($this->project->getConf()); + /** + * [signal] + * + * IDF_Review::create + * + * [sender] + * + * IDF_Form_ReviewCreate + * + * [description] + * + * This signal allows an application to perform a set of tasks + * just after the creation of a review and the notification. + * + * [parameters] + * + * array('review' => $review, + * 'patch' => $patch); + * + */ + $params = array('review' => $review, + 'patch' => $patch); + Pluf_Signal::send('IDF_Review::create', 'IDF_Form_ReviewCreate', + $params); + return $review; + } + + /** + * Based on the given string, try to find the matching commit. + * + * If no user found, simply returns null. + * + * @param string Commit + * @return IDF_Commit or null + */ + public static function findCommit($string) + { + $string = trim($string); + if (strlen($string) == 0) return null; + $gc = new IDF_Commit(); + $sql = new Pluf_SQL('scm_id=%s', array($string)); + $gcs = $gc->getList(array('filter' => $sql->gen())); + if ($gcs->count() > 0) { + return $gcs[0]; + } + return null; + } +} diff --git a/indefero/src/IDF/Form/ReviewFileComment.php b/indefero/src/IDF/Form/ReviewFileComment.php new file mode 100644 index 0000000..a85f6d6 --- /dev/null +++ b/indefero/src/IDF/Form/ReviewFileComment.php @@ -0,0 +1,181 @@ +files = $extra['files']; + $this->patch = $extra['patch']; + $this->user = $extra['user']; + $this->project = $extra['project']; + + foreach ($this->files as $filename => $def) { + $this->fields[md5($filename)] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Comment'), + 'initial' => '', + 'widget' => 'Pluf_Form_Widget_TextareaInput', + 'widget_attrs' => array( + 'cols' => 58, + 'rows' => 9, + ), + )); + } + $this->fields['content'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('General comment'), + 'initial' => '', + 'widget' => 'Pluf_Form_Widget_TextareaInput', + 'widget_attrs' => array( + 'cols' => 58, + 'rows' => 9, + ), + )); + if ($this->user->hasPerm('IDF.project-owner', $this->project) + or $this->user->hasPerm('IDF.project-member', $this->project)) { + $this->show_full = true; + } else { + $this->show_full = false; + } + if ($this->show_full) { + $this->fields['summary'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Summary'), + 'initial' => $this->patch->get_review()->summary, + 'widget_attrs' => array( + 'maxlength' => 200, + 'size' => 67, + ), + )); + + $this->fields['status'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Status'), + 'initial' => $this->patch->get_review()->get_status()->name, + 'widget_attrs' => array( + 'maxlength' => 20, + 'size' => 15, + ), + )); + } + } + + + /** + * Validate the interconnection in the form. + */ + public function clean() + { + $isOk = false; + + foreach($this->files as $filename => $def) { + $this->cleaned_data[md5($filename)] = trim($this->cleaned_data[md5($filename)]); + if(!empty($this->cleaned_data[md5($filename)])) { + $isOk = true; + } + } + + if(!empty($this->cleaned_data['content'])) { + $isOk = true; + } + + if (!$isOk) { + throw new Pluf_Form_Invalid(__('You need to provide your general comment about the proposal, or comments on at least one file.')); + } + + return $this->cleaned_data; + } + + function clean_content() + { + $content = trim($this->cleaned_data['content']); + if(empty($content)) { + if ($this->fields['status']->initial != $this->fields['status']->value) { + return __('The status have been updated.'); + } + } else { + return $content; + } + + throw new Pluf_Form_Invalid(__('This field is required.')); + } + + /** + * Save the model in the database. + * + * @param bool Commit in the database or not. If not, the object + * is returned but not saved in the database. + * @return Object Model with data set from the form. + */ + function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save the model from an invalid form.')); + } + // create a base comment + $bc = new IDF_Review_Comment(); + $bc->patch = $this->patch; + $bc->submitter = $this->user; + $bc->content = $this->cleaned_data['content']; + $review = $this->patch->get_review(); + if ($this->show_full) { + // Compare between the old and the new data + // Status, summary + $changes = array(); + $status = IDF_Tag::add(trim($this->cleaned_data['status']), $this->project, 'Status'); + if ($status->id != $this->patch->get_review()->status) { + $changes['st'] = $status->name; + } + if (trim($this->patch->get_review()->summary) != trim($this->cleaned_data['summary'])) { + $changes['su'] = trim($this->cleaned_data['summary']); + } + // Update the review + $review->summary = trim($this->cleaned_data['summary']); + $review->status = $status; + $bc->changes = $changes; + } + $bc->create(); + foreach ($this->files as $filename => $def) { + if (!empty($this->cleaned_data[md5($filename)])) { + // Add a comment. + $c = new IDF_Review_FileComment(); + $c->comment = $bc; + $c->cfile = $filename; + $c->content = $this->cleaned_data[md5($filename)]; + $c->create(); + } + } + $review->update(); // reindex and put up in the list. + return $bc; + } +} diff --git a/indefero/src/IDF/Form/SourceConf.php b/indefero/src/IDF/Form/SourceConf.php new file mode 100644 index 0000000..5a9a183 --- /dev/null +++ b/indefero/src/IDF/Form/SourceConf.php @@ -0,0 +1,62 @@ +conf = $extra['conf']; + if ($extra['remote_svn']) { + $this->fields['svn_username'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Repository username'), + 'initial' => $this->conf->getVal('svn_username', ''), + 'widget_attrs' => array('size' => '15'), + )); + + $this->fields['svn_password'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Repository password'), + 'initial' => $this->conf->getVal('svn_password', ''), + 'widget' => 'Pluf_Form_Widget_PasswordInput', + )); + } + $this->fields['webhook_url'] = new Pluf_Form_Field_Url( + array('required' => false, + 'label' => __('Webhook URL'), + 'initial' => $this->conf->getVal('webhook_url', ''), + 'widget_attrs' => array('size' => 35), + )); + + } +} + + diff --git a/indefero/src/IDF/Form/TabsConf.php b/indefero/src/IDF/Form/TabsConf.php new file mode 100644 index 0000000..d41863b --- /dev/null +++ b/indefero/src/IDF/Form/TabsConf.php @@ -0,0 +1,149 @@ +conf = $extra['conf']; + $this->project = $extra['project']; + + $ak = array('downloads_access_rights' => __('Downloads'), + 'review_access_rights' => __('Code Review'), + 'wiki_access_rights' => __('Documentation'), + 'source_access_rights' => __('Source'), + 'issues_access_rights' => __('Issues'),); + foreach ($ak as $key=>$label) { + $this->fields[$key] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => $label, + 'initial' => $this->conf->getVal($key, 'all'), + 'widget_attrs' => array('choices' => + array( + __('Open to all') => 'all', + __('Signed in users') => 'login', + __('Project members') => 'members', + __('Project owners') => 'owners', + __('Closed') => 'none', + ) + ), + 'widget' => 'Pluf_Form_Widget_SelectInput', + )); + } + + $sections = array( + 'downloads_notification', + 'review_notification', + 'wiki_notification', + 'source_notification', + 'issues_notification', + ); + + foreach ($sections as $section) { + $this->fields[$section.'_owners_enabled'] = new Pluf_Form_Field_Boolean( + array('required' => false, + 'label' => __('Project owners'), + 'initial' => $this->conf->getVal($section.'_owners_enabled', false), + 'widget' => 'Pluf_Form_Widget_CheckboxInput', + )); + $this->fields[$section.'_members_enabled'] = new Pluf_Form_Field_Boolean( + array('required' => false, + 'label' => __('Project members'), + 'initial' => $this->conf->getVal($section.'_members_enabled', false), + 'widget' => 'Pluf_Form_Widget_CheckboxInput', + )); + $this->fields[$section.'_email_enabled'] = new Pluf_Form_Field_Boolean( + array('required' => false, + 'label' => __('Others'), + 'initial' => $this->conf->getVal($section.'_email_enabled', false), + 'widget' => 'Pluf_Form_Widget_CheckboxInput', + )); + if ($this->conf->getVal($section.'_email_enabled', false)) { + $attrs['readonly'] = 'readonly'; + } + $this->fields[$section.'_email'] = new IDF_Form_Field_EmailList( + array('required' => false, + 'label' => null, + 'initial' => $this->conf->getVal($section.'_email', ''), + 'widget_attrs' => array('size' => 20), + )); + } + + $this->fields['private_project'] = new Pluf_Form_Field_Boolean( + array('required' => false, + 'label' => __('Private project'), + 'initial' => $this->project->private, + 'widget' => 'Pluf_Form_Widget_CheckboxInput', + )); + $this->fields['authorized_users'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Extra authorized users'), + 'widget_attrs' => array('rows' => 7, + 'cols' => 40), + 'widget' => 'Pluf_Form_Widget_TextareaInput', + )); + } + + public function clean_authorized_users() + { + return IDF_Form_MembersConf::checkBadLogins($this->cleaned_data['authorized_users']); + } + + public function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save the model from an invalid form.')); + } + // remove all the permissions + $perm = Pluf_Permission::getFromString('IDF.project-authorized-user'); + $cm = $this->project->getMembershipData(); + $guser = new Pluf_User(); + foreach ($cm['authorized'] as $user) { + Pluf_RowPermission::remove($user, $this->project, $perm); + } + if ($this->cleaned_data['private_project']) { + foreach (preg_split("/\015\012|\015|\012|\,/", $this->cleaned_data['authorized_users'], -1, PREG_SPLIT_NO_EMPTY) as $login) { + $sql = new Pluf_SQL('login=%s', array(trim($login))); + $users = $guser->getList(array('filter'=>$sql->gen())); + if ($users->count() == 1) { + Pluf_RowPermission::add($users[0], $this->project, $perm); + } + } + $this->project->private = 1; + } else { + $this->project->private = 0; + } + $this->project->update(); + $this->project->membershipsUpdated(); + } +} + + + diff --git a/indefero/src/IDF/Form/UpdateUpload.php b/indefero/src/IDF/Form/UpdateUpload.php new file mode 100644 index 0000000..cf653fe --- /dev/null +++ b/indefero/src/IDF/Form/UpdateUpload.php @@ -0,0 +1,177 @@ +user = $extra['user']; + $this->project = $extra['project']; + $this->upload = $extra['upload']; + + $this->fields['summary'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Summary'), + 'initial' => $this->upload->summary, + 'widget_attrs' => array( + 'maxlength' => 200, + 'size' => 67, + ), + )); + $this->fields['changelog'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Description'), + 'initial' => $this->upload->changelog, + 'widget' => 'Pluf_Form_Widget_TextareaInput', + 'widget_attrs' => array( + 'cols' => 58, + 'rows' => 13, + ), + )); + $tags = $this->upload->get_tags_list(); + for ($i=1;$i<7;$i++) { + $initial = ''; + if (isset($tags[$i-1])) { + if ($tags[$i-1]->class != 'Other') { + $initial = (string) $tags[$i-1]; + } else { + $initial = $tags[$i-1]->name; + } + } + $this->fields['label'.$i] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Labels'), + 'initial' => $initial, + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 20, + ), + )); + } + } + + /** + * Validate the interconnection in the form. + */ + public function clean() + { + $conf = new IDF_Conf(); + $conf->setProject($this->project); + $onemax = array(); + foreach (explode(',', $conf->getVal('labels_download_one_max', IDF_Form_UploadConf::init_one_max)) as $class) { + if (trim($class) != '') { + $onemax[] = mb_strtolower(trim($class)); + } + } + $count = array(); + for ($i=1;$i<7;$i++) { + $this->cleaned_data['label'.$i] = trim($this->cleaned_data['label'.$i]); + if (strpos($this->cleaned_data['label'.$i], ':') !== false) { + list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2); + list($class, $name) = array(mb_strtolower(trim($class)), + trim($name)); + } else { + $class = 'other'; + $name = $this->cleaned_data['label'.$i]; + } + if (!isset($count[$class])) $count[$class] = 1; + else $count[$class] += 1; + if (in_array($class, $onemax) and $count[$class] > 1) { + if (!isset($this->errors['label'.$i])) $this->errors['label'.$i] = array(); + $this->errors['label'.$i][] = sprintf(__('You cannot provide more than one label from the %s class to an issue.'), $class); + throw new Pluf_Form_Invalid(__('You provided an invalid label.')); + } + } + return $this->cleaned_data; + } + + /** + * Save the model in the database. + * + * @param bool Commit in the database or not. If not, the object + * is returned but not saved in the database. + * @return Object Model with data set from the form. + */ + function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save the model from an invalid form.')); + } + // Add a tag for each label + $tags = array(); + for ($i=1;$i<7;$i++) { + if (strlen($this->cleaned_data['label'.$i]) > 0) { + if (strpos($this->cleaned_data['label'.$i], ':') !== false) { + list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2); + list($class, $name) = array(trim($class), trim($name)); + } else { + $class = 'Other'; + $name = trim($this->cleaned_data['label'.$i]); + } + $tag = IDF_Tag::add($name, $this->project, $class); + $tags[] = $tag->id; + } + } + // Create the upload + $this->upload->summary = trim($this->cleaned_data['summary']); + $this->upload->changelog = trim($this->cleaned_data['changelog']); + $this->upload->modif_dtime = gmdate('Y-m-d H:i:s'); + $this->upload->update(); + $this->upload->batchAssoc('IDF_Tag', $tags); + + // Send the notification + $this->upload->notify($this->project->getConf(), false); + /** + * [signal] + * + * IDF_Upload::update + * + * [sender] + * + * IDF_Form_UpdateUpload + * + * [description] + * + * This signal allows an application to perform a set of tasks + * just after the update of an uploaded file. + * + * [parameters] + * + * array('upload' => $upload); + * + */ + $params = array('upload' => $this->upload); + Pluf_Signal::send('IDF_Upload::update', + 'IDF_Form_UpdateUpload', $params); + return $this->upload; + } +} + diff --git a/indefero/src/IDF/Form/Upload.php b/indefero/src/IDF/Form/Upload.php new file mode 100644 index 0000000..c973581 --- /dev/null +++ b/indefero/src/IDF/Form/Upload.php @@ -0,0 +1,205 @@ +user = $extra['user']; + $this->project = $extra['project']; + + $this->fields['summary'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Summary'), + 'initial' => '', + 'widget_attrs' => array( + 'maxlength' => 200, + 'size' => 67, + ), + )); + $this->fields['changelog'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Description'), + 'initial' => '', + 'widget' => 'Pluf_Form_Widget_TextareaInput', + 'widget_attrs' => array( + 'cols' => 58, + 'rows' => 13, + ), + )); + $this->fields['file'] = new Pluf_Form_Field_File( + array('required' => true, + 'label' => __('File'), + 'initial' => '', + 'max_size' => Pluf::f('max_upload_size', 2097152), + 'move_function_params' => array('upload_path' => Pluf::f('upload_path').'/'.$this->project->shortname.'/files', + 'upload_path_create' => true, + 'upload_overwrite' => false), + + )); + for ($i=1;$i<7;$i++) { + $this->fields['label'.$i] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Labels'), + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 20, + ), + )); + } + } + + + public function clean_file() + { + // FIXME: we do the same in IDF_Form_WikiResourceCreate and a couple of other places as well + $extra = strtolower(implode('|', explode(' ', Pluf::f('idf_extra_upload_ext')))); + if (strlen($extra)) $extra .= '|'; + if (!preg_match('/\.('.$extra.'png|jpg|jpeg|gif|bmp|psd|tif|aiff|asf|avi|bz2|css|doc|eps|gz|jar|mdtext|mid|mov|mp3|mpg|ogg|pdf|ppt|ps|qt|ra|ram|rm|rtf|sdd|sdw|sit|sxi|sxw|swf|tgz|txt|wav|xls|xml|war|wmv|zip)$/i', $this->cleaned_data['file'])) { + @unlink(Pluf::f('upload_path').'/'.$this->project->shortname.'/files/'.$this->cleaned_data['file']); + throw new Pluf_Form_Invalid(__('For security reasons, you cannot upload a file with this extension.')); + } + return $this->cleaned_data['file']; + } + + /** + * Validate the interconnection in the form. + */ + public function clean() + { + $conf = new IDF_Conf(); + $conf->setProject($this->project); + $onemax = array(); + foreach (explode(',', $conf->getVal('labels_download_one_max', IDF_Form_UploadConf::init_one_max)) as $class) { + if (trim($class) != '') { + $onemax[] = mb_strtolower(trim($class)); + } + } + $count = array(); + for ($i=1;$i<7;$i++) { + $this->cleaned_data['label'.$i] = trim($this->cleaned_data['label'.$i]); + if (strpos($this->cleaned_data['label'.$i], ':') !== false) { + list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2); + list($class, $name) = array(mb_strtolower(trim($class)), + trim($name)); + } else { + $class = 'other'; + $name = $this->cleaned_data['label'.$i]; + } + if (!isset($count[$class])) $count[$class] = 1; + else $count[$class] += 1; + if (in_array($class, $onemax) and $count[$class] > 1) { + if (!isset($this->errors['label'.$i])) $this->errors['label'.$i] = array(); + $this->errors['label'.$i][] = sprintf(__('You cannot provide more than one label from the %s class to a download.'), $class); + throw new Pluf_Form_Invalid(__('You provided an invalid label.')); + } + } + return $this->cleaned_data; + } + + /** + * If we have uploaded a file, but the form failed remove it. + * + */ + function failed() + { + if (!empty($this->cleaned_data['file']) + and file_exists(Pluf::f('upload_path').'/'.$this->project->shortname.'/files/'.$this->cleaned_data['file'])) { + @unlink(Pluf::f('upload_path').'/'.$this->project->shortname.'/files/'.$this->cleaned_data['file']); + } + } + + /** + * Save the model in the database. + * + * @param bool Commit in the database or not. If not, the object + * is returned but not saved in the database. + * @return Object Model with data set from the form. + */ + function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save the model from an invalid form.')); + } + // Add a tag for each label + $tags = array(); + for ($i=1;$i<7;$i++) { + if (strlen($this->cleaned_data['label'.$i]) > 0) { + if (strpos($this->cleaned_data['label'.$i], ':') !== false) { + list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2); + list($class, $name) = array(trim($class), trim($name)); + } else { + $class = 'Other'; + $name = trim($this->cleaned_data['label'.$i]); + } + $tags[] = IDF_Tag::add($name, $this->project, $class); + } + } + // Create the upload + $upload = new IDF_Upload(); + $upload->project = $this->project; + $upload->submitter = $this->user; + $upload->summary = trim($this->cleaned_data['summary']); + $upload->changelog = trim($this->cleaned_data['changelog']); + $upload->file = $this->cleaned_data['file']; + $upload->filesize = filesize(Pluf::f('upload_path').'/'.$this->project->shortname.'/files/'.$this->cleaned_data['file']); + $upload->downloads = 0; + $upload->create(); + foreach ($tags as $tag) { + $upload->setAssoc($tag); + } + // Send the notification + $upload->notify($this->project->getConf()); + /** + * [signal] + * + * IDF_Upload::create + * + * [sender] + * + * IDF_Form_Upload + * + * [description] + * + * This signal allows an application to perform a set of tasks + * just after the upload of a file and after the notification run. + * + * [parameters] + * + * array('upload' => $upload); + * + */ + $params = array('upload' => $upload); + Pluf_Signal::send('IDF_Upload::create', 'IDF_Form_Upload', + $params); + return $upload; + } +} + diff --git a/indefero/src/IDF/Form/UploadArchive.php b/indefero/src/IDF/Form/UploadArchive.php new file mode 100644 index 0000000..2ac3d3c --- /dev/null +++ b/indefero/src/IDF/Form/UploadArchive.php @@ -0,0 +1,227 @@ +user = $extra['user']; + $this->project = $extra['project']; + + $this->fields['archive'] = new Pluf_Form_Field_File( + array('required' => true, + 'label' => __('Archive file'), + 'initial' => '', + 'max_size' => Pluf::f('max_upload_archive_size', 20971520), + 'move_function_params' => array( + 'upload_path' => Pluf::f('upload_path').'/'.$this->project->shortname.'/archives', + 'upload_path_create' => true, + 'upload_overwrite' => true, + ))); + } + + + public function clean_archive() + { + $this->archiveHelper = new IDF_Form_UploadArchiveHelper( + Pluf::f('upload_path').'/'.$this->project->shortname.'/archives/'.$this->cleaned_data['archive']); + + // basic archive validation + $this->archiveHelper->validate(); + + // extension validation + $fileNames = $this->archiveHelper->getEntryNames(); + foreach ($fileNames as $fileName) { + $extra = strtolower(implode('|', explode(' ', Pluf::f('idf_extra_upload_ext')))); + if (strlen($extra)) $extra .= '|'; + if (!preg_match('/\.('.$extra.'png|jpg|jpeg|gif|bmp|psd|tif|aiff|asf|avi|bz2|css|doc|eps|gz|jar|mdtext|mid|mov|mp3|mpg|ogg|pdf|ppt|ps|qt|ra|ram|rm|rtf|sdd|sdw|sit|sxi|sxw|swf|tgz|txt|wav|xls|xml|war|wmv|zip)$/i', $fileName)) { + @unlink(Pluf::f('upload_path').'/'.$this->project->shortname.'/files/'.$this->cleaned_data['archive']); + throw new Pluf_Form_Invalid(sprintf(__('For security reasons, you cannot upload a file (%s) with this extension.'), $fileName)); + } + } + + // label and file name validation + $conf = new IDF_Conf(); + $conf->setProject($this->project); + $onemax = array(); + foreach (explode(',', $conf->getVal('labels_download_one_max', IDF_Form_UploadConf::init_one_max)) as $class) { + if (trim($class) != '') { + $onemax[] = mb_strtolower(trim($class)); + } + } + + foreach ($fileNames as $fileName) { + $meta = $this->archiveHelper->getMetaData($fileName); + $count = array(); + foreach ($meta['labels'] as $label) { + $label = trim($label); + if (strpos($label, ':') !== false) { + list($class, $name) = explode(':', $label, 2); + list($class, $name) = array(mb_strtolower(trim($class)), + trim($name)); + } else { + $class = 'other'; + $name = $label; + } + if (!isset($count[$class])) $count[$class] = 1; + else $count[$class] += 1; + if (in_array($class, $onemax) and $count[$class] > 1) { + throw new Pluf_Form_Invalid( + sprintf(__('You cannot provide more than label from the %1$s class to a download (%2$s).'), $class, $name) + ); + } + } + + $sql = new Pluf_SQL('file=%s AND project=%s', array($fileName, $this->project->id)); + $upload = Pluf::factory('IDF_Upload')->getOne(array('filter' => $sql->gen())); + + $meta = $this->archiveHelper->getMetaData($fileName); + if ($upload != null && $meta['replaces'] !== $fileName) { + throw new Pluf_Form_Invalid( + sprintf(__('A file with the name "%s" has already been uploaded and is not marked to be replaced.'), $fileName)); + } + } + + return $this->cleaned_data['archive']; + } + + /** + * If we have uploaded a file, but the form failed remove it. + * + */ + function failed() + { + if (!empty($this->cleaned_data['archive']) + and file_exists(Pluf::f('upload_path').'/'.$this->project->shortname.'/archives/'.$this->cleaned_data['archive'])) { + @unlink(Pluf::f('upload_path').'/'.$this->project->shortname.'/archives/'.$this->cleaned_data['archive']); + } + } + + /** + * Save the model in the database. + * + * @param bool Commit in the database or not. If not, the object + * is returned but not saved in the database. + */ + function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save the model from an invalid form.')); + } + + $uploadDir = Pluf::f('upload_path').'/'.$this->project->shortname.'/files/'; + $fileNames = $this->archiveHelper->getEntryNames(); + + foreach ($fileNames as $fileName) { + $meta = $this->archiveHelper->getMetaData($fileName); + + // add a tag for each label + $tags = array(); + foreach ($meta['labels'] as $label) { + $label = trim($label); + if (strlen($label) > 0) { + if (strpos($label, ':') !== false) { + list($class, $name) = explode(':', $label, 2); + list($class, $name) = array(trim($class), trim($name)); + } else { + $class = 'Other'; + $name = $label; + } + $tags[] = IDF_Tag::add($name, $this->project, $class); + } + } + + // process a possible replacement + if (!empty($meta['replaces'])) { + $sql = new Pluf_SQL('file=%s AND project=%s', array($meta['replaces'], $this->project->id)); + $oldUpload = Pluf::factory('IDF_Upload')->getOne(array('filter' => $sql->gen())); + + if ($oldUpload) { + if ($meta['replaces'] === $fileName) { + $oldUpload->delete(); + } else { + $tags = $this->project->getTagsFromConfig('labels_download_predefined', + IDF_Form_UploadConf::init_predefined); + // the deprecate tag is - by definition - always the last one + $deprecatedTag = array_pop($tags); + $oldUpload->setAssoc($deprecatedTag); + } + } + } + + // extract the file + $this->archiveHelper->extract($fileName, $uploadDir); + + // create the upload + $upload = new IDF_Upload(); + $upload->project = $this->project; + $upload->submitter = $this->user; + $upload->summary = trim($meta['summary']); + $upload->changelog = trim($meta['description']); + $upload->file = $fileName; + $upload->filesize = filesize($uploadDir.$fileName); + $upload->downloads = 0; + $upload->create(); + foreach ($tags as $tag) { + $upload->setAssoc($tag); + } + + // send the notification + $upload->notify($this->project->getConf()); + /** + * [signal] + * + * IDF_Upload::create + * + * [sender] + * + * IDF_Form_Upload + * + * [description] + * + * This signal allows an application to perform a set of tasks + * just after the upload of a file and after the notification run. + * + * [parameters] + * + * array('upload' => $upload); + * + */ + $params = array('upload' => $upload); + Pluf_Signal::send('IDF_Upload::create', 'IDF_Form_Upload', + $params); + } + + // finally unlink the uploaded archive + @unlink(Pluf::f('upload_path').'/'.$this->project->shortname.'/archives/'.$this->cleaned_data['archive']); + } +} + diff --git a/indefero/src/IDF/Form/UploadArchiveHelper.php b/indefero/src/IDF/Form/UploadArchiveHelper.php new file mode 100644 index 0000000..50f8aad --- /dev/null +++ b/indefero/src/IDF/Form/UploadArchiveHelper.php @@ -0,0 +1,158 @@ +file = $file; + } + + /** + * Validates the archive; throws a invalid form exception in case the + * archive contains invalid data or cannot be read. + */ + public function validate() + { + if (!file_exists($this->file)) { + throw new Pluf_Form_Invalid(__('The archive does not exist.')); + } + + $za = new ZipArchive(); + $res = $za->open($this->file); + if ($res !== true) { + throw new Pluf_Form_Invalid( + sprintf(__('The archive could not be read (code %d).'), $res)); + } + + $manifest = $za->getFromName('manifest.xml'); + if ($manifest === false) { + throw new Pluf_Form_Invalid(__('The archive does not contain a manifest.xml.')); + } + + libxml_use_internal_errors(true); + $xml = @simplexml_load_string($manifest); + if ($xml === false) { + $error = libxml_get_last_error(); + throw new Pluf_Form_Invalid( + sprintf(__('The archive\'s manifest is invalid: %s'), $error->message)); + } + + foreach (@$xml->file as $idx => $file) + { + $entry = array( + 'name' => (string)@$file->name, + 'summary' => (string)@$file->summary, + 'description' => (string)@$file->description, + 'replaces' => (string)@$file->replaces, + 'labels' => array(), + 'stream' => null + ); + + if (empty($entry['name'])) { + throw new Pluf_Form_Invalid( + sprintf(__('The entry %d in the manifest is missing a file name.'), $idx)); + } + + if (empty($entry['summary'])) { + throw new Pluf_Form_Invalid( + sprintf(__('The entry %d in the manifest is missing a summary.'), $idx)); + } + + if ($entry['name'] === 'manifest.xml') { + throw new Pluf_Form_Invalid(__('The manifest must not reference itself.')); + } + + if ($za->locateName($entry['name']) === false) { + throw new Pluf_Form_Invalid( + sprintf(__('The entry %s in the manifest does not exist in the archive.'), $entry['name'])); + } + + if (in_array($entry['name'], $this->entries)) { + throw new Pluf_Form_Invalid( + sprintf(__('The entry %s in the manifest is referenced more than once.'), $entry['name'])); + } + + if ($file->labels) { + foreach (@$file->labels->label as $label) { + $entry['labels'][] = (string)$label; + } + } + + // FIXME: remove this once we allow more than six labels everywhere + if (count($entry['labels']) > 6) { + throw new Pluf_Form_Invalid( + sprintf(__('The entry %s in the manifest has more than the six allowed labels set.'), $entry['name'])); + } + + $this->entries[$entry['name']] = $entry; + } + + $za->close(); + } + + /** + * Returns all entry names + * + * @return array of string + */ + public function getEntryNames() + { + return array_keys($this->entries); + } + + /** + * Returns meta data for the given entry + * + * @param string $name + * @throws Exception + */ + public function getMetaData($name) + { + if (!array_key_exists($name, $this->entries)) { + throw new Exception('unknown file ' . $name); + } + return $this->entries[$name]; + } + + /** + * Extracts the file entry $name at $path + * + * @param string $name + * @param string $path + * @throws Exception + */ + public function extract($name, $path) + { + if (!array_key_exists($name, $this->entries)) { + throw new Exception('unknown file ' . $name); + } + $za = new ZipArchive(); + $za->open($this->file); + $za->extractTo($path, $name); + $za->close(); + } +} diff --git a/indefero/src/IDF/Form/UploadConf.php b/indefero/src/IDF/Form/UploadConf.php new file mode 100644 index 0000000..eec6788 --- /dev/null +++ b/indefero/src/IDF/Form/UploadConf.php @@ -0,0 +1,78 @@ +fields['labels_download_predefined'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Predefined download labels'), + 'initial' => self::init_predefined, + 'widget_attrs' => array('rows' => 13, + 'cols' => 75), + 'widget' => 'Pluf_Form_Widget_TextareaInput', + )); + + $this->fields['labels_download_one_max'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Each download may have at most one label with each of these classes'), + 'initial' => self::init_one_max, + 'widget_attrs' => array('size' => 60), + )); + + $this->conf = $extra['conf']; + $this->fields['upload_webhook_url'] = new Pluf_Form_Field_Url( + array('required' => false, + 'label' => __('Webhook URL'), + 'initial' => $this->conf->getVal('upload_webhook_url', ''), + 'widget_attrs' => array('size' => 60), + )); + + } +} + + diff --git a/indefero/src/IDF/Form/UserAccount.php b/indefero/src/IDF/Form/UserAccount.php new file mode 100644 index 0000000..37ba62b --- /dev/null +++ b/indefero/src/IDF/Form/UserAccount.php @@ -0,0 +1,469 @@ +user = $extra['user']; + $user_data = IDF_UserData::factory($this->user); + + $this->fields['first_name'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('First name'), + 'initial' => $this->user->first_name, + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 15, + ), + )); + $this->fields['last_name'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Last name'), + 'initial' => $this->user->last_name, + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 20, + ), + )); + + $this->fields['email'] = new Pluf_Form_Field_Email( + array('required' => true, + 'label' => __('Your email'), + 'initial' => $this->user->email, + 'help_text' => __('If you change your email address, an email will be sent to the new address to confirm it.'), + )); + + $this->fields['language'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Language'), + 'initial' => $this->user->language, + 'widget' => 'Pluf_Form_Widget_SelectInput', + 'widget_attrs' => array( + 'choices' => + Pluf_L10n::getInstalledLanguages() + ), + )); + + $this->fields['password'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Your password'), + 'initial' => '', + 'widget' => 'Pluf_Form_Widget_PasswordInput', + 'help_text' => Pluf_Template::markSafe(__('Leave blank if you do not want to change your password.').'
'.__('Your password must be hard for other people to find it, but easy for you to remember.')), + 'widget_attrs' => array( + 'autocomplete' => 'off', + 'maxlength' => 50, + 'size' => 15, + ), + )); + $this->fields['password2'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Confirm your password'), + 'initial' => '', + 'widget' => 'Pluf_Form_Widget_PasswordInput', + 'widget_attrs' => array( + 'autocomplete' => 'off', + 'maxlength' => 50, + 'size' => 15, + ), + )); + + $this->fields['description'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Description'), + 'initial' => $user_data->description, + 'widget_attrs' => array('rows' => 3, + 'cols' => 40), + 'widget' => 'Pluf_Form_Widget_TextareaInput', + )); + + $this->fields['twitter'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Twitter username'), + 'initial' => $user_data->twitter, + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 15, + ), + )); + + $this->fields['public_email'] = new Pluf_Form_Field_Email( + array('required' => false, + 'label' => __('Public email address'), + 'initial' => $user_data->public_email, + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 15, + ), + )); + + $this->fields['website'] = new Pluf_Form_Field_Url( + array('required' => false, + 'label' => __('Website URL'), + 'initial' => $user_data->website, + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 15, + ), + )); + + $this->fields['custom_avatar'] = new Pluf_Form_Field_File( + array('required' => false, + 'label' => __('Upload custom avatar'), + 'initial' => '', + 'max_size' => Pluf::f('max_upload_size', 2097152), + 'move_function_params' => array('upload_path' => Pluf::f('upload_path').'/avatars', + 'upload_path_create' => true, + 'upload_overwrite' => true, + 'file_name' => 'user_'.$this->user->id.'_%s'), + 'help_text' => __('An image file with a width and height not larger than 60 pixels (bigger images are scaled down).'), + )); + + $this->fields['remove_custom_avatar'] = new Pluf_Form_Field_Boolean( + array('required' => false, + 'label' => __('Remove custom avatar'), + 'initial' => false, + 'widget' => 'Pluf_Form_Widget_CheckboxInput', + 'widget_attrs' => array(), + 'help_text' => __('Tick this to delete the custom avatar.'), + )); + + $this->fields['public_key'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Add a public key'), + 'initial' => '', + 'widget_attrs' => array('rows' => 3, + 'cols' => 40), + 'widget' => 'Pluf_Form_Widget_TextareaInput', + 'help_text' => __('Paste an SSH or monotone public key. Be careful to not provide your private key here!') + )); + + $this->fields['secondary_mail'] = new Pluf_Form_Field_Email( + array('required' => false, + 'label' => __('Add a secondary email address'), + 'initial' => '', + 'help_text' => __('You will get an email to confirm that you own the address you specify.'), + )); + } + + private function send_validation_mail($new_email, $secondary_mail=false) + { + if ($secondary_mail) { + $type = "secondary"; + } else { + $type = "primary"; + } + $cr = new Pluf_Crypt(md5(Pluf::f('secret_key'))); + $encrypted = trim($cr->encrypt($new_email.':'.$this->user->id.':'.time().':'.$type), '~'); + $key = substr(md5(Pluf::f('secret_key').$encrypted), 0, 2).$encrypted; + $url = Pluf::f('url_base').Pluf_HTTP_URL_urlForView('IDF_Views_User::changeEmailDo', array($key), array(), false); + $urlik = Pluf::f('url_base').Pluf_HTTP_URL_urlForView('IDF_Views_User::changeEmailInputKey', array(), array(), false); + $context = new Pluf_Template_Context( + array('key' => Pluf_Template::markSafe($key), + 'url' => Pluf_Template::markSafe($url), + 'urlik' => Pluf_Template::markSafe($urlik), + 'email' => $new_email, + 'user'=> $this->user, + ) + ); + $tmpl = new Pluf_Template('idf/user/changeemail-email.txt'); + $text_email = $tmpl->render($context); + $email = new Pluf_Mail(Pluf::f('from_email'), $new_email, + __('Confirm your new email address.')); + $email->addTextMessage($text_email); + $email->sendMail(); + $this->user->setMessage(sprintf(__('A validation email has been sent to "%s" to validate the email address change.'), Pluf_esc($new_email))); + } + + /** + * Save the model in the database. + * + * @param bool Commit in the database or not. If not, the object + * is returned but not saved in the database. + * @return Object Model with data set from the form. + */ + function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save the model from an invalid form.')); + } + unset($this->cleaned_data['password2']); + $update_pass = false; + if (strlen($this->cleaned_data['password']) == 0) { + unset($this->cleaned_data['password']); + } else { + $update_pass = true; + } + $old_email = $this->user->email; + $new_email = $this->cleaned_data['email']; + unset($this->cleaned_data['email']); + if ($old_email != $new_email) { + $this->send_validation_mail($new_email); + } + $this->user->setFromFormData($this->cleaned_data); + // Add key as needed. + if ('' !== $this->cleaned_data['public_key']) { + $key = new IDF_Key(); + $key->user = $this->user; + $key->content = $this->cleaned_data['public_key']; + if ($commit) { + $key->create(); + } + } + if ('' !== $this->cleaned_data['secondary_mail']) { + $this->send_validation_mail($this->cleaned_data['secondary_mail'], true); + } + + if ($commit) { + $this->user->update(); + + // FIXME: go the extra mile and check the input lengths for + // all fields here! + // FIXME: this is all doubled in admin/UserUpdate! + + $user_data = IDF_UserData::factory($this->user); + + // Add or remove avatar - we need to do this here because every + // single setter directly leads to a save in the database + if ($user_data->avatar != '' && + ($this->cleaned_data['remove_custom_avatar'] == 1 || + $this->cleaned_data['custom_avatar'] != '')) { + $avatar_path = Pluf::f('upload_path').'/avatars/'.basename($user_data->avatar); + if (basename($avatar_path) != '' && is_file($avatar_path)) { + unlink($avatar_path); + } + $user_data->avatar = ''; + } + + if ($this->cleaned_data['custom_avatar'] != '') { + $user_data->avatar = $this->cleaned_data['custom_avatar']; + } + + $user_data->description = $this->cleaned_data['description']; + $user_data->twitter = $this->cleaned_data['twitter']; + $user_data->public_email = $this->cleaned_data['public_email']; + $user_data->website = $this->cleaned_data['website']; + + if ($update_pass) { + /** + * [signal] + * + * Pluf_User::passwordUpdated + * + * [sender] + * + * IDF_Form_UserAccount + * + * [description] + * + * This signal is sent when the user updated his + * password from his account page. + * + * [parameters] + * + * array('user' => $user) + * + */ + $params = array('user' => $this->user); + Pluf_Signal::send('Pluf_User::passwordUpdated', + 'IDF_Form_UserAccount', $params); + } + } + return $this->user; + } + + /** + * Check arbitrary public keys. + * + * It will throw a Pluf_Form_Invalid exception if it cannot + * validate the key. + * + * @param $key string The key + * @param $user int The user id of the user of the key (0) + * @return string The clean key + */ + public static function checkPublicKey($key, $user=0) + { + $key = trim($key); + if (strlen($key) == 0) { + return ''; + } + + $keysearch = ''; + if (preg_match('#^(ssh\-(?:dss|rsa)\s+\S+)(.*)#', $key, $m)) { + $basekey = preg_replace('/\s+/', ' ', $m[1]); + $comment = trim(preg_replace('/[\r\n]/', ' ', $m[2])); + + $keysearch = $basekey.'%'; + $key = $basekey; + if (!empty($comment)) + $key .= ' '.$comment; + + if (Pluf::f('idf_strong_key_check', false)) { + + $tmpfile = Pluf::f('tmp_folder', '/tmp').'/'.$user.'-key'; + file_put_contents($tmpfile, $key, LOCK_EX); + $cmd = Pluf::f('idf_exec_cmd_prefix', ''). + 'ssh-keygen -l -f '.escapeshellarg($tmpfile).' > /dev/null 2>&1'; + exec($cmd, $out, $return); + unlink($tmpfile); + + if ($return != 0) { + throw new Pluf_Form_Invalid( + __('Please check the key as it does not appear '. + 'to be a valid SSH public key.') + ); + } + } + } + else if (preg_match('#^\[pubkey [^\]]+\]\s*(\S+)\s*\[end\]$#', $key, $m)) { + $keysearch = '%'.$m[1].'%'; + + if (Pluf::f('idf_strong_key_check', false)) { + + // if monotone can read it, it should be valid + $mtn_opts = implode(' ', Pluf::f('mtn_opts', array())); + $cmd = Pluf::f('idf_exec_cmd_prefix', ''). + sprintf('%s %s -d :memory: read >/tmp/php-out 2>&1', + Pluf::f('mtn_path', 'mtn'), $mtn_opts); + $fp = popen($cmd, 'w'); + fwrite($fp, $key); + $return = pclose($fp); + + if ($return != 0) { + throw new Pluf_Form_Invalid( + __('Please check the key as it does not appear '. + 'to be a valid monotone public key.') + ); + } + } + } + else { + throw new Pluf_Form_Invalid( + __('Public key looks like neither an SSH '. + 'nor monotone public key.')); + } + + // If $user, then check if not the same key stored + if ($user) { + $ruser = Pluf::factory('Pluf_User', $user); + if ($ruser->id > 0) { + $sql = new Pluf_SQL('content LIKE %s AND user=%s', array($keysearch, $ruser->id)); + $keys = Pluf::factory('IDF_Key')->getList(array('filter' => $sql->gen())); + if (count($keys) > 0) { + throw new Pluf_Form_Invalid( + __('You already have uploaded this key.') + ); + } + } + } + return $key; + } + + + function clean_custom_avatar() + { + // Just png, jpeg/jpg or gif + if (!preg_match('/\.(png|jpg|jpeg|gif)$/i', $this->cleaned_data['custom_avatar']) && + $this->cleaned_data['custom_avatar'] != '') { + @unlink(Pluf::f('upload_path').'/avatars/'.$this->cleaned_data['custom_avatar']); + throw new Pluf_Form_Invalid(__('For security reason, you cannot upload a file with this extension.')); + } + return $this->cleaned_data['custom_avatar']; + } + + + function clean_last_name() + { + $last_name = trim($this->cleaned_data['last_name']); + if ($last_name == mb_strtoupper($last_name)) { + return mb_convert_case(mb_strtolower($last_name), + MB_CASE_TITLE, 'UTF-8'); + } + return $last_name; + } + + function clean_first_name() + { + $first_name = trim($this->cleaned_data['first_name']); + if ($first_name == mb_strtoupper($first_name)) { + return mb_convert_case(mb_strtolower($first_name), + MB_CASE_TITLE, 'UTF-8'); + } + return $first_name; + } + + function clean_email() + { + $this->cleaned_data['email'] = mb_strtolower(trim($this->cleaned_data['email'])); + $user = Pluf::factory('IDF_EmailAddress')->get_user_for_email_address($this->cleaned_data['email']); + if ($user != null and $user->id != $this->user->id) { + throw new Pluf_Form_Invalid(sprintf(__('The email "%s" is already used.'), $this->cleaned_data['email'])); + } + return $this->cleaned_data['email']; + } + + function clean_secondary_mail() + { + $this->cleaned_data['secondary_mail'] = mb_strtolower(trim($this->cleaned_data['secondary_mail'])); + if (Pluf::factory('IDF_EmailAddress')->get_user_for_email_address($this->cleaned_data['secondary_mail']) != null) { + throw new Pluf_Form_Invalid(sprintf(__('The email "%s" is already used.'), $this->cleaned_data['secondary_mail'])); + } + return $this->cleaned_data['secondary_mail']; + } + + function clean_public_key() + { + $this->cleaned_data['public_key'] = + self::checkPublicKey($this->cleaned_data['public_key'], + $this->user->id); + return $this->cleaned_data['public_key']; + } + + /** + * Check to see if the 2 passwords are the same + */ + public function clean() + { + if (!isset($this->errors['password']) + && !isset($this->errors['password2'])) { + $password1 = $this->cleaned_data['password']; + $password2 = $this->cleaned_data['password2']; + if ($password1 != $password2) { + throw new Pluf_Form_Invalid(__('The passwords do not match. Please give them again.')); + } + } + + return $this->cleaned_data; + } + + +} diff --git a/indefero/src/IDF/Form/UserChangeEmail.php b/indefero/src/IDF/Form/UserChangeEmail.php new file mode 100644 index 0000000..578eb5c --- /dev/null +++ b/indefero/src/IDF/Form/UserChangeEmail.php @@ -0,0 +1,84 @@ +fields['key'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Your verification key'), + 'initial' => '', + 'widget_attrs' => array( + 'size' => 50, + ), + )); + } + + function clean_key() + { + self::validateKey($this->cleaned_data['key']); + return $this->cleaned_data['key']; + } + + /** + * Validate the key. + * + * Throw a Pluf_Form_Invalid exception if the key is not valid. + * + * @param string Key + * @return array array($new_email, $user_id, time(), [primary|secondary]) + */ + public static function validateKey($key) + { + $hash = substr($key, 0, 2); + $encrypted = substr($key, 2); + if ($hash != substr(md5(Pluf::f('secret_key').$encrypted), 0, 2)) { + throw new Pluf_Form_Invalid(__('The validation key is not valid. Please copy/paste it from your confirmation email.')); + } + $cr = new Pluf_Crypt(md5(Pluf::f('secret_key'))); + return explode(':', $cr->decrypt($encrypted), 4); + + } + + /** + * Save the model in the database. + * + * @param bool Commit in the database or not. If not, the object + * is returned but not saved in the database. + * @return Object Model with data set from the form. + */ + function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save the model from an invalid form.')); + } + return Pluf::f('url_base').Pluf_HTTP_URL_urlForView('IDF_Views_User::changeEmailDo', array($this->cleaned_data['key'])); + } +} diff --git a/indefero/src/IDF/Form/WikiConf.php b/indefero/src/IDF/Form/WikiConf.php new file mode 100644 index 0000000..7038486 --- /dev/null +++ b/indefero/src/IDF/Form/WikiConf.php @@ -0,0 +1,66 @@ +fields['labels_wiki_predefined'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Predefined documentation page labels'), + 'initial' => self::init_predefined, + 'widget_attrs' => array('rows' => 13, + 'cols' => 75), + 'widget' => 'Pluf_Form_Widget_TextareaInput', + )); + + $this->fields['labels_wiki_one_max'] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Each documentation page may have at most one label with each of these classes'), + 'initial' => self::init_one_max, + 'widget_attrs' => array('size' => 60), + )); + + } +} + + diff --git a/indefero/src/IDF/Form/WikiPageCreate.php b/indefero/src/IDF/Form/WikiPageCreate.php new file mode 100644 index 0000000..6f1335b --- /dev/null +++ b/indefero/src/IDF/Form/WikiPageCreate.php @@ -0,0 +1,205 @@ +user = $extra['user']; + $this->project = $extra['project']; + if ($this->user->hasPerm('IDF.project-owner', $this->project) + or $this->user->hasPerm('IDF.project-member', $this->project)) { + $this->show_full = true; + } + $initname = (!empty($extra['name'])) ? $extra['name'] : __('PageName'); + $this->fields['title'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Page title'), + 'initial' => $initname, + 'widget_attrs' => array( + 'maxlength' => 200, + 'size' => 67, + ), + 'help_text' => __('The page name must contains only letters, digits and the dash (-) character.'), + )); + $this->fields['summary'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Description'), + 'help_text' => __('This one line description is displayed in the list of pages.'), + 'initial' => '', + 'widget_attrs' => array( + 'maxlength' => 200, + 'size' => 67, + ), + )); + $this->fields['content'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Content'), + 'initial' => $initial, + 'widget' => 'Pluf_Form_Widget_TextareaInput', + 'widget_attrs' => array( + 'cols' => 68, + 'rows' => 26, + ), + )); + + if ($this->show_full) { + for ($i=1;$i<4;$i++) { + $this->fields['label'.$i] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Labels'), + 'initial' => '', + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 20, + ), + )); + } + } + } + + public function clean_title() + { + $title = $this->cleaned_data['title']; + if (preg_match('/[^a-zA-Z0-9\-]/', $title)) { + throw new Pluf_Form_Invalid(__('The title contains invalid characters.')); + } + $sql = new Pluf_SQL('project=%s AND title=%s', + array($this->project->id, $title)); + $pages = Pluf::factory('IDF_Wiki_Page')->getList(array('filter'=>$sql->gen())); + if ($pages->count() > 0) { + throw new Pluf_Form_Invalid(__('A page with this title already exists.')); + } + return $title; + } + + /** + * Validate the interconnection in the form. + */ + public function clean() + { + if (!$this->show_full) { + return $this->cleaned_data; + } + $conf = new IDF_Conf(); + $conf->setProject($this->project); + $onemax = array(); + foreach (explode(',', $conf->getVal('labels_wiki_one_max', IDF_Form_WikiConf::init_one_max)) as $class) { + if (trim($class) != '') { + $onemax[] = mb_strtolower(trim($class)); + } + } + $count = array(); + for ($i=1;$i<4;$i++) { + $this->cleaned_data['label'.$i] = trim($this->cleaned_data['label'.$i]); + if (strpos($this->cleaned_data['label'.$i], ':') !== false) { + list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2); + list($class, $name) = array(mb_strtolower(trim($class)), + trim($name)); + } else { + $class = 'other'; + $name = $this->cleaned_data['label'.$i]; + } + if (!isset($count[$class])) $count[$class] = 1; + else $count[$class] += 1; + if (in_array($class, $onemax) and $count[$class] > 1) { + if (!isset($this->errors['label'.$i])) $this->errors['label'.$i] = array(); + $this->errors['label'.$i][] = sprintf(__('You cannot provide more than one label from the %s class to a page.'), $class); + throw new Pluf_Form_Invalid(__('You provided an invalid label.')); + } + } + return $this->cleaned_data; + } + + /** + * Save the model in the database. + * + * @param bool Commit in the database or not. If not, the object + * is returned but not saved in the database. + * @return Object Model with data set from the form. + */ + function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save the model from an invalid form.')); + } + // Add a tag for each label + $tags = array(); + if ($this->show_full) { + for ($i=1;$i<4;$i++) { + if (strlen($this->cleaned_data['label'.$i]) > 0) { + if (strpos($this->cleaned_data['label'.$i], ':') !== false) { + list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2); + list($class, $name) = array(trim($class), trim($name)); + } else { + $class = 'Other'; + $name = trim($this->cleaned_data['label'.$i]); + } + $tags[] = IDF_Tag::add($name, $this->project, $class); + } + } + } + // Create the page + $page = new IDF_Wiki_Page(); + $page->project = $this->project; + $page->submitter = $this->user; + $page->summary = trim($this->cleaned_data['summary']); + $page->title = trim($this->cleaned_data['title']); + $page->create(); + foreach ($tags as $tag) { + $page->setAssoc($tag); + } + // add the first revision + $rev = new IDF_Wiki_PageRevision(); + $rev->wikipage = $page; + $rev->content = $this->cleaned_data['content']; + $rev->submitter = $this->user; + $rev->summary = __('Initial page creation'); + $rev->create(); + $rev->notify($this->project->getConf()); + return $page; + } +} diff --git a/indefero/src/IDF/Form/WikiPageDelete.php b/indefero/src/IDF/Form/WikiPageDelete.php new file mode 100644 index 0000000..d7b952a --- /dev/null +++ b/indefero/src/IDF/Form/WikiPageDelete.php @@ -0,0 +1,64 @@ +page = $extra['page']; + $this->fields['confirm'] = new Pluf_Form_Field_Boolean( + array('required' => true, + 'label' => __('Yes, I understand that the page and all its revisions will be deleted.'), + 'initial' => '', + )); + } + + /** + * Check the confirmation. + */ + public function clean_confirm() + { + if (!$this->cleaned_data['confirm']) { + throw new Pluf_Form_Invalid(__('You need to confirm the deletion.')); + } + return $this->cleaned_data['confirm']; + } + + + function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save the model from an invalid form.')); + } + $this->page->delete(); + return true; + } +} diff --git a/indefero/src/IDF/Form/WikiPageUpdate.php b/indefero/src/IDF/Form/WikiPageUpdate.php new file mode 100644 index 0000000..0910775 --- /dev/null +++ b/indefero/src/IDF/Form/WikiPageUpdate.php @@ -0,0 +1,242 @@ +page = $extra['page']; + $this->user = $extra['user']; + $this->project = $extra['project']; + if ($this->user->hasPerm('IDF.project-owner', $this->project) + or $this->user->hasPerm('IDF.project-member', $this->project)) { + $this->show_full = true; + } + if ($this->show_full) { + $this->fields['title'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Page title'), + 'initial' => $this->page->title, + 'widget_attrs' => array( + 'maxlength' => 200, + 'size' => 67, + ), + 'help_text' => __('The page name must contains only letters, digits and the dash (-) character.'), + )); + $this->fields['summary'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Description'), + 'help_text' => __('This one line description is displayed in the list of pages.'), + 'initial' => $this->page->summary, + 'widget_attrs' => array( + 'maxlength' => 200, + 'size' => 67, + ), + )); + } + $rev = $this->page->get_current_revision(); + $this->fields['content'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Content'), + 'initial' => $rev->content, + 'widget' => 'Pluf_Form_Widget_TextareaInput', + 'widget_attrs' => array( + 'cols' => 68, + 'rows' => 26, + ), + )); + $this->fields['comment'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Comment'), + 'help_text' => __('One line to describe the changes you made.'), + 'initial' => '', + 'widget_attrs' => array( + 'maxlength' => 200, + 'size' => 67, + ), + )); + + if ($this->show_full) { + $tags = $this->page->get_tags_list(); + for ($i=1;$i<4;$i++) { + $initial = ''; + if (isset($tags[$i-1])) { + if ($tags[$i-1]->class != 'Other') { + $initial = (string) $tags[$i-1]; + } else { + $initial = $tags[$i-1]->name; + } + } + $this->fields['label'.$i] = new Pluf_Form_Field_Varchar( + array('required' => false, + 'label' => __('Labels'), + 'initial' => $initial, + 'widget_attrs' => array( + 'maxlength' => 50, + 'size' => 20, + ), + )); + } + } + } + + public function clean_title() + { + $title = $this->cleaned_data['title']; + if (preg_match('/[^a-zA-Z0-9\-]/', $title)) { + throw new Pluf_Form_Invalid(__('The title contains invalid characters.')); + } + $sql = new Pluf_SQL('project=%s AND title=%s', + array($this->project->id, $title)); + $pages = Pluf::factory('IDF_Wiki_Page')->getList(array('filter'=>$sql->gen())); + if ($pages->count() > 0 and $pages[0]->id != $this->page->id) { + throw new Pluf_Form_Invalid(__('A page with this title already exists.')); + } + return $title; + } + + /** + * Validate the interconnection in the form. + */ + public function clean() + { + if (!$this->show_full) { + return $this->cleaned_data; + } + $conf = new IDF_Conf(); + $conf->setProject($this->project); + $onemax = array(); + foreach (explode(',', $conf->getVal('labels_wiki_one_max', IDF_Form_WikiConf::init_one_max)) as $class) { + if (trim($class) != '') { + $onemax[] = mb_strtolower(trim($class)); + } + } + $count = array(); + for ($i=1;$i<4;$i++) { + $this->cleaned_data['label'.$i] = trim($this->cleaned_data['label'.$i]); + if (strpos($this->cleaned_data['label'.$i], ':') !== false) { + list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2); + list($class, $name) = array(mb_strtolower(trim($class)), + trim($name)); + } else { + $class = 'other'; + $name = $this->cleaned_data['label'.$i]; + } + if (!isset($count[$class])) $count[$class] = 1; + else $count[$class] += 1; + if (in_array($class, $onemax) and $count[$class] > 1) { + if (!isset($this->errors['label'.$i])) $this->errors['label'.$i] = array(); + $this->errors['label'.$i][] = sprintf(__('You cannot provide more than one label from the %s class to a page.'), $class); + throw new Pluf_Form_Invalid(__('You provided an invalid label.')); + } + } + return $this->cleaned_data; + } + + /** + * Save the model in the database. + * + * @param bool Commit in the database or not. If not, the object + * is returned but not saved in the database. + * @return Object Model with data set from the form. + */ + function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save the model from an invalid form.')); + } + if ($this->show_full) { + $tagids = array(); + $tags = array(); + for ($i=1;$i<4;$i++) { + if (strlen($this->cleaned_data['label'.$i]) > 0) { + if (strpos($this->cleaned_data['label'.$i], ':') !== false) { + list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2); + list($class, $name) = array(trim($class), trim($name)); + } else { + $class = 'Other'; + $name = trim($this->cleaned_data['label'.$i]); + } + $tag = IDF_Tag::add($name, $this->project, $class); + $tags[] = $tag; + $tagids[] = $tag->id; + } + } + // Compare between the old and the new data + $changes = array(); + $oldtags = $this->page->get_tags_list(); + foreach ($tags as $tag) { + if (!Pluf_Model_InArray($tag, $oldtags)) { + if (!isset($changes['lb'])) $changes['lb'] = array(); + if ($tag->class != 'Other') { + $changes['lb'][] = (string) $tag; //new tag + } else { + $changes['lb'][] = (string) $tag->name; + } + } + } + foreach ($oldtags as $tag) { + if (!Pluf_Model_InArray($tag, $tags)) { + if (!isset($changes['lb'])) $changes['lb'] = array(); + if ($tag->class != 'Other') { + $changes['lb'][] = '-'.(string) $tag; //new tag + } else { + $changes['lb'][] = '-'.(string) $tag->name; + } + } + } + if (trim($this->page->summary) != trim($this->cleaned_data['summary'])) { + $changes['su'] = trim($this->cleaned_data['summary']); + } + // Update the page + $this->page->batchAssoc('IDF_Tag', $tagids); + $this->page->summary = trim($this->cleaned_data['summary']); + $this->page->title = trim($this->cleaned_data['title']); + } else { + $changes = array(); + } + $this->page->update(); + // add the new revision + $rev = new IDF_Wiki_PageRevision(); + $rev->wikipage = $this->page; + $rev->content = $this->cleaned_data['content']; + $rev->submitter = $this->user; + $rev->summary = $this->cleaned_data['comment']; + $rev->changes = $changes; + $rev->create(); + $rev->notify($this->project->getConf(), false); + return $this->page; + } +} diff --git a/indefero/src/IDF/Form/WikiResourceCreate.php b/indefero/src/IDF/Form/WikiResourceCreate.php new file mode 100644 index 0000000..8ef1e83 --- /dev/null +++ b/indefero/src/IDF/Form/WikiResourceCreate.php @@ -0,0 +1,169 @@ +project = $extra['project']; + $this->user = $extra['user']; + $initname = (!empty($extra['name'])) ? $extra['name'] : __('ResourceName'); + + $this->fields['title'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Resource title'), + 'initial' => $initname, + 'widget_attrs' => array( + 'maxlength' => 200, + 'size' => 67, + ), + 'help_text' => __('The resource name must contains only letters, digits and the dash (-) character.'), + )); + $this->fields['summary'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Description'), + 'help_text' => __('This one line description is displayed in the list of resources.'), + 'initial' => '', + 'widget_attrs' => array( + 'maxlength' => 200, + 'size' => 67, + ), + )); + + $this->fields['file'] = new Pluf_Form_Field_File( + array('required' => true, + 'label' => __('File'), + 'initial' => '', + 'max_size' => Pluf::f('max_upload_size', 2097152), + 'move_function_params' => array('upload_path' => $this->getTempUploadPath(), + 'upload_path_create' => true, + 'upload_overwrite' => true), + )); + } + + public function clean_title() + { + $title = $this->cleaned_data['title']; + if (preg_match('/[^a-zA-Z0-9\-]/', $title)) { + throw new Pluf_Form_Invalid(__('The title contains invalid characters.')); + } + $sql = new Pluf_SQL('project=%s AND title=%s', + array($this->project->id, $title)); + $resources = Pluf::factory('IDF_Wiki_Resource')->getList(array('filter'=>$sql->gen())); + if ($resources->count() > 0) { + throw new Pluf_Form_Invalid(__('A resource with this title already exists.')); + } + return $title; + } + + public function clean_file() + { + // FIXME: we do the same in IDF_Form_Upload and a couple of other places as well + $extra = strtolower(implode('|', explode(' ', Pluf::f('idf_extra_upload_ext')))); + if (strlen($extra)) $extra .= '|'; + if (!preg_match('/\.('.$extra.'png|jpg|jpeg|gif|bmp|psd|tif|aiff|asf|avi|bz2|css|doc|eps|gz|jar|mdtext|mid|mov|mp3|mpg|ogg|pdf|ppt|ps|qt|ra|ram|rm|rtf|sdd|sdw|sit|sxi|sxw|swf|tgz|txt|wav|xls|xml|war|wmv|zip)$/i', $this->cleaned_data['file'])) { + @unlink($this->getTempUploadPath().$this->cleaned_data['file']); + throw new Pluf_Form_Invalid(__('For security reasons, you cannot upload a file with this extension.')); + } + return $this->cleaned_data['file']; + } + + /** + * If we have uploaded a file, but the form failed remove it. + * + */ + function failed() + { + if (!empty($this->cleaned_data['file']) + and file_exists($this->getTempUploadPath().$this->cleaned_data['file'])) { + @unlink($this->getTempUploadPath().$this->cleaned_data['file']); + } + } + + /** + * Save the model in the database. + * + * @param bool Commit in the database or not. If not, the object + * is returned but not saved in the database. + * @return Object Model with data set from the form. + */ + function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save the model from an invalid form.')); + } + + $tempFile = $this->getTempUploadPath().$this->cleaned_data['file']; + list($mimeType, , $extension) = IDF_FileUtil::getMimeType($tempFile); + + // create the resource + $resource = new IDF_Wiki_Resource(); + $resource->project = $this->project; + $resource->submitter = $this->user; + $resource->summary = trim($this->cleaned_data['summary']); + $resource->title = trim($this->cleaned_data['title']); + $resource->mime_type = $mimeType; + $resource->create(); + + // add the first revision + $rev = new IDF_Wiki_ResourceRevision(); + $rev->wikiresource = $resource; + $rev->submitter = $this->user; + $rev->summary = __('Initial resource creation'); + $rev->filesize = filesize($tempFile); + $rev->fileext = $extension; + $rev->create(); + + $finalFile = $rev->getFilePath(); + if (!@mkdir(dirname($finalFile), 0755, true)) { + @unlink($tempFile); + $rev->delete(); + $resource->delete(); + throw new Exception('could not create final resource path'); + } + + if (!@rename($tempFile, $finalFile)) { + @unlink($tempFile); + $rev->delete(); + $resource->delete(); + throw new Exception('could not move resource to final location'); + } + + return $resource; + } + + private function getTempUploadPath() + { + return Pluf::f('upload_path').'/'.$this->project->shortname.'/wiki/temp/'; + } +} diff --git a/indefero/src/IDF/Form/WikiResourceDelete.php b/indefero/src/IDF/Form/WikiResourceDelete.php new file mode 100644 index 0000000..2eef1dd --- /dev/null +++ b/indefero/src/IDF/Form/WikiResourceDelete.php @@ -0,0 +1,64 @@ +resource = $extra['resource']; + $this->fields['confirm'] = new Pluf_Form_Field_Boolean( + array('required' => true, + 'label' => __('Yes, I understand that the resource and all its revisions will be deleted.'), + 'initial' => '', + )); + } + + /** + * Check the confirmation. + */ + public function clean_confirm() + { + if (!$this->cleaned_data['confirm']) { + throw new Pluf_Form_Invalid(__('You need to confirm the deletion.')); + } + return $this->cleaned_data['confirm']; + } + + + function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save the model from an invalid form.')); + } + $this->resource->delete(); + return true; + } +} diff --git a/indefero/src/IDF/Form/WikiResourceUpdate.php b/indefero/src/IDF/Form/WikiResourceUpdate.php new file mode 100644 index 0000000..2ea448d --- /dev/null +++ b/indefero/src/IDF/Form/WikiResourceUpdate.php @@ -0,0 +1,161 @@ +resource = $extra['resource']; + $this->user = $extra['user']; + $this->project = $extra['project']; + + $this->fields['summary'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Description'), + 'help_text' => __('This one line description is displayed in the list of resources.'), + 'initial' => $this->resource->summary, + 'widget_attrs' => array( + 'maxlength' => 200, + 'size' => 67, + ), + )); + $this->fields['file'] = new Pluf_Form_Field_File( + array('required' => true, + 'label' => __('File'), + 'initial' => '', + 'max_size' => Pluf::f('max_upload_size', 2097152), + 'move_function_params' => array('upload_path' => $this->getTempUploadPath(), + 'upload_path_create' => true, + 'upload_overwrite' => true), + )); + + $this->fields['comment'] = new Pluf_Form_Field_Varchar( + array('required' => true, + 'label' => __('Comment'), + 'help_text' => __('One line to describe the changes you made.'), + 'initial' => '', + 'widget_attrs' => array( + 'maxlength' => 200, + 'size' => 67, + ), + )); + } + + public function clean_file() + { + // FIXME: we do the same in IDF_Form_Upload and a couple of other places as well + $extra = strtolower(implode('|', explode(' ', Pluf::f('idf_extra_upload_ext')))); + if (strlen($extra)) $extra .= '|'; + if (!preg_match('/\.('.$extra.'png|jpg|jpeg|gif|bmp|psd|tif|aiff|asf|avi|bz2|css|doc|eps|gz|jar|mdtext|mid|mov|mp3|mpg|ogg|pdf|ppt|ps|qt|ra|ram|rm|rtf|sdd|sdw|sit|sxi|sxw|swf|tgz|txt|wav|xls|xml|war|wmv|zip)$/i', $this->cleaned_data['file'])) { + @unlink($this->getTempUploadPath().$this->cleaned_data['file']); + throw new Pluf_Form_Invalid(__('For security reasons, you cannot upload a file with this extension.')); + } + + list($mimeType, , $extension) = IDF_FileUtil::getMimeType($this->getTempUploadPath().$this->cleaned_data['file']); + if ($this->resource->mime_type != $mimeType) { + throw new Pluf_Form_Invalid(sprintf( + __('The mime type of the uploaded file "%1$s" does not match the mime type of this resource "%2$s"'), + $mimeType, $this->resource->mime_type + )); + } + $this->cleaned_data['fileext'] = $extension; + + if (md5_file($this->getTempUploadPath().$this->cleaned_data['file']) === + md5_file($this->resource->get_current_revision()->getFilePath())) { + throw new Pluf_Form_Invalid(__('The current version of the resource and the uploaded file are equal.')); + } + return $this->cleaned_data['file']; + } + + /** + * If we have uploaded a file, but the form failed remove it. + * + */ + function failed() + { + if (!empty($this->cleaned_data['file']) + and file_exists($this->getTempUploadPath().$this->cleaned_data['file'])) { + @unlink($this->getTempUploadPath().$this->cleaned_data['file']); + } + } + + /** + * Save the model in the database. + * + * @param bool Commit in the database or not. If not, the object + * is returned but not saved in the database. + * @return Object Model with data set from the form. + */ + function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save the model from an invalid form.')); + } + + $tempFile = $this->getTempUploadPath().$this->cleaned_data['file']; + + $this->resource->summary = trim($this->cleaned_data['summary']); + $this->resource->update(); + + // add the new revision + $rev = new IDF_Wiki_ResourceRevision(); + $rev->wikiresource = $this->resource; + $rev->submitter = $this->user; + $rev->summary = $this->cleaned_data['comment']; + $rev->filesize = filesize($tempFile); + $rev->fileext = $this->cleaned_data['fileext']; + $rev->create(); + + $finalFile = $rev->getFilePath(); + if (!is_dir(dirname($finalFile))) { + @unlink($tempFile); + $rev->delete(); + throw new Exception('resource path does not exist'); + } + + if (!@rename($tempFile, $finalFile)) { + @unlink($tempFile); + $rev->delete(); + throw new Exception('could not move resource to final location'); + } + + return $this->resource; + } + + private function getTempUploadPath() + { + return Pluf::f('upload_path').'/'.$this->project->shortname.'/wiki/temp/'; + } +} diff --git a/indefero/src/IDF/Gconf.php b/indefero/src/IDF/Gconf.php new file mode 100644 index 0000000..0ab63a0 --- /dev/null +++ b/indefero/src/IDF/Gconf.php @@ -0,0 +1,210 @@ +_a['table'] = 'idf_gconf'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + //It is automatically added. + 'blank' => true, + ), + 'model_class' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 150, + 'verbose' => __('model class'), + ), + 'model_id' => + array( + 'type' => 'Pluf_DB_Field_Integer', + 'blank' => false, + 'verbose' => __('model id'), + ), + 'vkey' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 50, + 'verbose' => __('key'), + ), + 'vdesc' => + array( + 'type' => 'Pluf_DB_Field_Text', + 'blank' => false, + 'verbose' => __('value'), + ), + ); + $this->_a['idx'] = array('model_vkey_idx' => + array( + 'col' => 'model_class, model_id, vkey', + 'type' => 'unique', + ), + ); + $this->f = new IDF_Config_DataProxy($this); + } + + function setModel($model) + { + $this->datacache = null; + $this->_mod = $model; + } + + function initCache() + { + $this->datacache = array(); + $this->dirty = array(); + $sql = new Pluf_SQL('model_class=%s AND model_id=%s', + array($this->_mod->_model, $this->_mod->id)); + foreach ($this->getList(array('filter' => $sql->gen())) as $val) { + $this->datacache[$val->vkey] = ($this->serialize) ? unserialize($val->vdesc) : $val->vdesc; + $this->dirty[$val->vkey] = $val->id; + } + } + + /** + * FIXME: This is not efficient when setting a large number of + * values in a loop. + */ + function setVal($key, $value) + { + if (!is_null($this->getVal($key, null)) + and $value == $this->getVal($key)) { + return; + } + $svalue = ($this->serialize) ? serialize($value) : $value; + if (isset($this->dirty[$key])) { + // we get to check if deleted by other process + update + $conf = new IDF_Gconf($this->dirty[$key]); + if ($conf->id == $this->dirty[$key]) { + $conf->vdesc = $svalue; + $conf->update(); + $this->datacache[$key] = $value; + return; + } + } + // we insert + $conf = new IDF_Gconf(); + $conf->model_class = $this->_mod->_model; + $conf->model_id = $this->_mod->id; + $conf->vkey = $key; + $conf->vdesc = $svalue; + $conf->create(); + $this->datacache[$key] = $value; + $this->dirty[$key] = $conf->id; + } + + function getVal($key, $default='') + { + if ($this->datacache === null) { + $this->initCache(); + } + return (isset($this->datacache[$key])) ? $this->datacache[$key] : $default; + } + + function delVal($key, $initcache=true) + { + $gconf = new IDF_Gconf(); + $sql = new Pluf_SQL('vkey=%s AND model_class=%s AND model_id=%s', array($key, $this->_mod->_model, $this->_mod->id)); + foreach ($gconf->getList(array('filter' => $sql->gen())) as $c) { + $c->delete(); + } + if ($initcache) { + $this->initCache(); + } + } + + /** + * Collection selection. + * + * Suppose you have 5 objects with associated meta data in the + * Gconf storage, if you load the data independently for each + * object, you end up with 5 SELECT queries. With 25 objects, 25 + * SELECT. You can select with one query all the data and merge in + * the code. It is faster. The collection selection get a + * model_class and a list of ids and returns an id indexed array + * of associative array data. This is for read only access as you + * do not get a series of Gconf objects. + */ + public static function collect($class, $ids) + { + $gconf = new IDF_Gconf(); + $stmpl = sprintf('model_class=%%s AND model_id IN (%s)', + implode(',' , $ids)); + $sql = new Pluf_SQL($stmpl, array($class)); + $out = array_fill_keys($ids, array()); + foreach ($gconf->getList(array('filter' => $sql->gen())) as $c) { + $out[$c->model_id][$c->vkey] = $c->vdesc; + } + + return $out; + } + + /** + * Drop the conf of a model. + * + * If your model is using this table, just add the following line + * in your preDelete() method: + * + * IDF_Gconf::dropForModel($this) + * + * It will take care of the cleaning. + */ + static public function dropForModel($model) + { + $table = Pluf::factory(__CLASS__)->getSqlTable(); + $sql = new Pluf_SQL('model_class=%s AND model_id=%s', + array($model->_model, $model->id)); + $db = &Pluf::db(); + $db->execute('DELETE FROM '.$table.' WHERE '.$sql->gen()); + } + + static public function dropUser($signal, &$params) + { + self::dropForModel($params['user']); + } +} diff --git a/indefero/src/IDF/Issue.php b/indefero/src/IDF/Issue.php new file mode 100644 index 0000000..050cdcf --- /dev/null +++ b/indefero/src/IDF/Issue.php @@ -0,0 +1,327 @@ +_a['table'] = 'idf_issues'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + 'blank' => true, + ), + 'project' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_Project', + 'blank' => false, + 'verbose' => __('project'), + 'relate_name' => 'issues', + ), + 'summary' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 250, + 'verbose' => __('summary'), + ), + 'submitter' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'Pluf_User', + 'blank' => false, + 'verbose' => __('submitter'), + 'relate_name' => 'submitted_issue', + ), + 'owner' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'Pluf_User', + 'blank' => true, // no owner when submitted. + 'is_null' => true, + 'verbose' => __('owner'), + 'relate_name' => 'owned_issue', + ), + 'interested' => + array( + 'type' => 'Pluf_DB_Field_Manytomany', + 'model' => 'Pluf_User', + 'blank' => true, + 'verbose' => __('interested users'), + 'help_text' => __('Interested users will get an email notification when the issue is changed.'), + ), + 'tags' => + array( + 'type' => 'Pluf_DB_Field_Manytomany', + 'blank' => true, + 'model' => 'IDF_Tag', + 'verbose' => __('labels'), + ), + 'status' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'blank' => false, + 'model' => 'IDF_Tag', + 'verbose' => __('status'), + ), + 'creation_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('creation date'), + ), + 'modif_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('modification date'), + ), + ); + $this->_a['idx'] = array( + 'modif_dtime_idx' => + array( + 'col' => 'modif_dtime', + 'type' => 'normal', + ), + ); + $table = $this->_con->pfx.'idf_issue_idf_tag_assoc'; + $this->_a['views'] = array( + 'join_tags' => + array( + 'join' => 'LEFT JOIN '.$table + .' ON idf_issue_id=id', + ), + ); + } + + function __toString() + { + return $this->id.' - '.$this->summary; + } + + function _toIndex() + { + $r = array(); + foreach ($this->get_comments_list() as $c) { + $r[] = $c->_toIndex(); + } + $str = str_repeat($this->summary.' ', 4).' '.implode(' ', $r); + return Pluf_Text::cleanString(html_entity_decode($str, ENT_QUOTES, 'UTF-8')); + } + + function preDelete() + { + IDF_Timeline::remove($this); + IDF_Search::remove($this); + } + + function preSave($create=false) + { + if ($this->id == '') { + $this->creation_dtime = gmdate('Y-m-d H:i:s'); + } + $this->modif_dtime = gmdate('Y-m-d H:i:s'); + } + + function postSave($create=false) + { + // Note: No indexing is performed here. The indexing is + // triggered in the postSave step of the comment to ensure + // that the issue as at least one comment in the database when + // doing the indexing. + if ($create) { + IDF_Timeline::insert($this, $this->get_project(), + $this->get_submitter()); + } + } + + function getGroupedRelatedIssues($opts = array(), $idsOnly = false) + { + $rels = $this->get_related_issues_list(array_merge($opts, array( + 'view' => 'with_other_issue', + ))); + + $res = array(); + foreach ($rels as $rel) { + $verb = $rel->verb; + if (!array_key_exists($verb, $res)) { + $res[$verb] = array(); + } + $res[$verb][] = $idsOnly ? $rel->other_issue : $rel; + } + + return $res; + } + + /** + * Returns an HTML fragment used to display this issue in the + * timeline. + * + * The request object is given to be able to check the rights and + * as such create links to other items etc. You can consider that + * if displayed, you can create a link to it. + * + * @param Pluf_HTTP_Request + * @return Pluf_Template_SafeString + */ + public function timelineFragment($request) + { + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view', + array($request->project->shortname, + $this->id)); + $out = ''. + Pluf_esc(Pluf_Template_dateAgo($this->creation_dtime, 'without')). + ''; + $stag = new IDF_Template_ShowUser(); + $user = $stag->start($this->get_submitter(), $request, '', false); + $ic = (in_array($this->status, $request->project->getTagIdsByStatus('closed'))) ? 'issue-c' : 'issue-o'; + $out .= sprintf(__('Issue %3$d, %4$s'), $url, $ic, $this->id, Pluf_esc($this->summary)).''; + $out .= "\n".' +
'.sprintf(__('Creation of issue %3$d, by %4$s'), $url, $ic, $this->id, $user).'
'; + return Pluf_Template::markSafe($out); + } + + public function feedFragment($request) + { + $url = Pluf::f('url_base') + .Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view', + array($request->project->shortname, + $this->id)); + $title = sprintf(__('%1$s: Issue %2$d created - %3$s'), + $request->project->name, + $this->id, $this->summary); + $cts = $this->get_comments_list(array('order' => 'id ASC', + 'nb' => 1)); + $date = Pluf_Date::gmDateToGmString($this->creation_dtime); + $context = new Pluf_Template_Context_Request( + $request, + array('url' => $url, + 'author' => $this->get_submitter(), + 'title' => $title, + 'c' => $cts[0], + 'issue' => $this, + 'date' => $date) + ); + $tmpl = new Pluf_Template('idf/issues/feedfragment.xml'); + return $tmpl->render($context); + } + + /** + * Notification of change of the object. + * + * For the moment, only email, but one can add webhooks later. + * + * Usage: + *
+     * $this->notify($conf); // Notify the creation
+     * $this->notify($conf, false); // Notify the update of the object
+     * 
+ * + * @param IDF_Conf Current configuration + * @param bool Creation (true) + */ + public function notify($conf, $create=true) + { + $project = $this->get_project(); + $current_locale = Pluf_Translation::getLocale(); + + $from_email = Pluf::f('from_email'); + $comments = $this->get_comments_list(array('order' => 'id DESC')); + $messageId = '<'.md5('issue'.$this->id.md5(Pluf::f('secret_key'))).'@'.Pluf::f('mail_host', 'localhost').'>'; + $recipients = $project->getNotificationRecipientsForTab('issues'); + + // the submitter (might be skipped later on if he is the one who also + // submitted the last comment) + if (!array_key_exists($this->get_submitter()->email, $recipients)) { + $recipients[$this->get_submitter()->email] = $this->get_submitter()->language; + } + + // the owner of the issue, if we have one + $owner = $this->get_owner(); + if (null != $owner && !array_key_exists($owner->email, $recipients)) { + $recipients[$owner->email] = $owner->language; + } + + // additional users who starred the issue + foreach ($this->get_interested_list() as $interested) { + if (array_key_exists($interested->email, $recipients)) + continue; + $recipients[$interested->email] = $interested->language; + } + + foreach ($recipients as $address => $language) { + + // do not notify the creator of the last comment, + // i.e. the user who triggered this notification + if ($comments[0]->get_submitter()->email === $address) { + continue; + } + + Pluf_Translation::loadSetLocale($language); + + $context = new Pluf_Template_Context(array( + 'issue' => $this, + 'owns_issue' => $owner !== null && $owner->email === $address, + // the initial comment for create, the last for update + 'comment' => $comments[0], + 'comments' => $comments, + 'project' => $project, + 'url_base' => Pluf::f('url_base'), + )); + + $tplfile = 'idf/issues/issue-created-email.txt'; + $subject = __('Issue %1$s - %2$s (%3$s)'); + $headers = array('Message-ID' => $messageId); + if (!$create) { + $tplfile = 'idf/issues/issue-updated-email.txt'; + $subject = __('Updated Issue %1$s - %2$s (%3$s)'); + $headers = array('References' => $messageId); + } + + $tmpl = new Pluf_Template($tplfile); + $text_email = $tmpl->render($context); + + $email = new Pluf_Mail($from_email, $address, + sprintf($subject, $this->id, $this->summary, $project->shortname)); + $email->addTextMessage($text_email); + $email->addHeaders($headers); + $email->sendMail(); + } + + Pluf_Translation::loadSetLocale($current_locale); + } +} diff --git a/indefero/src/IDF/IssueComment.php b/indefero/src/IDF/IssueComment.php new file mode 100644 index 0000000..bcd648c --- /dev/null +++ b/indefero/src/IDF/IssueComment.php @@ -0,0 +1,213 @@ +_a['table'] = 'idf_issuecomments'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + 'blank' => true, + ), + 'issue' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_Issue', + 'blank' => false, + 'verbose' => __('issue'), + 'relate_name' => 'comments', + ), + 'content' => + array( + 'type' => 'Pluf_DB_Field_Text', + 'blank' => false, + 'verbose' => __('comment'), + ), + 'submitter' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'Pluf_User', + 'blank' => false, + 'verbose' => __('submitter'), + 'relate_name' => 'commented_issue', + ), + 'changes' => + array( + 'type' => 'Pluf_DB_Field_Serialized', + 'blank' => true, + 'verbose' => __('changes'), + 'help_text' => __('Serialized array of the changes in the issue.'), + ), + 'creation_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('creation date'), + ), + ); + $this->_a['idx'] = array( + 'creation_dtime_idx' => + array( + 'col' => 'creation_dtime', + 'type' => 'normal', + ), + ); + } + + function changedIssue() + { + return (is_array($this->changes) and count($this->changes) > 0); + } + + function _toIndex() + { + return $this->content; + } + + function preDelete() + { + IDF_Timeline::remove($this); + } + + function preSave($create=false) + { + if ($this->id == '') { + $this->creation_dtime = gmdate('Y-m-d H:i:s'); + } + } + + function postSave($create=false) + { + if ($create) { + // Check if more than one comment for this issue. We do + // not want to insert the first comment in the timeline as + // the issue itself is inserted. + $sql = new Pluf_SQL('issue=%s', array($this->issue)); + $co = Pluf::factory('IDF_IssueComment')->getList(array('filter'=>$sql->gen())); + if ($co->count() > 1) { + IDF_Timeline::insert($this, $this->get_issue()->get_project(), + $this->get_submitter()); + } + } + IDF_Search::index($this->get_issue()); + } + + public function timelineFragment($request) + { + $issue = $this->get_issue(); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view', + array($request->project->shortname, + $issue->id)); + $url .= '#ic'.$this->id; + $out = "\n".''. + Pluf_esc(Pluf_Template_dateAgo($this->creation_dtime, 'without')). + ''; + $stag = new IDF_Template_ShowUser(); + $user = $stag->start($this->get_submitter(), $request, '', false); + + $ic = (in_array($issue->status, $request->project->getTagIdsByStatus('closed'))) ? 'issue-c' : 'issue-o'; + $out .= sprintf(__('Issue %3$d, %4$s'), $url, $ic, $issue->id, Pluf_esc($issue->summary)); + + if ($this->changedIssue()) { + $out .= '
'; + foreach ($this->changes as $w => $v) { + $out .= ''; + switch ($w) { + case 'su': + $out .= __('Summary:'); break; + case 'st': + $out .= __('Status:'); break; + case 'ow': + $out .= __('Owner:'); break; + case 'lb': + $out .= __('Labels:'); break; + case 'rel': + $out .= __('Relations:'); break; + } + $out .= ' '; + if ($w == 'lb' || $w == 'rel') { + foreach ($v as $t => $ls) { + foreach ($ls as $l) { + if ($t == 'rem') $out .= ''; + $out .= Pluf_esc($l); + if ($t == 'rem') $out .= ''; + $out .= ' '; + } + } + } else { + $out .= Pluf_esc($v); + } + $out .= ' '; + } + $out .= '
'; + } + $out .= ''; + $out .= "\n".' +
'.sprintf(__('Comment on issue %3$d, by %4$s'), $url, $ic, $issue->id, $user).'
'; + return Pluf_Template::markSafe($out); + } + + public function feedFragment($request) + { + $issue = $this->get_issue(); + $url = Pluf::f('url_base') + .Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view', + array($request->project->shortname, + $issue->id)); + $title = sprintf(__('%1$s: Comment on issue %2$d - %3$s'), + Pluf_esc($request->project->name), + $issue->id, Pluf_esc($issue->summary)); + $url .= '#ic'.$this->id; + $date = Pluf_Date::gmDateToGmString($this->creation_dtime); + $context = new Pluf_Template_Context_Request( + $request, + array('url' => $url, + 'author' => $issue->get_submitter(), + 'title' => $title, + 'c' => $this, + 'issue' => $issue, + 'date' => $date) + ); + $tmpl = new Pluf_Template('idf/issues/feedfragment.xml'); + return $tmpl->render($context); + } + + public function get_submitter_data() + { + return IDF_UserData::factory($this->get_submitter()); + } +} diff --git a/indefero/src/IDF/IssueFile.php b/indefero/src/IDF/IssueFile.php new file mode 100644 index 0000000..564247b --- /dev/null +++ b/indefero/src/IDF/IssueFile.php @@ -0,0 +1,137 @@ +_a['table'] = 'idf_issuefiles'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + //It is automatically added. + 'blank' => true, + ), + 'comment' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_IssueComment', + 'blank' => false, + 'verbose' => __('comment'), + 'relate_name' => 'attachment', + ), + 'submitter' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'Pluf_User', + 'blank' => false, + 'verbose' => __('submitter'), + ), + 'filename' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => true, + 'size' => 100, + 'verbose' => __('file name'), + ), + 'attachment' => + array( + 'type' => 'Pluf_DB_Field_File', + 'blank' => false, + 'verbose' => __('the file'), + ), + 'filesize' => + array( + 'type' => 'Pluf_DB_Field_Integer', + 'blank' => true, + 'verbose' => __('file size'), + 'help_text' => 'Size in bytes.', + ), + 'type' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 10, + 'verbose' => __('type'), + 'choices' => array( + __('Image') => 'img', + __('Other') => 'other', + ), + 'default' => 'other', + 'help_text' => 'The type is to display a thumbnail of the image.', + ), + 'creation_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('creation date'), + ), + 'modif_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('modification date'), + ), + ); + } + + function preSave($create=false) + { + if ($this->id == '') { + $this->creation_dtime = gmdate('Y-m-d H:i:s'); + $file = Pluf::f('upload_issue_path').'/'.$this->attachment; + $this->filesize = filesize($file); + // remove .dummy + $this->filename = substr(basename($file), 0, -6); + $img_extensions = array('jpeg', 'jpg', 'png', 'gif'); + $info = pathinfo($this->filename); + if (!isset($info['extension'])) $info['extension'] = ''; + if (in_array(strtolower($info['extension']), $img_extensions)) { + $this->type = 'img'; + } else { + $this->type = 'other'; + } + } + $this->modif_dtime = gmdate('Y-m-d H:i:s'); + } + + function preDelete() + { + @unlink(Pluf::f('upload_issue_path').'/'.$this->attachment); + } + + function isText() + { + $info = IDF_FileUtil::getMimeType($this->filename); + return IDF_FileUtil::isText($info); + } +} diff --git a/indefero/src/IDF/IssueRelation.php b/indefero/src/IDF/IssueRelation.php new file mode 100644 index 0000000..b0048dd --- /dev/null +++ b/indefero/src/IDF/IssueRelation.php @@ -0,0 +1,100 @@ +_a['table'] = 'idf_issuerelations'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + 'blank' => true, + ), + 'issue' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_Issue', + 'blank' => false, + 'verbose' => __('issue'), + 'relate_name' => 'related_issues', + ), + 'verb' => + array( + 'type' => 'Pluf_DB_Field_Text', + 'blank' => false, + 'verbose' => __('verb'), + ), + 'other_issue' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_Issue', + 'blank' => false, + 'verbose' => __('other issue'), + 'relate_name' => 'related_other_issues', + ), + 'submitter' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'Pluf_User', + 'blank' => false, + 'verbose' => __('submitter'), + ), + 'creation_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('creation date'), + ), + ); + $this->_a['idx'] = array( + 'creation_dtime_idx' => + array( + 'col' => 'creation_dtime', + 'type' => 'normal', + ), + ); + $issuetbl = $this->_con->pfx.'idf_issues'; + $this->_a['views'] = array( + 'with_other_issue' => array( + 'join' => 'INNER JOIN '.$issuetbl.' ON other_issue='.$issuetbl.'.id', + 'select' => $this->getSelect().', summary', + 'props' => array('summary' => 'other_summary'), + )); + } + + function preSave($create=false) + { + if ($this->id == '') { + $this->creation_dtime = gmdate('Y-m-d H:i:s'); + } + } +} diff --git a/indefero/src/IDF/Key.php b/indefero/src/IDF/Key.php new file mode 100644 index 0000000..85c9469 --- /dev/null +++ b/indefero/src/IDF/Key.php @@ -0,0 +1,185 @@ +_a['table'] = 'idf_keys'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + //It is automatically added. + 'blank' => true, + ), + 'user' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'Pluf_User', + 'blank' => false, + 'verbose' => __('user'), + ), + 'content' => + array( + 'type' => 'Pluf_DB_Field_Text', + 'blank' => false, + 'verbose' => __('public key'), + ), + ); + // WARNING: Not using getSqlTable on the Pluf_User object to + // avoid recursion. + $t_users = $this->_con->pfx.'users'; + $this->_a['views'] = array( + 'join_user' => + array( + 'join' => 'LEFT JOIN '.$t_users + .' ON '.$t_users.'.id='.$this->_con->qn('user'), + 'select' => $this->getSelect().', ' + .$t_users.'.login AS login', + 'props' => array('login' => 'login'), + ) + ); + } + + function showCompact() + { + return Pluf_Template::markSafe(Pluf_esc(substr($this->content, 0, 25)).' [...] '.Pluf_esc(substr($this->content, -55))); + } + + private function parseContent() + { + if (preg_match('#^\[pubkey ([^\]]+)\]\s*(\S+)\s*\[end\]$#', $this->content, $m)) { + return array('mtn', $m[1], $m[2]); + } + else if (preg_match('#^ssh\-(?:dss|rsa)\s(\S+)(?:\s(.*))?$#', $this->content, $m)) { + if (!isset($m[2])) { + $m[2] = ""; + } + return array('ssh', $m[2], $m[1]); + } + + throw new Exception(__('Invalid or unknown key data detected.')); + } + + /** + * Returns the type of the public key + * + * @return string 'ssh' or 'mtn' + */ + function getType() + { + list($type, , ) = $this->parseContent(); + return $type; + } + + /** + * Returns the key name of the key + * + * @return string + */ + function getName() + { + list(, $keyName, ) = $this->parseContent(); + return $keyName; + } + + /** + * This function should be used to calculate the key id from the + * public key hash for authentication purposes. This avoids clashes + * in case the key name is not unique across the project + * + * And yes, this is actually how monotone itself calculates the key + * id... + * + * @return string + */ + function getMtnId() + { + list($type, $keyName, $keyData) = $this->parseContent(); + if ($type != 'mtn') + throw new Exception('key is not a monotone public key'); + return sha1($keyName.":".$keyData); + } + + function postSave($create=false) + { + /** + * [signal] + * + * IDF_Key::postSave + * + * [sender] + * + * IDF_Key + * + * [description] + * + * This signal allows an application to perform special + * operations after the saving of a public Key. + * + * [parameters] + * + * array('key' => $key, + * 'created' => true/false) + * + */ + $params = array('key' => $this, 'created' => $create); + Pluf_Signal::send('IDF_Key::postSave', + 'IDF_Key', $params); + } + + function preDelete() + { + /** + * [signal] + * + * IDF_Key::preDelete + * + * [sender] + * + * IDF_Key + * + * [description] + * + * This signal allows an application to perform special + * operations before a key is deleted. + * + * [parameters] + * + * array('key' => $key) + * + */ + $params = array('key' => $this); + Pluf_Signal::send('IDF_Key::preDelete', + 'IDF_Key', $params); + } +} diff --git a/indefero/src/IDF/Middleware.php b/indefero/src/IDF/Middleware.php new file mode 100644 index 0000000..c59217b --- /dev/null +++ b/indefero/src/IDF/Middleware.php @@ -0,0 +1,123 @@ +project to the project. + * + * The url to match a project is in the format /p/(\w+)/whatever + * or /api/p/(\w+)/whatever. This means that it will not try to + * match on /login/ or /logout/. + * + * @param Pluf_HTTP_Request The request + * @return bool false or redirect. + */ + function process_request(&$request) + { + $match = array(); + if (preg_match('#^/(?:api/p|p)/([\-\w]+)/?#', $request->query, $match)) { + try { + $request->project = IDF_Project::getOr404($match[1]); + } catch (Pluf_HTTP_Error404 $e) { + return new Pluf_HTTP_Response_NotFound($request); + } + $request->conf = new IDF_Conf(); + $request->conf->setProject($request->project); + self::setRights($request); + } + return false; + } + + public static function setRights(&$request) + { + $ak = array('downloads_access_rights' => 'hasDownloadsAccess', + 'wiki_access_rights' => 'hasWikiAccess', + 'review_access_rights' => 'hasReviewAccess', + 'source_access_rights' => 'hasSourceAccess', + 'issues_access_rights' => 'hasIssuesAccess'); + $request->rights = array(); + foreach ($ak as $key=>$val) { + $request->rights[$val] = (true === IDF_Precondition::accessTabGeneric($request, $key)); + } + } + + /** + * Update the template tags and modifiers to not have them in the config. + * + * This is here at the moment because we do not want to put that + * in a IDF_Template class just for one method. + * + */ + public static function updateTemplateTagsModifiers($sender, &$params) + { + $params['tags'] = array_merge($params['tags'], + array( + 'hotkey' => 'IDF_Template_HotKey', + 'issuetext' => 'IDF_Template_IssueComment', + 'timeline' => 'IDF_Template_TimelineFragment', + 'markdown' => 'IDF_Template_Markdown', + 'markdown_forge' => 'IDF_Template_MarkdownForge', + 'showuser' => 'IDF_Template_ShowUser', + 'ashowuser' => 'IDF_Template_AssignShowUser', + 'appversion' => 'IDF_Template_AppVersion', + 'upload' => 'IDF_Template_Tag_UploadUrl', + )); + $params['modifiers'] = array_merge($params['modifiers'], + array( + 'size' => 'IDF_Views_Source_PrettySize', + 'ssize' => 'IDF_Views_Source_PrettySizeSimple', + 'shorten' => 'IDF_Views_Source_ShortenString', + )); + } +} + + +function IDF_Middleware_ContextPreProcessor($request) +{ + $forge = IDF_Forge::instance(); + $c = array(); + $c['request'] = $request; + $c['isAdmin'] = ($request->user->administrator or $request->user->staff); + if (isset($request->project)) { + $c['project'] = $request->project; + $c['isOwner'] = $request->user->hasPerm('IDF.project-owner', + $request->project); + $c['isMember'] = $request->user->hasPerm('IDF.project-member', + $request->project); + $c = array_merge($c, $request->rights); + } + $c['usherConfigured'] = Pluf::f("mtn_usher_conf", null) !== null; + $c['allProjects'] = IDF_Views::getProjects($request->user); + $c['customForgePageEnabled'] = $forge->isCustomForgePageEnabled(); + return $c; +} + diff --git a/indefero/src/IDF/Migrations/10SshKey.php b/indefero/src/IDF/Migrations/10SshKey.php new file mode 100644 index 0000000..33f17dd --- /dev/null +++ b/indefero/src/IDF/Migrations/10SshKey.php @@ -0,0 +1,52 @@ +model = new $model(); + $schema->createTables(); + } +} + +function IDF_Migrations_10SshKey_down($params=null) +{ + $models = array( + 'IDF_Key', + ); + $db = Pluf::db(); + $schema = new Pluf_DB_Schema($db); + foreach ($models as $model) { + $schema->model = new $model(); + $schema->dropTables(); + } +} \ No newline at end of file diff --git a/indefero/src/IDF/Migrations/11GitCache.php b/indefero/src/IDF/Migrations/11GitCache.php new file mode 100644 index 0000000..ccc97c8 --- /dev/null +++ b/indefero/src/IDF/Migrations/11GitCache.php @@ -0,0 +1,52 @@ +model = new $model(); + $schema->createTables(); + } +} + +function IDF_Migrations_11GitCache_down($params=null) +{ + $models = array( + 'IDF_Scm_Cache_Git', + ); + $db = Pluf::db(); + $schema = new Pluf_DB_Schema($db); + foreach ($models as $model) { + $schema->model = new $model(); + $schema->dropTables(); + } +} \ No newline at end of file diff --git a/indefero/src/IDF/Migrations/12DownloadDesc.php b/indefero/src/IDF/Migrations/12DownloadDesc.php new file mode 100644 index 0000000..175cedb --- /dev/null +++ b/indefero/src/IDF/Migrations/12DownloadDesc.php @@ -0,0 +1,55 @@ +getSqlTable(); + $sql = array(); + $sql['PostgreSQL'] = 'ALTER TABLE '.$table.' ADD COLUMN "changelog" TEXT DEFAULT \'\''; + $sql['MySQL'] = 'ALTER TABLE '.$table.' ADD COLUMN `changelog` LONGTEXT DEFAULT \'\''; + $db = Pluf::db(); + $engine = Pluf::f('db_engine'); + if (!isset($sql[$engine])) { + throw new Exception('SQLite complex migration not supported.'); + } + $db->execute($sql[$engine]); +} + +function IDF_Migrations_12DownloadDesc_down($params=null) +{ + $table = Pluf::factory('IDF_Upload')->getSqlTable(); + $sql = array(); + $sql['PostgreSQL'] = 'ALTER TABLE '.$table.' DROP COLUMN "changelog"'; + $sql['MySQL'] = 'ALTER TABLE '.$table.' DROP COLUMN `changelog`'; + $db = Pluf::db(); + $engine = Pluf::f('db_engine'); + if (!isset($sql[$engine])) { + throw new Exception('SQLite complex migration not supported.'); + } + $db->execute($sql[$engine]); + +} \ No newline at end of file diff --git a/indefero/src/IDF/Migrations/13NewReview.php b/indefero/src/IDF/Migrations/13NewReview.php new file mode 100644 index 0000000..0b75ce8 --- /dev/null +++ b/indefero/src/IDF/Migrations/13NewReview.php @@ -0,0 +1,60 @@ +execute('DROP TABLE IF EXISTS '.$pfx.$table.$extra); + } + $models = array( + 'IDF_Review', + 'IDF_Review_Patch', + 'IDF_Review_Comment', + 'IDF_Review_FileComment', + ); + $db = Pluf::db(); + $schema = new Pluf_DB_Schema($db); + foreach ($models as $model) { + $schema->model = new $model(); + $schema->createTables(); + } +} + +function IDF_Migrations_13NewReview_down($params=null) +{ + // We do nothing as we cannot go back to the old reviews +} \ No newline at end of file diff --git a/indefero/src/IDF/Migrations/14Queue.php b/indefero/src/IDF/Migrations/14Queue.php new file mode 100644 index 0000000..36627e5 --- /dev/null +++ b/indefero/src/IDF/Migrations/14Queue.php @@ -0,0 +1,53 @@ +model = new $model(); + $schema->createTables(); + } +} + +function IDF_Migrations_14Queue_down($params=null) +{ + $models = array( + 'IDF_Queue', + ); + $db = Pluf::db(); + $schema = new Pluf_DB_Schema($db); + foreach ($models as $model) { + $schema->model = new $model(); + $schema->dropTables(); + } +} \ No newline at end of file diff --git a/indefero/src/IDF/Migrations/15AddGconf.php b/indefero/src/IDF/Migrations/15AddGconf.php new file mode 100644 index 0000000..9638725 --- /dev/null +++ b/indefero/src/IDF/Migrations/15AddGconf.php @@ -0,0 +1,53 @@ +model = new $model(); + $schema->createTables(); + } +} + +function IDF_Migrations_15AddGconf_down($params=null) +{ + $models = array( + 'IDF_Gconf', + ); + $db = Pluf::db(); + $schema = new Pluf_DB_Schema($db); + foreach ($models as $model) { + $schema->model = new $model(); + $schema->dropTables(); + } +} \ No newline at end of file diff --git a/indefero/src/IDF/Migrations/16AddUserMail.php b/indefero/src/IDF/Migrations/16AddUserMail.php new file mode 100644 index 0000000..2ef2365 --- /dev/null +++ b/indefero/src/IDF/Migrations/16AddUserMail.php @@ -0,0 +1,43 @@ +model = new IDF_EmailAddress(); + $schema->createTables(); +} + +function IDF_Migrations_16AddUserMail_down($params=null) +{ + $db = Pluf::db(); + $schema = new Pluf_DB_Schema($db); + $schema->model = new IDF_EmailAddress(); + $schema->dropTables(); +} diff --git a/indefero/src/IDF/Migrations/17AddIssueRelations.php b/indefero/src/IDF/Migrations/17AddIssueRelations.php new file mode 100644 index 0000000..e9f3636 --- /dev/null +++ b/indefero/src/IDF/Migrations/17AddIssueRelations.php @@ -0,0 +1,90 @@ +model = new IDF_IssueRelation(); + $schema->createTables(); + + // change the serialization format for added / removed labels in IDF_IssueComment + $comments = Pluf::factory('IDF_IssueComment')->getList(); + foreach ($comments as $comment) { + if (!isset($comment->changes['lb'])) continue; + $changes = $comment->changes; + $adds = $removals = array(); + foreach ($comment->changes['lb'] as $lb) { + if (substr($lb, 0, 1) == '-') + $removals[] = substr($lb, 1); + else + $adds[] = $lb; + } + $changes['lb'] = array(); + if (count($adds) > 0) + $changes['lb']['add'] = $adds; + if (count($removals) > 0) + $changes['lb']['rem'] = $removals; + $comment->changes = $changes; + $comment->update(); + } +} + +function IDF_Migrations_17AddIssueRelations_down($params=null) +{ + $db = Pluf::db(); + $schema = new Pluf_DB_Schema($db); + $schema->model = new IDF_IssueRelation(); + $schema->dropTables(); + + // change the serialization format for added / removed labels in IDF_IssueComment + $comments = Pluf::factory('IDF_IssueComment')->getList(); + foreach ($comments as $comment) { + $changes = $comment->changes; + if (empty($changes)) + continue; + if (isset($changes['lb'])) { + $labels = array(); + foreach ($changes['lb'] as $type => $lbs) { + if (!is_array($lbs)) { + $labels[] = $lbs; + continue; + } + foreach ($lbs as $lb) { + $labels[] = ($type == 'rem' ? '-' : '') . $lb; + } + } + $changes['lb'] = $labels; + } + // while we're at it, remove any 'rel' changes + unset($changes['rel']); + $comment->changes = $changes; + $comment->update(); + } +} + diff --git a/indefero/src/IDF/Migrations/18DownloadMD5.php b/indefero/src/IDF/Migrations/18DownloadMD5.php new file mode 100644 index 0000000..159e909 --- /dev/null +++ b/indefero/src/IDF/Migrations/18DownloadMD5.php @@ -0,0 +1,63 @@ +getSqlTable(); + $sql = array(); + $sql['PostgreSQL'] = 'ALTER TABLE '.$table.' ADD COLUMN "md5" VARCHAR(32) DEFAULT \'\''; + $sql['MySQL'] = 'ALTER TABLE '.$table.' ADD COLUMN `md5` VARCHAR(32) DEFAULT \'\''; + $db = Pluf::db(); + $engine = Pluf::f('db_engine'); + if (!isset($sql[$engine])) { + throw new Exception('SQLite complex migration not supported.'); + } + $db->execute($sql[$engine]); + + // Process md5 of already uploaded file + $files = Pluf::factory('IDF_Upload')->getList(); + foreach ($files as $f) { + $f->md5 = md5_file (Pluf::f('upload_path') . '/' . $f->get_project()->shortname . '/files/' . $f->file); + $f->update(); + } +} + +function IDF_Migrations_18DownloadMD5_down($params=null) +{ + // Remove the row + $table = Pluf::factory('IDF_Upload')->getSqlTable(); + $sql = array(); + $sql['PostgreSQL'] = 'ALTER TABLE '.$table.' DROP COLUMN "md5"'; + $sql['MySQL'] = 'ALTER TABLE '.$table.' DROP COLUMN `md5`'; + $db = Pluf::db(); + $engine = Pluf::f('db_engine'); + if (!isset($sql[$engine])) { + throw new Exception('SQLite complex migration not supported.'); + } + $db->execute($sql[$engine]); +} diff --git a/indefero/src/IDF/Migrations/19WikiPageAssocs.php b/indefero/src/IDF/Migrations/19WikiPageAssocs.php new file mode 100644 index 0000000..8371f17 --- /dev/null +++ b/indefero/src/IDF/Migrations/19WikiPageAssocs.php @@ -0,0 +1,74 @@ +pfx.'idf_tag_idf_wiki_page_assoc', $intro->listTables())) { + echo '19 skipping up migration - relation table has correct name already'."\n"; + return; + } + + $db->execute('ALTER TABLE '.$db->pfx.'idf_tag_idf_wikipage_assoc RENAME TO '.$db->pfx.'idf_tag_idf_wiki_page_assoc'); + $db->execute('ALTER TABLE '.$db->pfx.'idf_wikipage_pluf_user_assoc RENAME TO '.$db->pfx.'idf_wiki_page_pluf_user_assoc'); + + if ($engine === 'PostgreSQL') { + $db->execute('ALTER TABLE '.$db->pfx.'idf_tag_idf_wiki_page_assoc RENAME COLUMN idf_wikipage_id TO idf_wiki_page_id'); + $db->execute('ALTER TABLE '.$db->pfx.'idf_wiki_page_pluf_user_assoc RENAME COLUMN idf_wikipage_id TO idf_wiki_page_id'); + } else if ($engine === 'MySQL') { + $db->execute('ALTER TABLE '.$db->pfx.'idf_tag_idf_wiki_page_assoc CHANGE idf_wikipage_id idf_wiki_page_id MEDIUMINT NOT NULL'); + $db->execute('ALTER TABLE '.$db->pfx.'idf_wiki_page_pluf_user_assoc CHANGE idf_wikipage_id idf_wiki_page_id MEDIUMINT NOT NULL'); + } +} + +function IDF_Migrations_19WikiPageAssocs_down($params=null) +{ + $engine = Pluf::f('db_engine'); + if (!in_array($engine, array('MySQL', 'PostgreSQL'))) { + throw new Exception('unsupported engine '.$engine); + } + + $db = Pluf::db(); + $intro = new Pluf_DB_Introspect($db); + if (in_array($db->pfx.'idf_tag_idf_wikipage_assoc', $intro->listTables())) { + echo '19 skipping down migration - relation table has correct name already'."\n"; + return; + } + + $db->execute('ALTER TABLE '.$db->pfx.'idf_tag_idf_wiki_page_assoc RENAME TO '.$db->pfx.'idf_tag_idf_wikipage_assoc'); + $db->execute('ALTER TABLE '.$db->pfx.'idf_wiki_page_pluf_user_assoc RENAME TO '.$db->pfx.'idf_wikipage_pluf_user_assoc'); + + if ($engine === 'PostgreSQL') { + $db->execute('ALTER TABLE '.$db->pfx.'idf_tag_idf_wikipage_assoc RENAME COLUMN idf_wiki_page_id TO idf_wikipage_id'); + $db->execute('ALTER TABLE '.$db->pfx.'idf_wikipage_pluf_user_assoc RENAME COLUMN idf_wiki_page_id TO idf_wikipage_id'); + } else if ($engine === 'MySQL') { + $db->execute('ALTER TABLE '.$db->pfx.'idf_tag_idf_wikipage_assoc CHANGE idf_wiki_page_id idf_wikipage_id MEDIUMINT NOT NULL'); + $db->execute('ALTER TABLE '.$db->pfx.'idf_wikipage_pluf_user_assoc CHANGE idf_wiki_page_id idf_wikipage_id MEDIUMINT NOT NULL'); + } +} diff --git a/indefero/src/IDF/Migrations/1Download.php b/indefero/src/IDF/Migrations/1Download.php new file mode 100644 index 0000000..3f081bf --- /dev/null +++ b/indefero/src/IDF/Migrations/1Download.php @@ -0,0 +1,52 @@ +model = new $model(); + $schema->createTables(); + } +} + +function IDF_Migrations_1Download_down($params=null) +{ + $models = array( + 'IDF_Upload', + ); + $db = Pluf::db(); + $schema = new Pluf_DB_Schema($db); + foreach ($models as $model) { + $schema->model = new $model(); + $schema->dropTables(); + } +} \ No newline at end of file diff --git a/indefero/src/IDF/Migrations/20AddWikiResources.php b/indefero/src/IDF/Migrations/20AddWikiResources.php new file mode 100644 index 0000000..20d82eb --- /dev/null +++ b/indefero/src/IDF/Migrations/20AddWikiResources.php @@ -0,0 +1,51 @@ +model = new IDF_Wiki_Resource(); + $schema->createTables(); + + $schema->model = new IDF_Wiki_ResourceRevision(); + $schema->createTables(); +} + +function IDF_Migrations_20AddWikiResources_down($params=null) +{ + $db = Pluf::db(); + $schema = new Pluf_DB_Schema($db); + + $schema->model = new IDF_Wiki_ResourceRevision(); + $schema->dropTables(); + + $schema->model = new IDF_Wiki_Resource(); + $schema->dropTables(); +} diff --git a/indefero/src/IDF/Migrations/21WikiPageRevisionName.php b/indefero/src/IDF/Migrations/21WikiPageRevisionName.php new file mode 100644 index 0000000..31fc1b3 --- /dev/null +++ b/indefero/src/IDF/Migrations/21WikiPageRevisionName.php @@ -0,0 +1,68 @@ +pfx.'idf_wikipagerevs', $intro->listTables())) { + echo '21 skipping up migration - table has correct name already'."\n"; + return; + } + + $db->execute('ALTER TABLE '.$db->pfx.'idf_wikirevisions RENAME TO '.$db->pfx.'idf_wikipagerevs'); + $db->execute("UPDATE ".$db->pfx."idf_timeline SET model_class='IDF_Wiki_Page' WHERE model_class LIKE 'IDF_WikiPage'"); + $db->execute("UPDATE ".$db->pfx."idf_timeline SET model_class='IDF_Wiki_PageRevision' WHERE model_class LIKE 'IDF_WikiRevision'"); + $db->execute("UPDATE ".$db->pfx."idf_search_occs SET model_class='IDF_Wiki_Page' WHERE model_class LIKE 'IDF_WikiPage'"); + $db->execute("UPDATE ".$db->pfx."idf_search_occs SET model_class='IDF_Wiki_PageRevision' WHERE model_class LIKE 'IDF_WikiRevision'"); + $db->execute("UPDATE ".$db->pfx."pluf_search_stats SET model_class='IDF_Wiki_Page' WHERE model_class LIKE 'IDF_WikiPage'"); + $db->execute("UPDATE ".$db->pfx."pluf_search_stats SET model_class='IDF_Wiki_PageRevision' WHERE model_class LIKE 'IDF_WikiRevision'"); +} + +function IDF_Migrations_21WikiPageRevisionName_down($params=null) +{ + $engine = Pluf::f('db_engine'); + if (!in_array($engine, array('MySQL', 'PostgreSQL'))) { + throw new Exception('unsupported engine '.$engine); + } + + $db = Pluf::db(); + $intro = new Pluf_DB_Introspect($db); + if (in_array($db->pfx.'idf_wikirevisions', $intro->listTables())) { + echo '21 skipping down migration - table has correct name already'."\n"; + return; + } + + $db->execute('ALTER TABLE '.$db->pfx.'idf_wikipagerevs RENAME TO '.$db->pfx.'idf_wikirevisions'); + $db->execute("UPDATE ".$db->pfx."idf_timeline SET model_class='IDF_WikiPage' WHERE model_class LIKE 'IDF_Wiki_Page'"); + $db->execute("UPDATE ".$db->pfx."idf_timeline SET model_class='IDF_WikiRevision' WHERE model_class LIKE 'IDF_Wiki_PageRevision'"); + $db->execute("UPDATE ".$db->pfx."idf_search_occs SET model_class='IDF_WikiPage' WHERE model_class LIKE 'IDF_Wiki_Page'"); + $db->execute("UPDATE ".$db->pfx."idf_search_occs SET model_class='IDF_WikiRevision' WHERE model_class LIKE 'IDF_Wiki_PageRevision'"); + $db->execute("UPDATE ".$db->pfx."pluf_search_stats SET model_class='IDF_WikiPage' WHERE model_class LIKE 'IDF_Wiki_Page'"); + $db->execute("UPDATE ".$db->pfx."pluf_search_stats SET model_class='IDF_WikiRevision' WHERE model_class LIKE 'IDF_Wiki_PageRevision'"); +} diff --git a/indefero/src/IDF/Migrations/22ProjectTagRelationTable.php b/indefero/src/IDF/Migrations/22ProjectTagRelationTable.php new file mode 100644 index 0000000..5113af1 --- /dev/null +++ b/indefero/src/IDF/Migrations/22ProjectTagRelationTable.php @@ -0,0 +1,60 @@ +pfx.'idf_project_idf_tag_assoc'; + if (!in_array($db->engine, array('MySQL', 'PostgreSQL'))) { + throw new Exception('unsupported engine '.$engine); + } + + $intro = new Pluf_DB_Introspect($db); + if (in_array($table, $intro->listTables())) { + echo '21 skipping up migration - table already exists'."\n"; + return; + } + + $schema = Pluf::factory('Pluf_DB_Schema_'.$db->engine, $db); + $sql = $schema->getSqlCreate(new IDF_Project()); + $db->execute($sql[$table]); +} + +function IDF_Migrations_22ProjectTagRelationTable_down($params=null) +{ + $db = Pluf::db(); + $table = $db->pfx.'idf_project_idf_tag_assoc'; + if (!in_array($db->engine, array('MySQL', 'PostgreSQL'))) { + throw new Exception('unsupported engine '.$engine); + } + + $intro = new Pluf_DB_Introspect($db); + if (!in_array($table, $intro->listTables())) { + echo '22 skipping down migration - table does not exist'."\n"; + return; + } + + $schema = Pluf::factory('Pluf_DB_Schema_'.$db->engine, $db); + $sql = $schema->getSqlDelete(new IDF_Project()); + $db->execute($sql[$table]); +} diff --git a/indefero/src/IDF/Migrations/23ProjectActivity.php b/indefero/src/IDF/Migrations/23ProjectActivity.php new file mode 100644 index 0000000..bf4b2a7 --- /dev/null +++ b/indefero/src/IDF/Migrations/23ProjectActivity.php @@ -0,0 +1,42 @@ +model = new IDF_ProjectActivity(); + $schema->createTables(); +} + +function IDF_Migrations_23ProjectActivity_down($params=null) +{ + $db = Pluf::db(); + $schema = new Pluf_DB_Schema($db); + $schema->model = new IDF_ProjectActivity(); + $schema->dropTables(); +} diff --git a/indefero/src/IDF/Migrations/24CurrentProjectActivity.php b/indefero/src/IDF/Migrations/24CurrentProjectActivity.php new file mode 100644 index 0000000..78483b1 --- /dev/null +++ b/indefero/src/IDF/Migrations/24CurrentProjectActivity.php @@ -0,0 +1,40 @@ +execute('ALTER TABLE '.$db->pfx.'idf_projects ADD COLUMN current_activity INTEGER'); + } else if ($engine === 'MySQL') { + $db->execute('ALTER TABLE '.$db->pfx.'idf_projects ADD COLUMN current_activity MEDIUMINT'); + } +} + +function IDF_Migrations_24CurrentProjectActivity_down($params=null) +{ + $db = Pluf::db(); + $db->execute('ALTER TABLE '.$db->pfx.'idf_projects DROP COLUMN current_activity'); +} diff --git a/indefero/src/IDF/Migrations/25NullableProjectInTag.php b/indefero/src/IDF/Migrations/25NullableProjectInTag.php new file mode 100644 index 0000000..0829acf --- /dev/null +++ b/indefero/src/IDF/Migrations/25NullableProjectInTag.php @@ -0,0 +1,47 @@ +execute('ALTER TABLE '.$db->pfx.'idf_tags ALTER COLUMN project DROP NOT NULL'); + } else if ($engine === 'MySQL') { + $db->execute('ALTER TABLE '.$db->pfx.'idf_tags MODIFY project MEDIUMINT NULL'); + // this is only needed for non-transactional setups where MySQL set 0 as default value + $db->execute('UPDATE '.$db->pfx.'idf_tags SET project=NULL WHERE project=0'); + } +} + +function IDF_Migrations_25NullableProjectInTag_down($params=null) +{ + $engine = Pluf::f('db_engine'); + $db = Pluf::db(); + if ($engine === 'PostgreSQL') { + $db->execute('ALTER TABLE '.$db->pfx.'idf_tags ALTER COLUMN project SET NOT NULL'); + } else if ($engine === 'MySQL') { + $db->execute('ALTER TABLE '.$db->pfx.'idf_tags MODIFY project MEDIUMINT NOT NULL'); + } +} diff --git a/indefero/src/IDF/Migrations/26NullableActivityInProject.php b/indefero/src/IDF/Migrations/26NullableActivityInProject.php new file mode 100644 index 0000000..6335d84 --- /dev/null +++ b/indefero/src/IDF/Migrations/26NullableActivityInProject.php @@ -0,0 +1,46 @@ +execute('ALTER TABLE '.$db->pfx.'idf_projects ALTER COLUMN current_activity DROP NOT NULL'); + } else if ($engine === 'MySQL') { + $db->execute('ALTER TABLE '.$db->pfx.'idf_projects MODIFY current_activity MEDIUMINT NULL'); + // this is only needed for non-transactional setups where MySQL set 0 as default value + $db->execute('UPDATE '.$db->pfx.'idf_projects SET current_activity=NULL WHERE current_activity=0'); + } +} + +function IDF_Migrations_26NullableActivityInProject_down($params=null) +{ + $engine = Pluf::f('db_engine'); + $db = Pluf::db(); + if ($engine === 'PostgreSQL') { + $db->execute('ALTER TABLE '.$db->pfx.'idf_projects ALTER COLUMN current_activity SET NOT NULL'); + } else if ($engine === 'MySQL') { + $db->execute('ALTER TABLE '.$db->pfx.'idf_projects MODIFY current_activity MEDIUMINT NOT NULL'); + } +} diff --git a/indefero/src/IDF/Migrations/2Search.php b/indefero/src/IDF/Migrations/2Search.php new file mode 100644 index 0000000..4f8e124 --- /dev/null +++ b/indefero/src/IDF/Migrations/2Search.php @@ -0,0 +1,55 @@ +model = new $model(); + $schema->createTables(); + } + foreach (Pluf::factory('IDF_Issue')->getList() as $i) { + IDF_Search::index($i); + } +} + +function IDF_Migrations_2Search_down($params=null) +{ + $models = array( + 'IDF_Search_Occ', + ); + $db = Pluf::db(); + $schema = new Pluf_DB_Schema($db); + foreach ($models as $model) { + $schema->model = new $model(); + $schema->dropTables(); + } +} \ No newline at end of file diff --git a/indefero/src/IDF/Migrations/3Attachments.php b/indefero/src/IDF/Migrations/3Attachments.php new file mode 100644 index 0000000..3e9611b --- /dev/null +++ b/indefero/src/IDF/Migrations/3Attachments.php @@ -0,0 +1,52 @@ +model = new $model(); + $schema->createTables(); + } +} + +function IDF_Migrations_3Attachments_down($params=null) +{ + $models = array( + 'IDF_IssueFile', + ); + $db = Pluf::db(); + $schema = new Pluf_DB_Schema($db); + foreach ($models as $model) { + $schema->model = new $model(); + $schema->dropTables(); + } +} \ No newline at end of file diff --git a/indefero/src/IDF/Migrations/4Timeline.php b/indefero/src/IDF/Migrations/4Timeline.php new file mode 100644 index 0000000..afa4e5d --- /dev/null +++ b/indefero/src/IDF/Migrations/4Timeline.php @@ -0,0 +1,54 @@ +model = new $model(); + $schema->createTables(); + } +} + +function IDF_Migrations_4Timeline_down($params=null) +{ + $models = array( + 'IDF_Timeline', + 'IDF_Commit', + ); + $db = Pluf::db(); + $schema = new Pluf_DB_Schema($db); + foreach ($models as $model) { + $schema->model = new $model(); + $schema->dropTables(); + } +} \ No newline at end of file diff --git a/indefero/src/IDF/Migrations/5DescToText.php b/indefero/src/IDF/Migrations/5DescToText.php new file mode 100644 index 0000000..40a1d63 --- /dev/null +++ b/indefero/src/IDF/Migrations/5DescToText.php @@ -0,0 +1,47 @@ +getSqlTable(); + $sql = array(); + $sql['PostgreSQL'] = 'ALTER TABLE '.$table.' ALTER vdesc TYPE text'; + $sql['MySQL'] = 'ALTER TABLE '.$table.' CHANGE vdesc TYPE text'; + $db = Pluf::db(); + $engine = Pluf::f('db_engine'); + if (!isset($sql[$engine])) { + echo 'Skip SQLite upgrade as not needed.'."\n"; + return; + } + $db->execute($sql[$engine]); +} + +function IDF_Migrations_5DescToText_down($params=null) +{ + // lazy, do not care + return; +} \ No newline at end of file diff --git a/indefero/src/IDF/Migrations/6PrivateProject.php b/indefero/src/IDF/Migrations/6PrivateProject.php new file mode 100644 index 0000000..eef47f1 --- /dev/null +++ b/indefero/src/IDF/Migrations/6PrivateProject.php @@ -0,0 +1,63 @@ +getSqlTable(); + $sql = array(); + $sql['PostgreSQL'] = 'ALTER TABLE '.$table.' ADD COLUMN "private" INTEGER DEFAULT 0'; + $sql['MySQL'] = 'ALTER TABLE '.$table.' ADD COLUMN `private` INTEGER DEFAULT 0'; + $db = Pluf::db(); + $engine = Pluf::f('db_engine'); + if (!isset($sql[$engine])) { + throw new Exception('SQLite complex migration not supported.'); + } + $db->execute($sql[$engine]); + $perm = new Pluf_Permission(); + $perm->name = 'Project authorized users'; + $perm->code_name = 'project-authorized-user'; + $perm->description = 'Permission given to users allowed to access a project.'; + $perm->application = 'IDF'; + $perm->create(); +} + +function IDF_Migrations_6PrivateProject_down($params=null) +{ + $perm = Pluf_Permission::getFromString('IDF.project-authorized-user'); + if ($perm) $perm->delete(); + $table = Pluf::factory('IDF_Project')->getSqlTable(); + $sql = array(); + $sql['PostgreSQL'] = 'ALTER TABLE '.$table.' DROP COLUMN "private"'; + $sql['MySQL'] = 'ALTER TABLE '.$table.' DROP COLUMN `private`'; + $db = Pluf::db(); + $engine = Pluf::f('db_engine'); + if (!isset($sql[$engine])) { + throw new Exception('SQLite complex migration not supported.'); + } + $db->execute($sql[$engine]); + +} \ No newline at end of file diff --git a/indefero/src/IDF/Migrations/7Wiki.php b/indefero/src/IDF/Migrations/7Wiki.php new file mode 100644 index 0000000..5330d63 --- /dev/null +++ b/indefero/src/IDF/Migrations/7Wiki.php @@ -0,0 +1,54 @@ +model = new $model(); + $schema->createTables(); + } +} + +function IDF_Migrations_7Wiki_down($params=null) +{ + $models = array( + 'IDF_Wiki_PageRevision', + 'IDF_Wiki_Page', + ); + $db = Pluf::db(); + $schema = new Pluf_DB_Schema($db); + foreach ($models as $model) { + $schema->model = new $model(); + $schema->dropTables(); + } +} \ No newline at end of file diff --git a/indefero/src/IDF/Migrations/8CodeReview.php b/indefero/src/IDF/Migrations/8CodeReview.php new file mode 100644 index 0000000..6b0c5e7 --- /dev/null +++ b/indefero/src/IDF/Migrations/8CodeReview.php @@ -0,0 +1,56 @@ +model = new $model(); + $schema->createTables(); + } +} + +function IDF_Migrations_8CodeReview_down($params=null) +{ + $models = array( + 'IDF_Review_FileComment', + 'IDF_Review_Patch', + 'IDF_Review', + ); + $db = Pluf::db(); + $schema = new Pluf_DB_Schema($db); + foreach ($models as $model) { + $schema->model = new $model(); + $schema->dropTables(); + } +} \ No newline at end of file diff --git a/indefero/src/IDF/Migrations/9ShortDescription.php b/indefero/src/IDF/Migrations/9ShortDescription.php new file mode 100644 index 0000000..0a258fc --- /dev/null +++ b/indefero/src/IDF/Migrations/9ShortDescription.php @@ -0,0 +1,55 @@ +getSqlTable(); + $sql = array(); + $sql['PostgreSQL'] = 'ALTER TABLE '.$table.' ADD COLUMN "shortdesc" VARCHAR(255) DEFAULT \'\''; + $sql['MySQL'] = 'ALTER TABLE '.$table.' ADD COLUMN `shortdesc` VARCHAR(255) DEFAULT \'\''; + $db = Pluf::db(); + $engine = Pluf::f('db_engine'); + if (!isset($sql[$engine])) { + throw new Exception('SQLite complex migration not supported.'); + } + $db->execute($sql[$engine]); +} + +function IDF_Migrations_9ShortDescription_down($params=null) +{ + $table = Pluf::factory('IDF_Project')->getSqlTable(); + $sql = array(); + $sql['PostgreSQL'] = 'ALTER TABLE '.$table.' DROP COLUMN "shortdesc"'; + $sql['MySQL'] = 'ALTER TABLE '.$table.' DROP COLUMN `shortdesc`'; + $db = Pluf::db(); + $engine = Pluf::f('db_engine'); + if (!isset($sql[$engine])) { + throw new Exception('SQLite complex migration not supported.'); + } + $db->execute($sql[$engine]); + +} \ No newline at end of file diff --git a/indefero/src/IDF/Migrations/Backup.php b/indefero/src/IDF/Migrations/Backup.php new file mode 100644 index 0000000..7145560 --- /dev/null +++ b/indefero/src/IDF/Migrations/Backup.php @@ -0,0 +1,127 @@ +model = new $model(); + $schema->createTables(); + } + $full_data = json_decode(file_get_contents(sprintf('%s/%s-IDF.json', $folder, $name)), true); + foreach ($full_data as $model => $data) { + Pluf_Test_Fixture::load($data, false); + } + foreach ($models as $model) { + $schema->model = new $model(); + $schema->createConstraints(); + } + return true; +} diff --git a/indefero/src/IDF/Migrations/Install.php b/indefero/src/IDF/Migrations/Install.php new file mode 100644 index 0000000..89b5880 --- /dev/null +++ b/indefero/src/IDF/Migrations/Install.php @@ -0,0 +1,135 @@ +model = new $model(); + $schema->createTables(); + } + foreach ($models as $model) { + $schema->model = new $model(); + $schema->createConstraints(); + } + // Install the permissions + $perm = new Pluf_Permission(); + $perm->name = 'Project membership'; + $perm->code_name = 'project-member'; + $perm->description = 'Permission given to project members.'; + $perm->application = 'IDF'; + $perm->create(); + $perm = new Pluf_Permission(); + $perm->name = 'Project ownership'; + $perm->code_name = 'project-owner'; + $perm->description = 'Permission given to project owners.'; + $perm->application = 'IDF'; + $perm->create(); + $perm = new Pluf_Permission(); + $perm->name = 'Project authorized users'; + $perm->code_name = 'project-authorized-user'; + $perm->description = 'Permission given to users allowed to access a project.'; + $perm->application = 'IDF'; + $perm->create(); +} + +function IDF_Migrations_Install_teardown($params=null) +{ + $perm = Pluf_Permission::getFromString('IDF.project-member'); + if ($perm) $perm->delete(); + $perm = Pluf_Permission::getFromString('IDF.project-owner'); + if ($perm) $perm->delete(); + $perm = Pluf_Permission::getFromString('IDF.project-authorized-user'); + if ($perm) $perm->delete(); + $models = array( + 'IDF_Gconf', + 'IDF_Queue', + 'IDF_Scm_Cache_Git', + 'IDF_Key', + 'IDF_Review_FileComment', + 'IDF_Review_Comment', + 'IDF_Review_Patch', + 'IDF_Review', + 'IDF_Wiki_PageRevision', + 'IDF_Wiki_Page', + 'IDF_Wiki_ResourceRevision', + 'IDF_Wiki_Resource', + 'IDF_Timeline', + 'IDF_IssueFile', + 'IDF_Search_Occ', + 'IDF_Upload', + 'IDF_Conf', + 'IDF_IssueComment', + 'IDF_Issue', + 'IDF_Tag', + 'IDF_Commit', + 'IDF_ProjectActivity', + 'IDF_Project', + 'IDF_EmailAddress', + 'IDF_IssueRelation', + ); + $db = Pluf::db(); + $schema = new Pluf_DB_Schema($db); + foreach ($models as $model) { + $schema->model = new $model(); + $schema->dropConstraints(); + } + foreach ($models as $model) { + $schema->model = new $model(); + $schema->dropTables(); + } +} diff --git a/indefero/src/IDF/Plugin/SyncGit.php b/indefero/src/IDF/Plugin/SyncGit.php new file mode 100644 index 0000000..ac527a1 --- /dev/null +++ b/indefero/src/IDF/Plugin/SyncGit.php @@ -0,0 +1,81 @@ +id)); + IDF_Scm::syncTimeline($project, true); + Pluf_Log::event(array('IDF_Plugin_SyncGit::postUpdate', 'sync', array($pname, $project->id))); + } +} diff --git a/indefero/src/IDF/Plugin/SyncGit/Cron.php b/indefero/src/IDF/Plugin/SyncGit/Cron.php new file mode 100644 index 0000000..bbbf55e --- /dev/null +++ b/indefero/src/IDF/Plugin/SyncGit/Cron.php @@ -0,0 +1,141 @@ +template; + $cmd = Pluf::f('idf_plugin_syncgit_path_gitserve', '/dev/null'); + $authorized_keys = Pluf::f('idf_plugin_syncgit_path_authorized_keys', false); + if (false == $authorized_keys) { + throw new Pluf_Exception_SettingError('Setting idf_plugin_syncgit_path_authorized_keys not set.'); + } + if (!is_writable($authorized_keys)) { + throw new Exception('Cannot create file: '.$authorized_keys); + } + $out = ''; + $keys = Pluf::factory('IDF_Key')->getList(array('view'=>'join_user')); + foreach ($keys as $key) { + try { + $key_type = $key->getType(); + } catch (Exception $e) { + // The key is a bad key, skip it + continue; + } + if ($key_type == 'ssh' and preg_match('/^[a-zA-Z][a-zA-Z0-9_.-]*(@[a-zA-Z][a-zA-Z0-9.-]*)?$/', $key->login)) { + $content = trim(str_replace(array("\n", "\r"), '', $key->content)); + $out .= sprintf($template, $cmd, $key->login, $content)."\n"; + } + } + $out = "# indefero start" . PHP_EOL . $out . "# indefero end" . PHP_EOL; + + // We update only the part of the file between IDF_START / IDF_END comment + $original_keys = file_get_contents($authorized_keys); + if (strstr($original_keys, "# indefero start") && strstr($original_keys, "# indefero end")) { + $out = preg_replace('%(#\sindefero\sstart).+(#\sindefero\send\s\s?)%isU', + $out, $original_keys); + } else { + $out .= $original_keys; + } + file_put_contents($authorized_keys, $out, LOCK_EX); + } + + /** + * Mark export of git repositories for the daemon. + */ + public static function markExport() + { + foreach (Pluf::factory('IDF_Project')->getList() as $project) { + $rep = sprintf(Pluf::f('git_repositories'), $project->shortname); + $serve = new IDF_Plugin_SyncGit_Serve(); + $serve->setGitExport($project->shortname, $rep); + } + } + + /** + * Remove orphan repositories. + */ + public static function removeOrphanRepositories() + { + $path = Pluf::f('idf_plugin_syncgit_base_repositories', '/home/git/repositories'); + if (!is_dir($path) || is_link($path)) { + throw new Pluf_Exception_SettingError(sprintf( + 'Directory %s does not exist! Setting "idf_plugin_syncgit_base_repositories not set.', + $path)); + } + if (!is_writable($path)) { + throw new Exception(sprintf('Repository %s is not writable.', $path)); + } + $projects = array(); + foreach (Pluf::factory('IDF_Project')->getList() as $project) { + $projects[] = $project->shortname; + } + unset($project); + $it = new DirectoryIterator($path); + $orphans = array(); + while ($it->valid()) { + if (!$it->isDot() && $it->isDir() && !in_array(basename($it->getFileName(), '.git'), $projects)) { + $orphans[] = $it->getPathName(); + } + $it->next(); + } + if (count($orphans)) { + $cmd = Pluf::f('idf_exec_cmd_prefix', '').'rm -rf '.implode(' ', $orphans); + exec($cmd); + clearstatcache(); + while (list(, $project) = each($orphans)) { + if (is_dir($project)) { + throw new Exception(sprintf('Cannot remove %s directory.', $project)); + } + } + } + } + + /** + * Check if a sync is needed. + * + */ + public static function main() + { + if (file_exists(Pluf::f('idf_plugin_syncgit_sync_file'))) { + @unlink(Pluf::f('idf_plugin_syncgit_sync_file')); + self::sync(); + self::markExport(); + if (Pluf::f('idf_plugin_syncgit_remove_orphans', false)) { + self::removeOrphanRepositories(); + } + } + } +} diff --git a/indefero/src/IDF/Plugin/SyncGit/Serve.php b/indefero/src/IDF/Plugin/SyncGit/Serve.php new file mode 100644 index 0000000..83fda42 --- /dev/null +++ b/indefero/src/IDF/Plugin/SyncGit/Serve.php @@ -0,0 +1,317 @@ +[a-zA-Z0-9][a-zA-Z0-9@._-]*(/[a-zA-Z0-9][a-zA-Z0-9@._-]*)*)\'$#'; + + public $commands_readonly = array('git-upload-pack', 'git upload-pack'); + public $commands_write = array('git-receive-pack', 'git receive-pack'); + + /** + * Serve a git request. + * + * @param string Username. + * @param string Command to be run. + */ + public function serve($username, $cmd) + { + if (false !== strpos($cmd, "\n")) { + throw new Exception('Command may not contain newline.'); + } + $splitted = preg_split('/\s/', $cmd, 2); + if (count($splitted) != 2) { + throw new Exception('Unknown command denied.'); + } + if ($splitted[0] == 'git') { + $sub_splitted = preg_split('/\s/', $splitted[1], 2); + if (count($sub_splitted) != 2) { + throw new Exception('Unknown command denied.'); + } + $verb = sprintf('%s %s', $splitted[0], $sub_splitted[0]); + $args = $sub_splitted[1]; + } else { + $verb = $splitted[0]; + $args = $splitted[1]; + } + if (!in_array($verb, $this->commands_write) + and !in_array($verb, $this->commands_readonly)) { + throw new Exception('Unknown command denied.'); + } + if (!preg_match($this->preg, $args, $matches)) { + throw new Exception('Arguments to command look dangerous.'); + } + $path = $matches['path']; + // Check read/write rights + $new_path = $this->haveAccess($username, $path, 'writable'); + if ($new_path == false) { + $new_path = $this->haveAccess($username, $path, 'readonly'); + if ($new_path == false) { + throw new Exception('Repository read access denied.'); + } + if (in_array($verb, $this->commands_write)) { + throw new Exception('Repository write access denied.'); + } + } + list($topdir, $relpath) = $new_path; + $repopath = sprintf('%s.git', $relpath); + $fullpath = $topdir.DIRECTORY_SEPARATOR.$repopath; + if (!file_exists($fullpath) + and in_array($verb, $this->commands_write)) { + // it doesn't exist on the filesystem, but the + // configuration refers to it, we're serving a write + // request, and the user is authorized to do that: create + // the repository on the fly + $p = explode(DIRECTORY_SEPARATOR, $fullpath); + $mpath = implode(DIRECTORY_SEPARATOR, array_slice($p, 0, -1)); + if (!file_exists($mpath)) { + mkdir($mpath, 0750, true); + } + $this->initRepository($fullpath); + $this->setGitExport($relpath, $fullpath); + } + $new_cmd = sprintf("%s '%s'", $verb, $fullpath); + Pluf_Log::info(array('IDF_Plugin_Git_Serve::serve', $username, $cmd, $new_cmd)); + return $new_cmd; + } + + /** + * Main function called by the serve script. + */ + public static function main($argv, $env) + { + if (count($argv) != 2) { + self::fatalError('Missing argument USER.'); + } + $username = $argv[1]; + umask(0022); + if (!isset($env['SSH_ORIGINAL_COMMAND'])) { + self::fatalError('Need SSH_ORIGINAL_COMMAND in environment.'); + } + $cmd = $env['SSH_ORIGINAL_COMMAND']; + chdir(Pluf::f('idf_plugin_syncgit_git_home_dir', '/home/git')); + $serve = new IDF_Plugin_SyncGit_Serve(); + try { + $new_cmd = $serve->serve($username, $cmd); + } catch (Exception $e) { + self::fatalError($e->getMessage()); + } + print $new_cmd; + exit(0); + } + + /** + * Control the access rights to the repository. + * + * @param string Username + * @param string Path including the possible .git + * @param string Type of access. 'readonly' or ('writable') + * @return mixed False or array(base_git_reps, relative path to repo) + */ + public function haveAccess($username, $path, $mode='writable') + { + if ('.git' == substr($path, -4)) { + $path = substr($path, 0, -4); + } + $sql = new Pluf_SQL('shortname=%s', array($path)); + $projects = Pluf::factory('IDF_Project')->getList(array('filter'=>$sql->gen())); + if ($projects->count() != 1) { + return false; + } + $project = $projects[0]; + $conf = new IDF_Conf(); + $conf->setProject($project); + $scm = $conf->getVal('scm', 'git'); + if ($scm != 'git') { + return false; + } + $sql = new Pluf_SQL('login=%s', array($username)); + $users = Pluf::factory('Pluf_User')->getList(array('filter'=>$sql->gen())); + if ($users->count() != 1 or !$users[0]->active) { + return false; + } + $user = $users[0]; + $request = new StdClass(); + $request->user = $user; + $request->conf = $conf; + $request->project = $project; + if (true === IDF_Precondition::accessSource($request)) { + if ($mode == 'readonly') { + return array(Pluf::f('idf_plugin_syncgit_base_repositories', '/home/git/repositories'), + $project->shortname); + } + if (true === IDF_Precondition::projectMemberOrOwner($request)) { + return array(Pluf::f('idf_plugin_syncgit_base_repositories', '/home/git/repositories'), + $project->shortname); + } + } + return false; + } + + /** + * Die on a message on stderr. + * + * @param string Message + */ + public static function fatalError($mess) + { + fwrite(STDERR, $mess."\n"); + exit(1); + } + + /** + * Init a new empty bare repository. + * + * @param string Full path to the repository + */ + public function initRepository($fullpath) + { + if (!file_exists($fullpath)) { + mkdir($fullpath, 0750, true); + } + $out = array(); + $res = 0; + exec(sprintf(Pluf::f('idf_exec_cmd_prefix', ''). + Pluf::f('git_path', 'git').' --git-dir=%s init', escapeshellarg($fullpath)), + $out, $res); + if ($res != 0) { + Pluf_Log::error(array('IDF_Plugin_Git_Serve::initRepository', $res, $fullpath)); + throw new Exception(sprintf('Init repository error, exit status %d.', $res)); + } + Pluf_Log::event(array('IDF_Plugin_Git_Serve::initRepository', 'success', $fullpath)); + // Add the post-update hook by removing the original one and add the + // Indefero's one. + $p = realpath(dirname(__FILE__).'/../../../../scripts/git-post-update'); + $p = Pluf::f('idf_plugin_syncgit_post_update', $p); + $post_update_hook = $fullpath.'/hooks/post-update'; + if (file_exists($post_update_hook) && !@unlink($post_update_hook)) { + Pluf_Log::warn(array('IDF_Plugin_Git_Serve::initRepository', + 'post-update hook removal error.', + $post_update_hook)); + return; + } + $out = array(); + $res = 0; + exec(sprintf(Pluf::f('idf_exec_cmd_prefix', '').'ln -s %s %s', + escapeshellarg($p), + escapeshellarg($post_update_hook)), + $out, $res); + if ($res != 0) { + Pluf_Log::warn(array('IDF_Plugin_Git_Serve::initRepository', + 'post-update hook creation error.', + $post_update_hook)); + return; + } + Pluf_Log::debug(array('IDF_Plugin_Git_Serve::initRepository', + 'Added post-update hook.', $fullpath)); + // Configure the core.quotepath option + $quotepath = (Pluf::f('git_core_quotepath', true) == true) ? 'true' : 'false'; + $out = array(); + $res = 0; + exec(sprintf(Pluf::f('idf_exec_cmd_prefix', ''). + Pluf::f('git_path', 'git').' config -f %s/config --add core.quotepath %s', + escapeshellarg($fullpath), + escapeshellarg($quotepath) + ), + $out, $res); + if ($res != 0) { + Pluf_Log::warn(array('IDF_Plugin_Git_Serve::initRepository', + 'core.quotepath configuration error.', + $quotepath)); + return; + } + Pluf_Log::debug(array('IDF_Plugin_Git_Serve::initRepository', + 'core.quotepath configured.', $quotepath)); + } + + /** + * Set the git export value. + * + * @param string Relative path of the repository (not .git) + * @param string Full path of the repository with .git + */ + public function setGitExport($relpath, $fullpath) + { + $sql = new Pluf_SQL('shortname=%s', array($relpath)); + $projects = Pluf::factory('IDF_Project')->getList(array('filter'=>$sql->gen())); + if ($projects->count() != 1 and file_exists($fullpath)) { + return $this->gitExportDeny($fullpath); + } + $project = $projects[0]; + $conf = new IDF_Conf(); + $conf->setProject($project); + $scm = $conf->getVal('scm', 'git'); + if ($scm == 'git' and !file_exists($fullpath)) { + // No repository yet, just skip + return false; + } + if ($scm != 'git' or $project->private) { + return $this->gitExportDeny($fullpath); + } + if ('all' == $conf->getVal('source_access_rights', 'all')) { + return $this->gitExportAllow($fullpath); + } + return $this->gitExportDeny($fullpath); + } + + /** + * Remove the export flag. + * + * @param string Full path to the repository + */ + public function gitExportDeny($fullpath) + { + if (!file_exists($fullpath)) { + return; // Not created yet. + } + @unlink($fullpath.DIRECTORY_SEPARATOR.'git-daemon-export-ok'); + if (file_exists($fullpath.DIRECTORY_SEPARATOR.'git-daemon-export-ok')) { + throw new Exception('Cannot remove git-daemon-export-ok file.'); + } + return true; + } + + /** + * Set the export flag. + * + * @param string Full path to the repository + */ + public function gitExportAllow($fullpath) + { + if (!file_exists($fullpath)) { + return; // Not created yet. + } + touch($fullpath.DIRECTORY_SEPARATOR.'git-daemon-export-ok'); + if (!file_exists($fullpath.DIRECTORY_SEPARATOR.'git-daemon-export-ok')) { + throw new Exception('Cannot create git-daemon-export-ok file.'); + } + return true; + } +} diff --git a/indefero/src/IDF/Plugin/SyncMercurial.php b/indefero/src/IDF/Plugin/SyncMercurial.php new file mode 100644 index 0000000..98998b3 --- /dev/null +++ b/indefero/src/IDF/Plugin/SyncMercurial.php @@ -0,0 +1,264 @@ +processMercurialCreate($params['project']); + break; + case 'IDF_Project::membershipsUpdated': + $plug->processSyncAuthz($params['project']); + break; + case 'Pluf_User::passwordUpdated': + $plug->processSyncPasswd($params['user']); + break; + case 'hgchangegroup.php::run': + $plug->processSyncTimeline($params); + break; + } + } + + /** + * Run hg init command to create the corresponding Mercurial + * repository. + * + * @param IDF_Project + * @return bool Success + */ + function processMercurialCreate($project) + { + if ($project->getConf()->getVal('scm') != 'mercurial') { + return false; + } + $shortname = $project->shortname; + if (false===($mercurial_path=Pluf::f('idf_plugin_syncmercurial_path',false))) { + throw new Pluf_Exception_SettingError("'idf_plugin_syncmercurial_path' must be defined in your configuration file."); + } + + if (file_exists($mercurial_path.'/'.$shortname)) { + throw new Exception(sprintf(__('The repository %s already exists.'), + $mercurial_path.'/'.$shortname)); + } + $return = 0; + $output = array(); + $cmd = sprintf(Pluf::f('hg_path', 'hg').' init %s', + escapeshellarg($mercurial_path.'/'.$shortname)); + $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; + $ll = exec($cmd, $output, $return); + return ($return == 0); + } + + /** + * Synchronise an user's password. + * + * @param Pluf_User + */ + function processSyncPasswd($user) + { + $passwd_file = Pluf::f('idf_plugin_syncmercurial_passwd_file'); + if (!file_exists($passwd_file) or !is_writable($passwd_file)) { + return false; + } + $ht = new File_Passwd_Authbasic($passwd_file); + $ht->load(); + //$ht->setMode(Pluf::f('idf_plugin_syncmercurial_passwd_mode', + // FILE_PASSWD_SHA)); + $ht->setMode("plain"); + if ($ht->userExists($user->login)) { + $ht->changePasswd($user->login, "{SHA}" . $this->getMercurialPass($user)); + } else { + $ht->addUser($user->login, "{SHA}" . $this->getMercurialPass($user)); + } + $ht->save(); + return true; + } + + /** + * Synchronize the hgrc file and the passwd file for the project. + * + * @param IDF_Project + */ + function processSyncAuthz($project) + { + if ($project->getConf()->getVal('scm') != 'mercurial') { + return false; + } + $this->SyncAccess($project); + $this->generateProjectPasswd($project); + } + + /** + * Get the repository password for the user + */ + function getMercurialPass($user){ + //echo $user->password.Pluf::f('secret_key'); + # return base64_encode(sha1($_POST["password"], true)); + #file_put_contents("/tmp/test3", "test"); + //return sha1($_POST["password"], true); + //if (isset($_POST["password"])) return $_POST["password"]; + //return $_POST["password"]; + //file_put_contents("/tmp/test", $user->password.Pluf::f('secret_key')); + //file_put_contents("/tmp/test", $user->password); + //return substr(sha1($user->password.Pluf::f('secret_key')), 0, 8); + return $user->password; + } + + /** + * For a particular project: update all passwd information + */ + function generateProjectPasswd($project) + { + $passwd_file = Pluf::f('idf_plugin_syncmercurial_passwd_file'); + if (!file_exists($passwd_file) or !is_writable($passwd_file)) { + throw new Exception (sprintf(__('%s does not exist or is not writable.'), $passwd_file)); + } + $ht = new File_Passwd_Authbasic($passwd_file); + //$ht->setMode(Pluf::f('idf_plugin_syncmercurial_passwd_mode', + // FILE_PASSWD_SHA)); + $ht->setMode("plain"); + $ht->load(); + $mem = $project->getMembershipData(); + $members = array_merge((array)$mem['members'], (array)$mem['owners'], + (array)$mem['authorized']); + foreach($members as $user) { + //file_put_contents("/tmp/test", $this->getMercurialPass($user)); + if ($ht->userExists($user->login)) { + $ht->changePasswd($user->login, "{SHA}" . $this->getMercurialPass($user)); + } else { + $ht->addUser($user->login, "{SHA}" . $this->getMercurialPass($user)); + } + } + $ht->save(); + } + + /** + * Generate the hgrc file + */ + function SyncAccess($project) + { + $shortname = $project->shortname; + $hgrc_file = Pluf::f('idf_plugin_syncmercurial_path').sprintf('/%s/.hg/hgrc', $shortname); + + // Get allow_push list + $allow_push = ''; + $mem = $project->getMembershipData(); + foreach ($mem['owners'] as $v) { + $allow_push .= $v->login.' '; + } + foreach ($mem['members'] as $v) { + $allow_push .= $v->login.' '; + } + + // Generate hgrc content + if (is_file($hgrc_file)) { + $tmp_content = @parse_ini_file($hgrc_file, true, INI_SCANNER_RAW); + if ($tmp_content === false) { + throw new Exception('could not parse "'.$hgrc_file.'" because of syntax problems'); + } + $tmp_content['web']['allow_push'] = $allow_push; + } + else { + $tmp_content = Pluf::f('idf_plugin_syncmercurial_hgrc'); + $tmp_content['web']['allow_push'] = $allow_push; + } + $fcontent = ''; + foreach ($tmp_content as $key => $elem){ + $fcontent .= '['.$key."]\n"; + foreach ($elem as $key2 => $elem2){ + $fcontent .= $key2.' = '.$elem2."\n"; + } + } + file_put_contents($hgrc_file, $fcontent, LOCK_EX); + + // Generate private repository config file + $private_file = Pluf::f('idf_plugin_syncmercurial_private_include'); + $notify_file = Pluf::f('idf_plugin_syncmercurial_private_notify'); + $fcontent = ''; + foreach (Pluf::factory('IDF_Project')->getList() as $project) { + $conf = new IDF_Conf(); + $conf->setProject($project); + if ($project->private == true){ + $mem = $project->getMembershipData(); + $user = ''; + foreach ($mem['owners'] as $v) { + $user .= $v->login.' '; + } + foreach ($mem['members'] as $v) { + $user .= $v->login.' '; + } + foreach ($mem['authorized'] as $v) { + $user .= $v->login.' '; + } + $fcontent .= 'shortname).'>'."\n"; + $fcontent .= 'AuthType Basic'."\n"; + $fcontent .= 'AuthName "Restricted"'."\n"; + $fcontent .= sprintf('AuthUserFile %s', Pluf::f('idf_plugin_syncmercurial_passwd_file'))."\n"; + $fcontent .= sprintf('Require user %s', $user)."\n"; + $fcontent .= ''."\n\n"; + } + } + file_put_contents($private_file, $fcontent, LOCK_EX); + file_put_contents($notify_file, ' ', LOCK_EX); + return true; + } + + /** + * Update the timeline in post commit. + * + */ + public function processSyncTimeline($params) + { + $pname = basename($params['rel_dir']); + try { + $project = IDF_Project::getOr404($pname); + } catch (Pluf_HTTP_Error404 $e) { + Pluf_Log::event(array('IDF_Plugin_SyncMercurial::processSyncTimeline', 'Project not found.', array($pname, $params))); + return false; // Project not found + } + // Now we have the project and can update the timeline + Pluf_Log::debug(array('IDF_Plugin_SyncMercurial::processSyncTimeline', 'Project found', $pname, $project->id)); + IDF_Scm::syncTimeline($project, true); + Pluf_Log::event(array('IDF_Plugin_SyncMercurial::processSyncTimeline', 'sync', array($pname, $project->id))); + + + } +} diff --git a/indefero/src/IDF/Plugin/SyncMonotone.php b/indefero/src/IDF/Plugin/SyncMonotone.php new file mode 100644 index 0000000..d8e273b --- /dev/null +++ b/indefero/src/IDF/Plugin/SyncMonotone.php @@ -0,0 +1,911 @@ +old_err_rep = error_reporting(0); + } + + public function __destruct() + { + error_reporting($this->old_err_rep); + } + + /** + * Entry point of the plugin. + */ + static public function entry($signal, &$params) + { + $plug = new IDF_Plugin_SyncMonotone(); + switch ($signal) { + case 'IDF_Project::created': + $plug->processProjectCreate($params['project']); + break; + case 'IDF_Project::membershipsUpdated': + $plug->processMembershipsUpdated($params['project']); + break; + case 'IDF_Project::preDelete': + $plug->processProjectDelete($params['project']); + break; + case 'IDF_Key::postSave': + $plug->processKeyCreate($params['key']); + break; + case 'IDF_Key::preDelete': + $plug->processKeyDelete($params['key']); + break; + case 'mtnpostpush.php::run': + $plug->processSyncTimeline($params['project']); + break; + } + } + + /** + * Initial steps to setup a new monotone project: + * + * 1) run mtn db init to initialize a new database underknees + * 'mtn_repositories' + * 2) create a new server key in the same directory + * 3) create a new client key for IDF and store it in the project conf + * 4) setup the configuration + * 5) add the database as new local server in the usher configuration + * 6) reload the running usher instance so it acknowledges the new server + * + * The initial right setup happens in processMembershipsUpdated() + * + * @param IDF_Project + */ + function processProjectCreate($project) + { + if ($project->getConf()->getVal('scm') != 'mtn') { + return; + } + + if (Pluf::f('mtn_db_access', 'local') == 'local') { + return; + } + + // This guard cleans up on any kind of error, and here is how it works: + // As long as the guard is not committed, it keeps a reference to + // the given project. When the guard is destroyed and the reference + // is still present, it deletes the object. The deletion indirectly + // also calls into this plugin again, as the project delete hook + // will be called, that removes any changes we've made during the + // process. + $projectGuard = new IDF_Plugin_SyncMonotone_ModelGuard($project); + + $projecttempl = Pluf::f('mtn_repositories', false); + if ($projecttempl === false) { + $this->_diagnoseProblem( + __('"mtn_repositories" must be defined in your configuration file') + ); + } + + $usher_config = Pluf::f('mtn_usher_conf', false); + if (!$usher_config || !is_writable($usher_config)) { + $this->_diagnoseProblem( + __('"mtn_usher_conf" does not exist or is not writable') + ); + } + + $mtnpostpush = realpath(dirname(__FILE__) . '/../../../scripts/mtn-post-push'); + if (!file_exists($mtnpostpush)) { + $this->_diagnoseProblem(sprintf( + __('Could not find mtn-post-push script "%s"'), $mtnpostpush + )); + } + + // check some static configuration files + $confdir = Pluf::f('mtn_confdir', false); + if ($confdir === false) { + $confdir = dirname(__FILE__).'/SyncMonotone/'; + } + $confdir_contents = array( + 'monotonerc.in', + 'remote-automate-permissions.in', + 'hooks.d/', + 'hooks.d/indefero_authorize_remote_automate.lua', + 'hooks.d/indefero_post_push.conf.in', + 'hooks.d/indefero_post_push.lua', + ); + // enable remote command execution of read-only commands + // only for public projects + if (!$project->private) { + // this is linked and not copied to be able to update + // the list of read-only commands on upgrades + $confdir_contents[] = 'hooks.d/indefero_authorize_remote_automate.conf'; + } + + // check whether we should handle additional files in the config directory + $confdir_extra_contents = Pluf::f('mtn_confdir_extra', false); + if ($confdir_extra_contents !== false) { + $confdir_contents = + array_merge($confdir_contents, $confdir_extra_contents); + } + foreach ($confdir_contents as $content) { + if (!file_exists($confdir.$content)) { + $this->_diagnoseProblem(sprintf( + __('The configuration file "%s" is missing'), $content + )); + } + } + + $shortname = $project->shortname; + $projectpath = sprintf($projecttempl, $shortname); + if (file_exists($projectpath)) { + $this->_diagnoseProblem(sprintf( + __('The project path "%s" already exists'), $projectpath + )); + } + + if (!@mkdir($projectpath)) { + $this->_diagnoseProblem(sprintf( + __('The project path "%s" could not be created'), + $projectpath + )); + } + + // + // step 1) create a new database + // + $dbfile = $projectpath.'/database.mtn'; + $cmd = sprintf('db init -d %s', escapeshellarg($dbfile)); + $this->_mtn_exec($cmd); + + // + // step 2) create a server key + // + // try to parse the key's domain part from the remote_url's host + // name, otherwise fall back to the configured Apache server name + $server = $_SERVER['SERVER_NAME']; + $remote_url = Pluf::f('mtn_remote_url'); + if (($parsed = parse_url($remote_url)) !== false && + !empty($parsed['host'])) { + $server = $parsed['host']; + } + + $serverkey = $shortname.'-server@'.$server; + $cmd = sprintf('au generate_key --confdir=%s %s ""', + escapeshellarg($projectpath), + escapeshellarg($serverkey) + ); + $this->_mtn_exec($cmd); + + // + // step 3) create a client key, and save it in IDF + // + $keydir = Pluf::f('tmp_folder').'/mtn-client-keys'; + if (!file_exists($keydir)) { + if (!@mkdir($keydir)) { + $this->_diagnoseProblem(sprintf( + __('The key directory "%s" could not be created'), + $keydir + )); + } + } + + $clientkey_name = $shortname.'-client@'.$server; + $cmd = sprintf('au generate_key --keydir=%s %s ""', + escapeshellarg($keydir), + escapeshellarg($clientkey_name) + ); + $keyinfo = $this->_mtn_exec($cmd); + + $parsed_keyinfo = array(); + try { + $parsed_keyinfo = IDF_Scm_Monotone_BasicIO::parse($keyinfo); + } + catch (Exception $e) { + $this->_diagnoseProblem(sprintf( + __('Could not parse key information: %s'), $e->getMessage() + )); + } + + $clientkey_hash = $parsed_keyinfo[0][1]['hash']; + $clientkey_file = $keydir . '/' . $clientkey_name . '.' . $clientkey_hash; + $clientkey_data = file_get_contents($clientkey_file); + + $project->getConf()->setVal('mtn_client_key_name', $clientkey_name); + $project->getConf()->setVal('mtn_client_key_hash', $clientkey_hash); + $project->getConf()->setVal('mtn_client_key_data', $clientkey_data); + + // add the public client key to the server + $cmd = sprintf('au get_public_key --keydir=%s %s', + escapeshellarg($keydir), + escapeshellarg($clientkey_hash) + ); + $clientkey_pubdata = $this->_mtn_exec($cmd); + + $cmd = sprintf('au put_public_key --db=%s %s', + escapeshellarg($dbfile), + escapeshellarg($clientkey_pubdata) + ); + $this->_mtn_exec($cmd); + + // + // step 4) setup the configuration + // + + // we assume that all confdir entries ending with a slash mean a + // directory that has to be created, that all files ending on ".in" + // have to be processed and copied in place and that all other files + // just need to be symlinked from the original location + foreach ($confdir_contents as $content) { + $filepath = $projectpath.'/'.$content; + if (substr($content, -1) == '/') { + if (!@mkdir($filepath)) { + $this->_diagnoseProblem(sprintf( + __('Could not create configuration directory "%s"'), + $filepath + )); + } + continue; + } + + if (substr($content, -3) != '.in') { + if (!@symlink($confdir.$content, $filepath)) { + $this->_diagnoseProblem(sprintf( + __('Could not create symlink for configuration file "%s"'), + $filepath + )); + } + continue; + } + + $filecontents = file_get_contents($confdir.'/'.$content); + $filecontents = str_replace( + array('%%MTNPOSTPUSH%%', '%%PROJECT%%', '%%MTNCLIENTKEY%%'), + array($mtnpostpush, $shortname, $clientkey_hash), + $filecontents + ); + + // remove the .in + $filepath = substr($filepath, 0, -3); + if (@file_put_contents($filepath, $filecontents, LOCK_EX) === false) { + $this->_diagnoseProblem(sprintf( + __('Could not write configuration file "%s"'), + $filepath + )); + } + } + + // + // step 5) read in and append the usher config with the new server + // + $usher_rc = file_get_contents($usher_config); + $parsed_config = array(); + try { + $parsed_config = IDF_Scm_Monotone_BasicIO::parse($usher_rc); + } + catch (Exception $e) { + $this->_diagnoseProblem(sprintf( + __('Could not parse usher configuration in "%1$s": %2$s'), + $usher_config, $e->getMessage() + )); + } + + // ensure we haven't configured a server with this name already + foreach ($parsed_config as $stanzas) { + foreach ($stanzas as $stanza_line) { + if ($stanza_line['key'] == 'server' && + $stanza_line['values'][0] == $shortname) { + $this->_diagnoseProblem(sprintf( + __('usher configuration already contains a server '. + 'entry named "%s"'), + $shortname + )); + } + } + } + + $new_server = array( + array('key' => 'server', 'values' => array($shortname)), + array('key' => 'local', 'values' => array( + '--confdir', $projectpath, + '-d', $dbfile, + '--timestamps', + '--ticker=dot' + )), + ); + + $parsed_config[] = $new_server; + $usher_rc = IDF_Scm_Monotone_BasicIO::compile($parsed_config); + + // FIXME: more sanity - what happens on failing writes? we do not + // have a backup copy of usher.conf around... + if (@file_put_contents($usher_config, $usher_rc, LOCK_EX) === false) { + $this->_diagnoseProblem(sprintf( + __('Could not write usher configuration file "%s"'), + $usher_config + )); + } + + // + // step 6) reload usher to pick up the new configuration + // + IDF_Scm_Monotone_Usher::reload(); + + // commit the guard, so the newly created project is not deleted + $projectGuard->commit(); + } + + /** + * Updates the read / write permissions for the monotone database + * + * @param IDF_Project + */ + public function processMembershipsUpdated($project) + { + if ($project->getConf()->getVal('scm') != 'mtn') { + return; + } + + if (Pluf::f('mtn_db_access', 'local') == 'local') { + return; + } + + $mtn = IDF_Scm_Monotone::factory($project); + $stdio = $mtn->getStdio(); + + $projectpath = $this->_get_project_path($project); + $auth_ids = $this->_get_authorized_user_ids($project); + $key_ids = array(); + foreach ($auth_ids as $auth_id) { + $sql = new Pluf_SQL('user=%s', array($auth_id)); + $keys = Pluf::factory('IDF_Key')->getList(array('filter' => $sql->gen())); + foreach ($keys as $key) { + if ($key->getType() != 'mtn') + continue; + $stdio->exec(array('put_public_key', $key->content)); + $key_ids[] = $key->getMtnId(); + } + } + + $write_permissions = implode("\n", $key_ids); + $rcfile = $projectpath.'/write-permissions'; + if (@file_put_contents($rcfile, $write_permissions, LOCK_EX) === false) { + $this->_diagnoseProblem(sprintf( + __('Could not write write-permissions file "%s"'), + $rcfile + )); + } + + if ($project->private) { + $stanza = array( + array('key' => 'pattern', 'values' => array('*')), + ); + foreach ($key_ids as $key_id) + { + $stanza[] = array('key' => 'allow', 'values' => array($key_id)); + } + } + else { + $stanza = array( + array('key' => 'pattern', 'values' => array('*')), + array('key' => 'allow', 'values' => array('*')), + ); + } + + $read_permissions = IDF_Scm_Monotone_BasicIO::compile(array($stanza)); + $rcfile = $projectpath.'/read-permissions'; + if (@file_put_contents($rcfile, $read_permissions, LOCK_EX) === false) { + $this->_diagnoseProblem(sprintf( + __('Could not write read-permissions file "%s"'), + $rcfile + )); + } + + // link / unlink the read-only automate permissions for the project + $confdir = Pluf::f('mtn_confdir', false); + if ($confdir === false) { + $confdir = dirname(__FILE__).'/SyncMonotone/'; + } + $file = 'hooks.d/indefero_authorize_remote_automate.conf'; + $projectfile = $projectpath.'/'.$file; + $templatefile = $confdir.'/'.$file; + + $serverRestartRequired = false; + if ($project->private && file_exists($projectfile) && is_link($projectfile)) { + if (!@unlink($projectfile)) { + $this->_diagnoseProblem(sprintf( + __('Could not remove symlink "%s"'), $projectfile + )); + } + $serverRestartRequired = true; + } else + if (!$project->private && !file_exists($projectfile)) { + if (!@symlink($templatefile, $projectfile)) { + $this->_diagnoseProblem(sprintf( + __('Could not create symlink "%s"'), $projectfile + )); + } + $serverRestartRequired = true; + } + + if ($serverRestartRequired) { + // FIXME: we should actually use stopServer() here, but this + // seems to be ignored when the server should be started + // again immediately afterwards + IDF_Scm_Monotone_Usher::killServer($project->shortname); + // give usher some time to cool down, otherwise it might hang + // (see https://code.monotone.ca/p/contrib/issues/175/) + sleep(2); + IDF_Scm_Monotone_Usher::startServer($project->shortname); + } + } + + /** + * Clean up after a mtn project was deleted + * + * @param IDF_Project + */ + public function processProjectDelete($project) + { + if ($project->getConf()->getVal('scm') != 'mtn') { + return; + } + + if (Pluf::f('mtn_db_access', 'local') == 'local') { + return; + } + + $usher_config = Pluf::f('mtn_usher_conf', false); + if (!$usher_config || !is_writable($usher_config)) { + $this->_diagnoseProblem( + __('"mtn_usher_conf" does not exist or is not writable') + ); + } + + $shortname = $project->shortname; + IDF_Scm_Monotone_Usher::killServer($shortname); + + $projecttempl = Pluf::f('mtn_repositories', false); + if ($projecttempl === false) { + $this->_diagnoseProblem( + __('"mtn_repositories" must be defined in your configuration file') + ); + } + + $projectpath = sprintf($projecttempl, $shortname); + if (file_exists($projectpath)) { + if (!$this->_delete_recursive($projectpath)) { + $this->_diagnoseProblem(sprintf( + __('One or more paths underneath %s could not be deleted'), $projectpath + )); + } + } + + $keydir = Pluf::f('tmp_folder').'/mtn-client-keys'; + $keyname = $project->getConf()->getVal('mtn_client_key_name', false); + $keyhash = $project->getConf()->getVal('mtn_client_key_hash', false); + if ($keyname && $keyhash && + file_exists($keydir .'/'. $keyname . '.' . $keyhash)) { + if (!@unlink($keydir .'/'. $keyname . '.' . $keyhash)) { + $this->_diagnoseProblem(sprintf( + __('Could not delete client private key "%s"'), + $keyname + )); + } + } + + $usher_rc = file_get_contents($usher_config); + $parsed_config = array(); + try { + $parsed_config = IDF_Scm_Monotone_BasicIO::parse($usher_rc); + } + catch (Exception $e) { + $this->_diagnoseProblem(sprintf( + __('Could not parse usher configuration in "%1$s": %2$s'), + $usher_config, $e->getMessage() + )); + } + + foreach ($parsed_config as $idx => $stanzas) { + foreach ($stanzas as $stanza_line) { + if ($stanza_line['key'] == 'server' && + $stanza_line['values'][0] == $shortname) { + unset($parsed_config[$idx]); + break; + } + } + } + + $usher_rc = IDF_Scm_Monotone_BasicIO::compile($parsed_config); + + // FIXME: more sanity - what happens on failing writes? we do not + // have a backup copy of usher.conf around... + if (@file_put_contents($usher_config, $usher_rc, LOCK_EX) === false) { + $this->_diagnoseProblem(sprintf( + __('Could not write usher configuration file "%s"'), + $usher_config + )); + } + + IDF_Scm_Monotone_Usher::reload(); + } + + /** + * Adds the (monotone) key to all monotone projects of this forge + * where the user of the key has write access to + */ + public function processKeyCreate($key) + { + if ($key->getType() != 'mtn') { + return; + } + + if (Pluf::f('mtn_db_access', 'local') == 'local') { + return; + } + + $keyGuard = new IDF_Plugin_SyncMonotone_ModelGuard($key); + + foreach (Pluf::factory('IDF_Project')->getList() as $project) { + $conf = new IDF_Conf(); + $conf->setProject($project); + $scm = $conf->getVal('scm', 'mtn'); + if ($scm != 'mtn') + continue; + + $projectpath = $this->_get_project_path($project); + $auth_ids = $this->_get_authorized_user_ids($project); + if (!in_array($key->user, $auth_ids)) + continue; + + $mtn_key_id = $key->getMtnId(); + + // if the project is not defined as private, all people have + // read access already, so we don't need to write anything + // and we currently do not check if read-permissions really + // contains + // pattern "*" + // allow "*" + // which is the default for non-private projects + if ($project->private == true) { + $read_perms = file_get_contents($projectpath.'/read-permissions'); + $parsed_read_perms = array(); + try { + $parsed_read_perms = IDF_Scm_Monotone_BasicIO::parse($read_perms); + } + catch (Exception $e) { + $this->_diagnoseProblem(sprintf( + __('Could not parse read-permissions for project "%1$s": %2$s'), + $shortname, $e->getMessage() + )); + } + + $wildcard_section = null; + for ($i=0; $i 'pattern', 'values' => array('*')) + ); + $parsed_read_perms[] =& $wildcard_section; + } + + $key_found = false; + foreach ($wildcard_section as $line) + { + if ($line['key'] == 'allow' && $line['values'][0] == $mtn_key_id) { + $key_found = true; + break; + } + } + + if (!$key_found) { + $wildcard_section[] = array( + 'key' => 'allow', 'values' => array($mtn_key_id) + ); + } + + $read_perms = IDF_Scm_Monotone_BasicIO::compile($parsed_read_perms); + + if (@file_put_contents($projectpath.'/read-permissions', + $read_perms, LOCK_EX) === false) { + $this->_diagnoseProblem(sprintf( + __('Could not write read-permissions for project "%s"'), + $shortname + )); + } + } + + $write_perms = file_get_contents($projectpath.'/write-permissions'); + $lines = preg_split("/(\n|\r\n)/", $write_perms, -1, PREG_SPLIT_NO_EMPTY); + if (!in_array('*', $lines) && !in_array($mtn_key_id, $lines)) { + $lines[] = $mtn_key_id; + } + if (@file_put_contents($projectpath.'/write-permissions', + implode("\n", $lines) . "\n", LOCK_EX) === false) { + $this->_diagnoseProblem(sprintf( + __('Could not write write-permissions file for project "%s"'), + $shortname + )); + } + + $mtn = IDF_Scm_Monotone::factory($project); + $stdio = $mtn->getStdio(); + $stdio->exec(array('put_public_key', $key->content)); + } + + $keyGuard->commit(); + } + + /** + * Removes the (monotone) key from all monotone projects of this forge + * where the user of the key has write access to + */ + public function processKeyDelete($key) + { + try { + if ($key->getType() != 'mtn') { + return; + } + } catch (Exception $e) { + // bad key type, skip it. + return; + } + + if (Pluf::f('mtn_db_access', 'local') == 'local') { + return; + } + + foreach (Pluf::factory('IDF_Project')->getList() as $project) { + $conf = new IDF_Conf(); + $conf->setProject($project); + $scm = $conf->getVal('scm', 'mtn'); + if ($scm != 'mtn') + continue; + + $projectpath = $this->_get_project_path($project); + $auth_ids = $this->_get_authorized_user_ids($project); + if (!in_array($key->user, $auth_ids)) + continue; + + $mtn_key_id = $key->getMtnId(); + + // if the project is not defined as private, all people have + // read access already, so we don't need to write anything + // and we currently do not check if read-permissions really + // contains + // pattern "*" + // allow "*" + // which is the default for non-private projects + if ($project->private) { + $read_perms = file_get_contents($projectpath.'/read-permissions'); + $parsed_read_perms = array(); + try { + $parsed_read_perms = IDF_Scm_Monotone_BasicIO::parse($read_perms); + } + catch (Exception $e) { + $this->_diagnoseProblem(sprintf( + __('Could not parse read-permissions for project "%1$s": %2$s'), + $shortname, $e->getMessage() + )); + } + + // while we add new keys only to an existing wild-card entry + // we remove dropped keys from all sections since the key + // should be simply unavailable for all of them + for ($h=0; $h_diagnoseProblem(sprintf( + __('Could not write read-permissions for project "%s"'), + $shortname + )); + } + } + + $write_perms = file_get_contents($projectpath.'/write-permissions'); + $lines = preg_split("/(\n|\r\n)/", $write_perms, -1, PREG_SPLIT_NO_EMPTY); + for ($i=0; $i_diagnoseProblem(sprintf( + __('Could not write write-permissions file for project "%s"'), + $shortname + )); + } + + $mtn = IDF_Scm_Monotone::factory($project); + $stdio = $mtn->getStdio(); + // if the public key did not sign any revisions, drop it from + // the database as well + try { + if (strlen($stdio->exec(array('select', 'k:' . $mtn_key_id))) == 0) { + $stdio->exec(array('drop_public_key', $mtn_key_id)); + } + } catch (IDF_Scm_Exception $e) { + if (strpos($e->getMessage(), 'there is no key named') === false) + throw $e; + } + } + } + + /** + * Update the timeline after a push + * + */ + public function processSyncTimeline($project_name) + { + try { + $project = IDF_Project::getOr404($project_name); + } catch (Pluf_HTTP_Error404 $e) { + Pluf_Log::event(array( + 'IDF_Plugin_SyncMonotone::processSyncTimeline', + 'Project not found.', + array($project_name, $params) + )); + return false; // Project not found + } + + Pluf_Log::debug(array( + 'IDF_Plugin_SyncMonotone::processSyncTimeline', + 'Project found', $project_name, $project->id + )); + IDF_Scm::syncTimeline($project, true); + Pluf_Log::event(array( + 'IDF_Plugin_SyncMonotone::processSyncTimeline', + 'sync', array($project_name, $project->id) + )); + } + + private function _get_project_path($project) + { + $projecttempl = Pluf::f('mtn_repositories', false); + if ($projecttempl === false) { + $this->_diagnoseProblem( + __('"mtn_repositories" must be defined in your configuration file.') + ); + } + + $projectpath = sprintf($projecttempl, $project->shortname); + if (!file_exists($projectpath)) { + $this->_diagnoseProblem(sprintf( + __('The project path %s does not exists.'), $projectpath + )); + } + return $projectpath; + } + + private function _mtn_exec($cmd) + { + $fullcmd = sprintf('%s %s %s', + Pluf::f('idf_exec_cmd_prefix', ''), + Pluf::f('mtn_path', 'mtn'), + $cmd + ); + + $output = $return = null; + exec($fullcmd, $output, $return); + if ($return != 0) { + $this->_diagnoseProblem(sprintf( + __('The command "%s" could not be executed.'), $cmd + )); + } + return implode("\n", $output); + } + + private function _get_authorized_user_ids($project) + { + $mem = $project->getMembershipData(); + $members = array_merge((array)$mem['members'], + (array)$mem['owners'], + (array)$mem['authorized']); + $userids = array(); + foreach ($members as $member) { + $userids[] = $member->id; + } + return $userids; + } + + private function _delete_recursive($path) + { + if (is_file($path) || is_link($path)) { + return @unlink($path); + } + + if (is_dir($path)) { + $scan = glob(rtrim($path, '/') . '/*'); + $status = 0; + foreach ($scan as $subpath) { + $status |= $this->_delete_recursive($subpath); + } + $status |= @rmdir($path); + return $status; + } + } + + private function _diagnoseProblem($msg) + { + $system_err = error_get_last(); + if (!empty($system_err)) { + $msg .= ': '.$system_err['message']; + } + + error_reporting($this->old_err_rep); + throw new IDF_Scm_Exception($msg); + } +} + +/** + * A simple helper class that deletes the model instance if + * it is not committed + */ +class IDF_Plugin_SyncMonotone_ModelGuard +{ + private $model; + + public function __construct(Pluf_Model $m) + { + $this->model = $m; + } + + public function __destruct() + { + if ($this->model == null) + return; + $this->model->delete(); + } + + public function commit() + { + $this->model = null; + } +} + diff --git a/indefero/src/IDF/Plugin/SyncMonotone/hooks.d/indefero_authorize_remote_automate.conf b/indefero/src/IDF/Plugin/SyncMonotone/hooks.d/indefero_authorize_remote_automate.conf new file mode 100644 index 0000000..c38789f --- /dev/null +++ b/indefero/src/IDF/Plugin/SyncMonotone/hooks.d/indefero_authorize_remote_automate.conf @@ -0,0 +1,10 @@ +ARA_safe_commands = { + "get_corresponding_path", "get_content_changed", "tags", "branches", + "common_ancestors", "packet_for_fdelta", "packet_for_fdata", + "packets_for_certs", "packet_for_rdata", "get_manifest_of", + "get_revision", "select", "graph", "children", "parents", "roots", + "leaves", "ancestry_difference", "toposort", "erase_ancestors", + "descendents", "ancestors", "heads", "get_file_of", "get_file", + "interface_version", "get_attributes", "content_diff", + "file_merge", "show_conflicts", "certs", "keys", "get_extended_manifest_of" +} diff --git a/indefero/src/IDF/Plugin/SyncMonotone/hooks.d/indefero_authorize_remote_automate.lua b/indefero/src/IDF/Plugin/SyncMonotone/hooks.d/indefero_authorize_remote_automate.lua new file mode 100644 index 0000000..a1f43a3 --- /dev/null +++ b/indefero/src/IDF/Plugin/SyncMonotone/hooks.d/indefero_authorize_remote_automate.lua @@ -0,0 +1,88 @@ +-- ***** BEGIN LICENSE BLOCK ***** +-- This file is part of InDefero, an open source project management application. +-- Copyright (C) 2008-2011 Céondo Ltd and contributors. +-- Copyright (C) 2010 Thomas Keller +-- Richard Levitte +-- +-- InDefero is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 2 of the License, or +-- (at your option) any later version. +-- +-- InDefero is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +-- +-- ***** END LICENSE BLOCK ***** + +-- +-- This script reads key identities from a file "remote-automate-permissions" +-- in the configuration directory and permits those authenticating with one +-- of those keys to perform dangerous (read/write) remote automate operations. +-- The format of the file is very simple, one key identity on every line. +-- Lines starting with # are ignore, as well as empty lines. +-- +-- It's possible to configure this script to allow the performance of some +-- remote automate commands anonymously, through the variable +-- ARA_safe_commands, which has to be a table of commands as strings. +-- One example configuration, taken from the setup at code.monotone.ca, could +-- be this: +-- +-- ARA_safe_commands = { +-- "get_corresponding_path", "get_content_changed", "tags", "branches", +-- "common_ancestors", "packet_for_fdelta", "packet_for_fdata", +-- "packets_for_certs", "packet_for_rdata", "get_manifest_of", +-- "get_revision", "select", "graph", "children", "parents", "roots", +-- "leaves", "ancestry_difference", "toposort", "erase_ancestors", +-- "descendents", "ancestors", "heads", "get_file_of", "get_file", +-- "interface_version", "get_attributes", "content_diff", +-- "file_merge", "show_conflicts", "certs", "keys", "get_extended_manifest_of" +-- } +-- +do + local _safe_commands = {} + if ARA_safe_commands then + _safe_commands = ARA_safe_commands + end + + local _save_get_remote_automate_permitted = get_remote_automate_permitted + function get_remote_automate_permitted(key_identity, command, options) + local permfile = + io.open(get_confdir() .. "/remote-automate-permissions", "r") + if (permfile == nil) then + return false + end + + -- See if the incoming key matches any of the key identities or + -- patterns found in the permissions file. + local matches = false + local line = permfile:read() + while (not matches and line ~= nil) do + if not globish_match("#*", line) then + local _, _, ln = string.find(line, "%s*([^%s]*)%s*") + if ln == "*" then matches = true end + if ln == key_identity.id then matches = true end + if globish_match(ln, key_identity.name) then matches = true end + line = permfile:read() + end + end + io.close(permfile) + if matches then return true end + + -- No matching key found, let's see if the command matches one the + -- admin allowed to be performed anonymously + for _,v in ipairs(_safe_commands) do + if (v == command[1]) then + return true + end + end + + -- No matches found anywhere, then don't permit this operation + return false + end +end diff --git a/indefero/src/IDF/Plugin/SyncMonotone/hooks.d/indefero_post_push.conf.in b/indefero/src/IDF/Plugin/SyncMonotone/hooks.d/indefero_post_push.conf.in new file mode 100644 index 0000000..efeeaad --- /dev/null +++ b/indefero/src/IDF/Plugin/SyncMonotone/hooks.d/indefero_post_push.conf.in @@ -0,0 +1,2 @@ +IDF_project = "%%PROJECT%%" +IDF_push_script = "%%MTNPOSTPUSH%%" diff --git a/indefero/src/IDF/Plugin/SyncMonotone/hooks.d/indefero_post_push.lua b/indefero/src/IDF/Plugin/SyncMonotone/hooks.d/indefero_post_push.lua new file mode 100644 index 0000000..2f58f64 --- /dev/null +++ b/indefero/src/IDF/Plugin/SyncMonotone/hooks.d/indefero_post_push.lua @@ -0,0 +1,58 @@ +-- ***** BEGIN LICENSE BLOCK ***** +-- This file is part of InDefero, an open source project management application. +-- Copyright (C) 2008-2011 Céondo Ltd and contributors. +-- +-- InDefero is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 2 of the License, or +-- (at your option) any later version. +-- +-- InDefero is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +-- +-- ***** END LICENSE BLOCK ***** + +-- +-- let IDF know of new arriving revisions to fill its timeline +-- +_idf_revs = {} +push_hook_functions( + { + start = + function (session_id) + _idf_revs[session_id] = {} + return "continue",nil + end, + revision_received = + function (new_id, revision, certs, session_id) + table.insert(_idf_revs[session_id], new_id) + return "continue",nil + end, + ["end"] = + function (session_id, ...) + if table.getn(_idf_revs[session_id]) == 0 then + return "continue",nil + end + + local pin,pout,pid = spawn_pipe(IDF_push_script, IDF_project); + if pid == -1 then + print("could not execute " .. IDF_push_script) + return "continue",nil + end + + for _,r in ipairs(_idf_revs[session_id]) do + pin:write(r .. "\n") + end + pin:close() + + wait(pid) + return "continue",nil + end + }) + diff --git a/indefero/src/IDF/Plugin/SyncMonotone/monotonerc.in b/indefero/src/IDF/Plugin/SyncMonotone/monotonerc.in new file mode 100644 index 0000000..fcf3c15 --- /dev/null +++ b/indefero/src/IDF/Plugin/SyncMonotone/monotonerc.in @@ -0,0 +1,30 @@ +-- ***** BEGIN LICENSE BLOCK ***** +-- This file is part of InDefero, an open source project management application. +-- Copyright (C) 2008-2011 Céondo Ltd and contributors. +-- +-- InDefero is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation; either version 2 of the License, or +-- (at your option) any later version. +-- +-- InDefero is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program; if not, write to the Free Software +-- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +-- +-- ***** END LICENSE BLOCK ***** + +---- Load local hooks if they exist. +-- The way this is supposed to work is that hooks.d can contain symbolic +-- links to lua scripts. These links MUST have the extension .lua +-- If the script needs some configuration, a corresponding file with +-- the extension .conf is the right spot. +---- +-- First load the configuration of the hooks, if applicable +includedirpattern(get_confdir() .. "/hooks.d/","*.conf") +-- Then load the hooks themselves +includedirpattern(get_confdir() .. "/hooks.d/","*.lua") diff --git a/indefero/src/IDF/Plugin/SyncMonotone/remote-automate-permissions.in b/indefero/src/IDF/Plugin/SyncMonotone/remote-automate-permissions.in new file mode 100644 index 0000000..164a44c --- /dev/null +++ b/indefero/src/IDF/Plugin/SyncMonotone/remote-automate-permissions.in @@ -0,0 +1 @@ +%%MTNCLIENTKEY%% diff --git a/indefero/src/IDF/Plugin/SyncSvn.php b/indefero/src/IDF/Plugin/SyncSvn.php new file mode 100644 index 0000000..1e1b2da --- /dev/null +++ b/indefero/src/IDF/Plugin/SyncSvn.php @@ -0,0 +1,294 @@ +processSvnCreate($params['project']); + break; + case 'IDF_Project::membershipsUpdated': + $plug->processSyncAuthz($params['project']); + break; + case 'Pluf_User::passwordUpdated': + $plug->processSyncPasswd($params['user']); + break; + case 'IDF_Project::preDelete': + $plug->processSvnDelete($params['project']); + break; + case 'svnpostcommit.php::run': + $plug->processSvnUpdateTimeline($params); + break; + } + } + + /** + * Run svnadmin command to create the corresponding Subversion + * repository. + * + * @param IDF_Project + * @return bool Success + */ + function processSvnCreate($project) + { + if ($project->getConf()->getVal('scm') != 'svn') { + return false; + } + $shortname = $project->shortname; + if (false===($svn_path=Pluf::f('idf_plugin_syncsvn_svn_path',false))) { + throw new Pluf_Exception_SettingError("'idf_plugin_syncsvn_svn_path' must be defined in your configuration file."); + } + if (file_exists($svn_path.'/'.$shortname)) { + throw new Exception(sprintf(__('The repository %s already exists.'), + $svn_path.'/'.$shortname)); + } + $return = 0; + $output = array(); + $cmd = sprintf(Pluf::f('svnadmin_path', 'svnadmin').' create %s', + escapeshellarg($svn_path.'/'.$shortname)); + $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; + $ll = exec($cmd, $output, $return); + if ($return != 0) { + Pluf_Log::error(array('IDF_Plugin_SyncSvn::processSvnCreate', + 'Error', + array('path' => $svn_path.'/'.$shortname, + 'output' => $output))); + return; + } + $p = realpath(dirname(__FILE__).'/../../../scripts/svn-post-commit'); + exec(sprintf(Pluf::f('idf_exec_cmd_prefix', '').'ln -s %s %s', + escapeshellarg($p), + escapeshellarg($svn_path.'/'.$shortname.'/hooks/post-commit')), + $out, $res); + if ($res != 0) { + Pluf_Log::warn(array('IDF_Plugin_SyncSvn::processSvnCreate', + 'post-commit hook creation error.', + $svn_path.'/'.$shortname.'/hooks/post-commit')); + return; + } + $p = realpath(dirname(__FILE__).'/../../../scripts/svn-post-revprop-change'); + exec(sprintf(Pluf::f('idf_exec_cmd_prefix', '').'ln -s %s %s', + escapeshellarg($p), + escapeshellarg($svn_path.'/'.$shortname.'/hooks/post-revprop-change')), + $out, $res); + if ($res != 0) { + Pluf_Log::warn(array('IDF_Plugin_SyncSvn::processSvnCreate', + 'post-revprop-change hook creation error.', + $svn_path.'/'.$shortname.'/hooks/post-revprop-change')); + return; + } + + return ($return == 0); + } + + /** + * Remove the project from the drive and update the access rights. + * + * @param IDF_Project + * @return bool Success + */ + function processSvnDelete($project) + { + if (!Pluf::f('idf_plugin_syncsvn_remove_orphans', false)) { + return; + } + if ($project->getConf()->getVal('scm') != 'svn') { + return false; + } + $this->SyncAccess($project); // exclude $project + $shortname = $project->shortname; + if (false===($svn_path=Pluf::f('idf_plugin_syncsvn_svn_path',false))) { + throw new Pluf_Exception_SettingError("'idf_plugin_syncsvn_svn_path' must be defined in your configuration file."); + } + if (file_exists($svn_path.'/'.$shortname)) { + $cmd = Pluf::f('idf_exec_cmd_prefix', '').'rm -rf '.$svn_path.'/'.$shortname; + exec($cmd); + } + } + + /** + * Synchronise an user's password. + * + * @param Pluf_User + */ + function processSyncPasswd($user) + { + $passwd_file = Pluf::f('idf_plugin_syncsvn_passwd_file'); + if (!file_exists($passwd_file) or !is_writable($passwd_file)) { + return false; + } + $ht = new File_Passwd_Authbasic($passwd_file); + $ht->load(); + $ht->setMode('plain'); + //$ht->setMode(FILE_PASSWD_SHA); + if ($ht->userExists($user->login)) { + $ht->changePasswd($user->login, '{SHA}' . $this->getSvnPass($user)); + } else { + $ht->addUser($user->login, '{SHA}' . $this->getSvnPass($user)); + } + $ht->save(); + return true; + } + + /** + * Synchronize the authz file and the passwd file for the project. + * + * @param IDF_Project + */ + function processSyncAuthz($project) + { + $this->SyncAccess(); + $this->generateProjectPasswd($project); + } + + /** + * Get the repository password for the user + */ + function getSvnPass($user){ + //if (isset($_POST["password"])) return $_POST["password"]; + //return $_POST["password"]; + //return substr(sha1($user->password.Pluf::f('secret_key')), 0, 8); + return $user->password; + } + + /** + * For a particular project: update all passwd information + */ + function generateProjectPasswd($project) + { + $passwd_file = Pluf::f('idf_plugin_syncsvn_passwd_file'); + if (!file_exists($passwd_file) or !is_writable($passwd_file)) { + return false; + } + $ht = new File_Passwd_Authbasic($passwd_file); + $ht->setMode('plain'); + $ht->load(); + $mem = $project->getMembershipData(); + $members = array_merge((array)$mem['members'], (array)$mem['owners'], + (array)$mem['authorized']); + foreach($members as $user) { + if ($ht->userExists($user->login)) { + + $ht->changePasswd($user->login, '{SHA}' . $this->getSvnPass($user)); + } else { + $ht->addUser($user->login, '{SHA}' . $this->getSvnPass($user)); + } + } + $ht->save(); + } + + /** + * Generate the dav_svn.authz file + * + * We rebuild the complete file each time. This is just to be sure + * not to bork the rights when trying to just edit part of the + * file. + * + * @param IDF_Project Possibly exclude a project (null) + */ + function SyncAccess($exclude=null) + { + $authz_file = Pluf::f('idf_plugin_syncsvn_authz_file'); + $access_owners = Pluf::f('idf_plugin_syncsvn_access_owners', 'rw'); + $access_members = Pluf::f('idf_plugin_syncsvn_access_members', 'rw'); + $access_extra = Pluf::f('idf_plugin_syncsvn_access_extra', 'r'); + $access_public = Pluf::f('idf_plugin_syncsvn_access_public', 'r'); + $access_public_priv = Pluf::f('idf_plugin_syncsvn_access_private', ''); + if (!file_exists($authz_file) or !is_writable($authz_file)) { + return false; + } + $fcontent = ''; + foreach (Pluf::factory('IDF_Project')->getList() as $project) { + if ($exclude and $exclude->id == $project->id) { + continue; + } + $conf = new IDF_Conf(); + $conf->setProject($project); + if ($conf->getVal('scm') != 'svn' or + strlen($conf->getVal('svn_remote_url')) > 0) { + continue; + } + $mem = $project->getMembershipData(); + // [shortname:/] + $fcontent .= '['.$project->shortname.':/]'."\n"; + foreach ($mem['owners'] as $v) { + $fcontent .= $v->login.' = '.$access_owners."\n"; + } + foreach ($mem['members'] as $v) { + $fcontent .= $v->login.' = '.$access_members."\n"; + } + // access for all users + if ($project->private == true) { + foreach ($mem['authorized'] as $v) { + $fcontent .= $v->login.' = '.$access_extra."\n"; + } + $fcontent .= '* = '.$access_public_priv."\n"; + } else { + $fcontent .= '* = '.$access_public."\n"; + } + $fcontent .= "\n"; + } + file_put_contents($authz_file, $fcontent, LOCK_EX); + return true; + } + + /** + * Update the timeline in post commit. + * + */ + public function processSvnUpdateTimeline($params) + { + $pname = basename($params['repo_dir']); + try { + $project = IDF_Project::getOr404($pname); + } catch (Pluf_HTTP_Error404 $e) { + Pluf_Log::event(array('IDF_Plugin_SyncSvn::processSvnUpdateTimeline', 'Project not found.', array($pname, $params))); + return false; // Project not found + } + // Now we have the project and can update the timeline + Pluf_Log::debug(array('IDF_Plugin_SyncGit::processSvnUpdateTimeline', 'Project found', $pname, $project->id)); + IDF_Scm::syncTimeline($project, true); + Pluf_Log::event(array('IDF_Plugin_SyncGit::processSvnUpdateTimeline', 'sync', array($pname, $project->id))); + + + } +} diff --git a/indefero/src/IDF/Precondition.php b/indefero/src/IDF/Precondition.php new file mode 100644 index 0000000..163f457 --- /dev/null +++ b/indefero/src/IDF/Precondition.php @@ -0,0 +1,264 @@ +project->private) { + return true; + } + if ($request->user->hasPerm('IDF.project-authorized-user', $request->project)) { + return true; + } + return self::projectMemberOrOwner($request); + } + + /** + * Check if the user is project owner. + * + * @param Pluf_HTTP_Request + * @return mixed + */ + static public function projectOwner($request) + { + $res = Pluf_Precondition::loginRequired($request); + if (true !== $res) { + return $res; + } + if ($request->user->hasPerm('IDF.project-owner', $request->project)) { + return true; + } + return new Pluf_HTTP_Response_Forbidden($request); + } + + /** + * Check if the user is project owner or member. + * + * @param Pluf_HTTP_Request + * @return mixed + */ + static public function projectMemberOrOwner($request) + { + $res = Pluf_Precondition::loginRequired($request); + if (true !== $res) { + return $res; + } + if ($request->user->hasPerm('IDF.project-owner', $request->project) + or + $request->user->hasPerm('IDF.project-member', $request->project) + ) { + return true; + } + return new Pluf_HTTP_Response_Forbidden($request); + } + + /** + * Check if the user can access a given element. + * + * The rights are: + * - 'all' (default) + * - 'none' + * - 'login' + * - 'members' + * - 'owners' + * + * The order of the rights is such that a 'owner' is also a + * 'member' and of course a logged in person. + * + * @param Pluf_HTTP_Request + * @param string Control key + * @return mixed + */ + static public function accessTabGeneric($request, $key) + { + switch ($request->conf->getVal($key, 'all')) { + case 'none': + return new Pluf_HTTP_Response_Forbidden($request); + case 'login': + return Pluf_Precondition::loginRequired($request); + case 'members': + return self::projectMemberOrOwner($request); + case 'owners': + return self::projectOwner($request); + case 'all': + default: + return true; + } + } + + static public function accessSource($request) + { + $res = self::baseAccess($request); + if (true !== $res) { + return $res; + } + return self::accessTabGeneric($request, 'source_access_rights'); + } + + static public function accessIssues($request) + { + $res = self::baseAccess($request); + if (true !== $res) { + return $res; + } + return self::accessTabGeneric($request, 'issues_access_rights'); + } + + static public function accessDownloads($request) + { + $res = self::baseAccess($request); + if (true !== $res) { + return $res; + } + return self::accessTabGeneric($request, 'downloads_access_rights'); + } + + static public function accessWiki($request) + { + $res = self::baseAccess($request); + if (true !== $res) { + return $res; + } + return self::accessTabGeneric($request, 'wiki_access_rights'); + } + + static public function accessReview($request) + { + $res = self::baseAccess($request); + if (true !== $res) { + return $res; + } + return self::accessTabGeneric($request, 'review_access_rights'); + } + + /** + * Based on the request, it is automatically setting the user. + * + * API calls are not translated. + */ + static public function apiSetUser($request) + { + // REQUEST is used to be used both for POST and GET requests. + if (!isset($request->REQUEST['_hash']) + or !isset($request->REQUEST['_login']) + or !isset($request->REQUEST['_salt'])) { + // equivalent to anonymous access. + return true; + } + $db =& Pluf::db(); + $true = Pluf_DB_BooleanToDb(true, $db); + $sql = new Pluf_SQL('login=%s AND active='.$true, + $request->REQUEST['_login']); + $users = Pluf::factory('Pluf_User')->getList(array('filter'=>$sql->gen())); + if ($users->count() != 1 or !$users[0]->active) { + // Should return a special authentication error like user + // not found. + return true; + } + $hash = sha1($request->REQUEST['_salt'].sha1($users[0]->password)); + if ($hash != $request->REQUEST['_hash']) { + return true; // Again need authentication error + } + $request->user = $users[0]; + + // Don't try to load projects rights access if we are not in one + if ($request->query !== "/api/") { + IDF_Middleware::setRights($request); + } + + return true; + } + + /** + * Based on the request, it is automatically setting the user. + * + * Authenticated feeds have a token set at the end of the url in + * the for of 'authenticated/url/token/234092384023woeiur/'. If + * you remove 'token/234092384023woeiur/' the url is not + * authenticated. + * + * If the user is already logged in and not anonymous and no token + * is given, then the user is unset and a non authenticated user + * is loaded. This is to avoid people to not understand why a + * normally not authenticated feed is providing authenticated + * data. + */ + static public function feedSetUser($request) + { + if (!isset($request->project)) { + return true; // we do not act on non project pages at the + // moment. + } + if (!$request->user->isAnonymous()) { + // by default anonymous + $request->user = new Pluf_User(); + IDF_Middleware::setRights($request); + } + $match = array(); + if (!preg_match('#/token/([^/]+)/$#', $request->query, $match)) { + return true; // anonymous + } + $token = $match[1]; + $hash = substr($token, 0, 2); + $encrypted = substr($token, 2); + if ($hash != substr(md5(Pluf::f('secret_key').$encrypted), 0, 2)) { + return true; // no match in the hash, anonymous + } + $cr = new Pluf_Crypt(md5(Pluf::f('secret_key'))); + list($userid, $projectid) = explode(':', $cr->decrypt($encrypted), 2); + if ($projectid != $request->project->id) { + return true; // anonymous + } + $user = new Pluf_User($userid); + if (!$user->active) { + return true; // anonymous + } + $request->user = $user; + IDF_Middleware::setRights($request); + return true; + } + + /** + * Generate the token for the feed. + * + * @param IDF_Project + * @param Pluf_User + * @return string Token + */ + static public function genFeedToken($project, $user) + { + $cr = new Pluf_Crypt(md5(Pluf::f('secret_key'))); + $encrypted = trim($cr->encrypt($user->id.':'.$project->id), '~'); + return substr(md5(Pluf::f('secret_key').$encrypted), 0, 2).$encrypted; + } +} diff --git a/indefero/src/IDF/Project.php b/indefero/src/IDF/Project.php new file mode 100644 index 0000000..c298047 --- /dev/null +++ b/indefero/src/IDF/Project.php @@ -0,0 +1,885 @@ +_pconf = null; + $this->_extra_cache = array(); + $this->_a['table'] = 'idf_projects'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + 'blank' => true, + ), + 'name' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 250, + 'verbose' => __('name'), + ), + 'shortname' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 50, + 'verbose' => __('short name'), + 'help_text' => __('Used in the URL to access the project, must be short with only letters and numbers.'), + 'unique' => true, + ), + 'shortdesc' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 255, + 'verbose' => __('short description'), + 'help_text' => __('A one line description of the project.'), + ), + 'description' => + array( + 'type' => 'Pluf_DB_Field_Text', + 'blank' => false, + 'size' => 250, + 'verbose' => __('description'), + 'help_text' => __('The description can be extended using the Markdown syntax.'), + ), + 'tags' => + array( + 'type' => 'Pluf_DB_Field_Manytomany', + 'blank' => true, + 'model' => 'IDF_Tag', + 'verbose' => __('labels'), + ), + 'private' => + array( + 'type' => 'Pluf_DB_Field_Integer', + 'blank' => false, + 'verbose' => __('private'), + 'default' => 0, + ), + 'current_activity' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_ProjectActivity', + 'blank' => true, + 'is_null' => true, + 'default' => null, + 'verbose' => __('current project activity'), + ), + 'enableads' => + array( + 'type' => 'Pluf_DB_Field_Integer', + 'blank' => false, + 'verbose' => __('enableads'), + 'default' => 1, + ), + ); + $activityTable = $this->_con->pfx.'idf_projectactivities'; + $tagTable = $this->_con->pfx.'idf_project_idf_tag_assoc'; + $this->_a['views'] = array( + 'join_activities_and_tags' => + array( + 'join' => 'LEFT JOIN '.$activityTable.' ON current_activity='.$activityTable.'.id ' + .'LEFT JOIN '.$tagTable.' ON idf_project_id='.$this->getSqlTable().'.id', + 'select' => 'DISTINCT '.$this->getSelect().', date, value', + 'props' => array( + 'date' => 'current_activity_date', + 'value' => 'current_activity_value' + ), + ), + ); + } + + + /** + * String representation of the abstract. + */ + function __toString() + { + return $this->name; + } + + /** + * String ready for indexation. + */ + function _toIndex() + { + return ''; + } + + + function preSave($create=false) + { + if ($this->id == '') { + $this->creation_dtime = gmdate('Y-m-d H:i:s'); + } + $this->modif_dtime = gmdate('Y-m-d H:i:s'); + } + + public static function getOr404($shortname) + { + $sql = new Pluf_SQL('shortname=%s', array(trim($shortname))); + $projects = Pluf::factory(__CLASS__)->getList(array('filter' => $sql->gen())); + if ($projects->count() != 1) { + throw new Pluf_HTTP_Error404(sprintf(__('Project "%s" not found.'), + $shortname)); + } + return $projects[0]; + } + + /** + * Returns the number of open/closed issues. + * + * @param string Status ('open'), 'closed' + * @param IDF_Tag Subfilter with a label (null) + * @return int Count + */ + public function getIssueCountByOwner($status='open') + { + switch ($status) { + case 'open': + $tags = implode(',', $this->getTagIdsByStatus('open')); + break; + case 'closed': + default: + $tags = implode(',', $this->getTagIdsByStatus('closed')); + break; + } + $sqlIssueTable = Pluf::factory('IDF_Issue')->getSqlTable(); + $query = "SELECT uid AS id,COUNT(uid) AS nb +FROM ( + SELECT COALESCE(owner, -1) AS uid + FROM $sqlIssueTable + WHERE status IN ($tags) + ) AS ff +GROUP BY uid"; + + $db = Pluf::db(); + $dbData = $db->select($query); + $ownerStatistics = array(); + foreach ($dbData as $k => $v) { + $key = ($v['id'] === '-1') ? null : $v['id']; + $ownerStatistics[$key] = (int)$v['nb']; + } + + arsort($ownerStatistics); + + return $ownerStatistics; + } + + /** + * Returns the number of open/closed issues. + * + * @param string Status ('open'), 'closed' + * @param IDF_Tag Subfilter with a label (null) + * @param array Restrict further to a list of ids + * @return int Count + */ + public function getIssueCountByStatus($status='open', $label=null, $ids=array()) + { + switch ($status) { + case 'open': + $key = 'labels_issue_open'; + $default = IDF_Form_IssueTrackingConf::init_open; + break; + case 'closed': + default: + $key = 'labels_issue_closed'; + $default = IDF_Form_IssueTrackingConf::init_closed; + break; + } + $tags = array(); + foreach ($this->getTagsFromConfig($key, $default, 'Status') as $tag) { + $tags[] = (int)$tag->id; + } + if (count($tags) == 0) return array(); + $sql = new Pluf_SQL(sprintf('project=%%s AND status IN (%s)', implode(', ', $tags)), array($this->id)); + if (!is_null($label)) { + $sql2 = new Pluf_SQL('idf_tag_id=%s', array($label->id)); + $sql->SAnd($sql2); + } + if (count($ids) > 0) { + $sql2 = new Pluf_SQL(sprintf('id IN (%s)', implode(', ', $ids))); + $sql->SAnd($sql2); + } + $params = array('filter' => $sql->gen()); + if (!is_null($label)) { $params['view'] = 'join_tags'; } + $gissue = new IDF_Issue(); + return $gissue->getCount($params); + } + + /** + * Get the tags for a specific list of issues. + * + * @param string Status ('open') or 'closed' + * @param array A list of issue ids + * @return array An array of tag objects + */ + public function getTagsByIssues($issue_ids=array()) + { + // make the below query always a valid one + if (count($issue_ids) == 0) $issue_ids[] = 0; + + $assocTable = $this->_con->pfx.'idf_issue_idf_tag_assoc'; + $query = sprintf( + 'SELECT DISTINCT idf_tag_id FROM %s '. + 'WHERE idf_issue_id IN (%s) '. + 'GROUP BY idf_tag_id', + $assocTable, implode(',', $issue_ids) + ); + + $db = Pluf::db(); + $dbData = $db->select($query); + $ids = array(0); + foreach ($dbData as $data) { + $ids[] = $data['idf_tag_id']; + } + + $sql = new Pluf_SQL(sprintf('id IN (%s)', implode(', ', $ids))); + $model = new IDF_Tag(); + return $model->getList(array('filter' => $sql->gen())); + } + + /** + * Get the open/closed tag ids as they are often used when doing + * listings. + * + * As this can be often used, the info are cached. + * + * @param string Status ('open') or 'closed' + * @param bool Force cache refresh (false) + * @return array Ids of the open/closed tags + */ + public function getTagIdsByStatus($status='open', $cache_refresh=false) + { + if (!$cache_refresh + and isset($this->_extra_cache['getTagIdsByStatus-'.$status])) { + return $this->_extra_cache['getTagIdsByStatus-'.$status]; + } + switch ($status) { + case 'open': + $key = 'labels_issue_open'; + $default = IDF_Form_IssueTrackingConf::init_open; + break; + case 'closed': + default: + $key = 'labels_issue_closed'; + $default = IDF_Form_IssueTrackingConf::init_closed; + break; + } + $tags = array(); + foreach ($this->getTagsFromConfig($key, $default, 'Status') as $tag) { + $tags[] = (int) $tag->id; + } + $this->_extra_cache['getTagIdsByStatus-'.$status] = $tags; + return $tags; + } + + /** + * Convert the definition of tags in the configuration into the + * corresponding list of tags. + * + * @param string Configuration key where the tag is. + * @param string Default config if nothing in the db. + * @param string Default class. + * @return array List of tags + */ + public function getTagsFromConfig($cfg_key, $default, $dclass='Other') + { + $conf = $this->getConf(); + $tags = array(); + foreach (preg_split("/\015\012|\015|\012/", $conf->getVal($cfg_key, $default), -1, PREG_SPLIT_NO_EMPTY) as $s) { + $_s = explode('=', $s, 2); + $v = trim($_s[0]); + $_v = explode(':', $v, 2); + if (count($_v) > 1) { + $class = trim($_v[0]); + $name = trim($_v[1]); + } else { + $name = trim($_s[0]); + $class = $dclass; + } + $tags[] = IDF_Tag::add($name, $this, $class); + } + return $tags; + } + + /** + * Returns a list of relations which are available in this project as + * associative array. Each key-value pair marks a set of orthogonal + * relations. To ease processing, each of these pairs is included twice + * in the array, once as key1 => key2 and once as key2 => key1. + * + * @return array List of relation names + */ + public function getRelationsFromConfig() + { + $conf = $this->getConf(); + $rel = $conf->getVal('issue_relations', IDF_Form_IssueTrackingConf::init_relations); + $relations = array(); + foreach (preg_split("/\015\012|\015|\012/", $rel, -1, PREG_SPLIT_NO_EMPTY) as $s) { + $verbs = preg_split("/\s*,\s*/", $s, 2); + if (count($verbs) == 1) + $relations += array($verbs[0] => $verbs[0]); + else + $relations += array($verbs[0] => $verbs[1], $verbs[1] => $verbs[0]); + } + return $relations; + } + + /** + * Return membership data. + * + * The array has 3 keys: 'members', 'owners' and 'authorized'. + * + * The list of users is only taken using the row level permission + * table. That is, if you set a user as administrator, he will + * have the member and owner rights but will not appear in the + * lists. + * + * @param string Format ('objects'), 'string'. + * @return mixed Array of Pluf_User or newline separated list of logins. + */ + public function getMembershipData($fmt='objects') + { + $mperm = Pluf_Permission::getFromString('IDF.project-member'); + $operm = Pluf_Permission::getFromString('IDF.project-owner'); + $aperm = Pluf_Permission::getFromString('IDF.project-authorized-user'); + $grow = new Pluf_RowPermission(); + $db =& Pluf::db(); + $false = Pluf_DB_BooleanToDb(false, $db); + $sql = new Pluf_SQL('model_class=%s AND model_id=%s AND owner_class=%s AND permission=%s AND negative='.$false, + array('IDF_Project', $this->id, 'Pluf_User', $operm->id)); + $owners = new Pluf_Template_ContextVars(array()); + foreach ($grow->getList(array('filter' => $sql->gen())) as $row) { + if ($fmt == 'objects') { + $owners[] = Pluf::factory('Pluf_User', $row->owner_id); + } else { + $owners[] = Pluf::factory('Pluf_User', $row->owner_id)->login; + } + } + $sql = new Pluf_SQL('model_class=%s AND model_id=%s AND owner_class=%s AND permission=%s AND negative='.$false, + array('IDF_Project', $this->id, 'Pluf_User', $mperm->id)); + $members = new Pluf_Template_ContextVars(array()); + foreach ($grow->getList(array('filter' => $sql->gen())) as $row) { + if ($fmt == 'objects') { + $members[] = Pluf::factory('Pluf_User', $row->owner_id); + } else { + $members[] = Pluf::factory('Pluf_User', $row->owner_id)->login; + } + } + $authorized = new Pluf_Template_ContextVars(array()); + if ($aperm != false) { + $sql = new Pluf_SQL('model_class=%s AND model_id=%s AND owner_class=%s AND permission=%s AND negative='.$false, + array('IDF_Project', $this->id, 'Pluf_User', $aperm->id)); + foreach ($grow->getList(array('filter' => $sql->gen())) as $row) { + if ($fmt == 'objects') { + $authorized[] = Pluf::factory('Pluf_User', $row->owner_id); + } else { + $authorized[] = Pluf::factory('Pluf_User', $row->owner_id)->login; + } + } + } + if ($fmt == 'objects') { + return new Pluf_Template_ContextVars(array('members' => $members, 'owners' => $owners, 'authorized' => $authorized)); + } else { + return array('members' => implode("\n", (array) $members), + 'owners' => implode("\n", (array) $owners), + 'authorized' => implode("\n", (array) $authorized), + ); + } + } + + /** + * Generate the tag clouds. + * + * Return an array of tags sorted by class, then name. Each tag + * get the extra property 'nb_use' for the number of use in the + * project. + * + * @param string ('issues') 'closed_issues', 'wiki' or 'downloads' + * @return ArrayObject of IDF_Tag + */ + public function getTagCloud($what='issues') + { + $tag_t = Pluf::factory('IDF_Tag')->getSqlTable(); + if ($what == 'issues' or $what == 'closed_issues') { + $what_t = Pluf::factory('IDF_Issue')->getSqlTable(); + $asso_t = $this->_con->pfx.'idf_issue_idf_tag_assoc'; + if ($what == 'issues') { + $ostatus = $this->getTagIdsByStatus('open'); + } else { + $ostatus = $this->getTagIdsByStatus('closed'); + } + if (count($ostatus) == 0) $ostatus[] = 0; + $sql = sprintf('SELECT '.$tag_t.'.id AS id, COUNT(*) AS nb_use FROM '.$tag_t.' '."\n". + 'LEFT JOIN '.$asso_t.' ON idf_tag_id='.$tag_t.'.id '."\n". + 'LEFT JOIN '.$what_t.' ON idf_issue_id='.$what_t.'.id '."\n". + 'WHERE idf_tag_id IS NOT NULL AND '.$what_t.'.status IN (%s) AND '.$what_t.'.project='.$this->id.' GROUP BY '.$tag_t.'.id, '.$tag_t.'.class, '.$tag_t.'.name ORDER BY '.$tag_t.'.class ASC, '.$tag_t.'.name ASC', + implode(', ', $ostatus)); + } elseif ($what == 'wiki') { + $dep_ids = IDF_Views_Wiki::getDeprecatedPagesIds($this); + $extra = ''; + if (count($dep_ids)) { + $extra = ' AND idf_wiki_page_id NOT IN ('.implode(', ', $dep_ids).') '; + } + $what_t = Pluf::factory('IDF_Wiki_Page')->getSqlTable(); + $asso_t = $this->_con->pfx.'idf_tag_idf_wiki_page_assoc'; + $sql = 'SELECT '.$tag_t.'.id AS id, COUNT(*) AS nb_use FROM '.$tag_t.' '."\n". + 'LEFT JOIN '.$asso_t.' ON idf_tag_id='.$tag_t.'.id '."\n". + 'LEFT JOIN '.$what_t.' ON idf_wiki_page_id='.$what_t.'.id '."\n". + 'WHERE idf_tag_id IS NOT NULL '.$extra.' AND '.$what_t.'.project='.$this->id.' GROUP BY '.$tag_t.'.id, '.$tag_t.'.class, '.$tag_t.'.name ORDER BY '.$tag_t.'.class ASC, '.$tag_t.'.name ASC'; + } elseif ($what == 'downloads') { + $dep_ids = IDF_Views_Download::getDeprecatedFilesIds($this); + $extra = ''; + if (count($dep_ids)) { + $extra = ' AND idf_upload_id NOT IN ('.implode(', ', $dep_ids).') '; + } + $what_t = Pluf::factory('IDF_Upload')->getSqlTable(); + $asso_t = $this->_con->pfx.'idf_tag_idf_upload_assoc'; + $sql = 'SELECT '.$tag_t.'.id AS id, COUNT(*) AS nb_use FROM '.$tag_t.' '."\n". + 'LEFT JOIN '.$asso_t.' ON idf_tag_id='.$tag_t.'.id '."\n". + 'LEFT JOIN '.$what_t.' ON idf_upload_id='.$what_t.'.id '."\n". + 'WHERE idf_tag_id IS NOT NULL '.$extra.' AND '.$what_t.'.project='.$this->id.' GROUP BY '.$tag_t.'.id, '.$tag_t.'.class, '.$tag_t.'.name ORDER BY '.$tag_t.'.class ASC, '.$tag_t.'.name ASC'; + } + $tags = array(); + foreach ($this->_con->select($sql) as $idc) { + $tag = new IDF_Tag($idc['id']); + $tag->nb_use = $idc['nb_use']; + // group by class + if (!array_key_exists($tag->class, $tags)) { + $tags[$tag->class] = array(); + } + $tags[$tag->class][] = $tag; + } + return new Pluf_Template_ContextVars($tags); + } + + /** + * Get the repository size. + * + * @param bool Force to skip the cache (false) + * @return int Size in byte or -1 if not available + */ + public function getRepositorySize($force=false) + { + $last_eval = $this->getConf()->getVal('repository_size_check_date', 0); + if (Pluf::f('idf_no_size_check', false) or + (!$force and $last_eval > time()-172800)) { + return $this->getConf()->getVal('repository_size', -1); + } + $this->getConf()->setVal('repository_size_check_date', time()); + $scm = IDF_Scm::get($this); + $this->getConf()->setVal('repository_size', $scm->getRepositorySize()); + return $this->getConf()->getVal('repository_size', -1); + } + + /** + * Get the access url to the repository. + * + * This will return the right url based on the user. + * + * @param Pluf_User The user (null) + * @param string A specific commit to access + */ + public function getSourceAccessUrl($user=null, $commit=null) + { + $right = $this->getConf()->getVal('source_access_rights', 'all'); + if (($user == null or $user->isAnonymous()) + and $right == 'all' and !$this->private) { + return $this->getRemoteAccessUrl($commit); + } + return $this->getWriteRemoteAccessUrl($user, $commit); + } + + + /** + * Get the remote access url to the repository. + * + * This will always return the anonymous access url. + * + * @param string A specific commit to access + */ + public function getRemoteAccessUrl($commit=null) + { + $conf = $this->getConf(); + $scm = $conf->getVal('scm', 'git'); + $scms = Pluf::f('allowed_scm'); + Pluf::loadClass($scms[$scm]); + return call_user_func(array($scms[$scm], 'getAnonymousAccessUrl'), + $this, $commit); + } + + /** + * Get the remote write access url to the repository. + * + * Some SCM have a remote access URL to write which is not the + * same as the one to read. For example, you do a checkout with + * git-daemon and push with SSH. + * + * @param string A specific commit to access + */ + public function getWriteRemoteAccessUrl($user,$commit=null) + { + $conf = $this->getConf(); + $scm = $conf->getVal('scm', 'git'); + $scms = Pluf::f('allowed_scm'); + return call_user_func(array($scms[$scm], 'getAuthAccessUrl'), + $this, $user, $commit); + } + + /** + * Get the web hook key. + * + * The goal is to get something predictable but from which one + * cannot reverse find the secret key. + */ + public function getWebHookKey() + { + return md5($this->id.sha1(Pluf::f('secret_key')).$this->shortname); + } + + /** + * Get the root name of the project scm + * + * @return string SCM root + */ + public function getScmRoot() + { + $conf = $this->getConf(); + $roots = array( + 'git' => 'master', + 'svn' => 'HEAD', + 'mercurial' => 'tip', + 'mtn' => 'h:'.$conf->getVal('mtn_master_branch', '*'), + ); + $scm = $conf->getVal('scm', 'git'); + return $roots[$scm]; + } + + /** + * Check that the object belongs to the project or rise a 404 + * error. + * + * By convention, all the objects belonging to a project have the + * 'project' property set, so this is easy to check. + * + * @param Pluf_Model + */ + public function inOr404($obj) + { + if ($obj->project != $this->id) { + throw new Pluf_HTTP_Error404(); + } + } + + /** + * Utility function to get a configuration object. + * + * @return IDF_Conf + */ + public function getConf() + { + if ($this->_pconf == null) { + $this->_pconf = new IDF_Conf(); + $this->_pconf->setProject($this); + } + return $this->_pconf; + } + + /** + * Magic overload that falls back to the values of the internal configuration + * if no getter / caller matched + * + * @param string $key + */ + public function __get($key) + { + try { + return parent::__get($key); + } + catch (Exception $e) { + return $this->getConf()->getVal($key); + } + } + + /** + * Get simple statistics about the project. + * + * This returns an associative array with number of tickets, + * number of downloads, etc. + * + * @return array Stats + */ + public function getStats() + { + $stats = array(); + $stats['total'] = 0; + $what = array('downloads' => 'IDF_Upload', + 'reviews' => 'IDF_Review', + 'issues' => 'IDF_Issue', + 'docpages' => 'IDF_Wiki_Page', + 'commits' => 'IDF_Commit', + ); + foreach ($what as $key=>$m) { + $i = Pluf::factory($m)->getCount(array('filter' => 'project='.(int)$this->id)); + $stats[$key] = $i; + $stats['total'] += $i; + } + /** + * [signal] + * + * IDF_Project::getStats + * + * [sender] + * + * IDF_Project + * + * [description] + * + * This signal allows an application to update the statistics + * array of a project. For example to add the on disk size + * of the repository if available. + * + * [parameters] + * + * array('project' => $project, + * 'stats' => $stats) + * + */ + $params = array('project' => $this, + 'stats' => $stats); + Pluf_Signal::send('IDF_Project::getStats', + 'IDF_Project', $params); + return $stats; + } + + /** + * Needs to be called when you update the memberships of a + * project. + * + * This will allow a plugin to, for example, update some access + * rights to a repository. + */ + public function membershipsUpdated() + { + /** + * [signal] + * + * IDF_Project::membershipsUpdated + * + * [sender] + * + * IDF_Project + * + * [description] + * + * This signal allows an application to update the some access + * rights to a repository when the project memberships is + * updated. + * + * [parameters] + * + * array('project' => $project) + * + */ + $params = array('project' => $this); + Pluf_Signal::send('IDF_Project::membershipsUpdated', + 'IDF_Project', $params); + } + + /** + * Needs to be called when you create a project. + * + * We cannot put it into the postSave call as the configuration of + * the project is not defined at that time. + */ + function created() + { + /** + * [signal] + * + * IDF_Project::created + * + * [sender] + * + * IDF_Project + * + * [description] + * + * This signal allows an application to perform special + * operations at the creation of a project. + * + * [parameters] + * + * array('project' => $project) + * + */ + $params = array('project' => $this); + Pluf_Signal::send('IDF_Project::created', + 'IDF_Project', $params); + } + + /** + * The delete() call do not like circular references and the + * IDF_Tag is creating some. We predelete to solve these issues. + */ + public function preDelete() + { + /** + * [signal] + * + * IDF_Project::preDelete + * + * [sender] + * + * IDF_Project + * + * [description] + * + * This signal allows an application to perform special + * operations at the deletion of a project. + * + * [parameters] + * + * array('project' => $project) + * + */ + $params = array('project' => $this); + Pluf_Signal::send('IDF_Project::preDelete', + 'IDF_Project', $params); + $what = array('IDF_Upload', 'IDF_Review', 'IDF_Issue', + 'IDF_Wiki_Page', 'IDF_Wiki_Resource', + 'IDF_Commit', 'IDF_Tag', + ); + foreach ($what as $m) { + foreach (Pluf::factory($m)->getList(array('filter' => 'project='.(int)$this->id)) as $item) { + $item->delete(); + } + } + } + + /** + * Check if the project has one restricted tab. + * + * @return bool + */ + public function isRestricted() + { + if ($this->_isRestricted !== null) { + return $this->_isRestricted; + } + if ($this->private) { + $this->_isRestricted = true; + return true; + } + $tabs = array( + 'source_access_rights', + 'issues_access_rights', + 'downloads_access_rights', + 'wiki_access_rights', + 'review_access_rights' + ); + $conf = $this->getConf(); + foreach ($tabs as $tab) { + if (!in_array($conf->getVal($tab, 'all'), + array('all', 'none'))) { + $this->_isRestricted = true; + return true; + } + } + $this->_isRestricted = false; + return false; + } + + /** + * Returns an associative array of email addresses to notify about changes + * in a certain tab like 'issues', 'source', and so on. + * + * @param string $tab + * @return array Key is the email address, value is the preferred language setting + */ + public function getNotificationRecipientsForTab($tab) + { + if (!in_array($tab, array('source', 'issues', 'downloads', 'wiki', 'review'))) { + throw new Exception(sprintf('unknown tab %s', $tab)); + } + + $conf = $this->getConf(); + $recipients = array(); + $membership_data = $this->getMembershipData(); + + if ($conf->getVal($tab.'_notification_owners_enabled', false)) { + foreach ($membership_data['owners'] as $owner) { + $recipients[$owner->email] = $owner->language; + } + } + + if ($conf->getVal($tab.'_notification_members_enabled', false)) { + foreach ($membership_data['members'] as $member) { + $recipients[$member->email] = $member->language; + } + } + + if ($conf->getVal($tab.'_notification_email_enabled', false)) { + $addresses = preg_split('/\s*,\s*/', + $conf->getVal($tab.'_notification_email', ''), + -1, PREG_SPLIT_NO_EMPTY); + + // we use a default language setting for this plain list of + // addresses, but we ensure that we do not overwrite an existing + // address which might come with a proper setting already + $languages = Pluf::f('languages', array('en')); + foreach ($addresses as $address) { + if (array_key_exists($address, $recipients)) + continue; + $recipients[$address] = $languages[0]; + } + } + + return $recipients; + } +} diff --git a/indefero/src/IDF/ProjectActivity.php b/indefero/src/IDF/ProjectActivity.php new file mode 100644 index 0000000..0b0f65d --- /dev/null +++ b/indefero/src/IDF/ProjectActivity.php @@ -0,0 +1,78 @@ +_a['table'] = 'idf_projectactivities'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + 'blank' => true, + ), + 'project' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_Project', + 'blank' => false, + 'verbose' => __('project'), + 'relate_name' => 'activities', + ), + 'date' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => false, + 'verbose' => __('date'), + ), + 'value' => + array( + 'type' => 'Pluf_DB_Field_Float', + 'blank' => false, + 'verbose' => __('value'), + 'default' => 0, + ), + ); + } + + function postSave($create=false) + { + $prj = $this->get_project(); + $sql = new Pluf_SQL('project=%s', array($prj->id)); + $list = Pluf::factory('IDF_ProjectActivity')->getList(array('filter' => $sql->gen(), 'order' => 'date desc')); + if (count($list) > 0 && $prj->current_activity != $list[0]->id) { + $prj->current_activity = $list[0]; + $prj->update(); + } + } +} diff --git a/indefero/src/IDF/Queue.php b/indefero/src/IDF/Queue.php new file mode 100644 index 0000000..356cd34 --- /dev/null +++ b/indefero/src/IDF/Queue.php @@ -0,0 +1,222 @@ + + * $item = new IDF_Queue(); + * $item->type = 'new_commit'; + * $item->payload = array('what', 'ever', array('data')); + * $item->create(); + * + * + * To process one item from the queue, you first need to register an + * handler, by adding the following in your relations.php file before + * the return statement or in your config file. + * + * + * Pluf_Signal::connect('IDF_Queue::processItem', + * array('YourApp_Class', 'processItem')); + * + * + * The processItem method will be called with two arguments, the first + * is the name of the signal ('IDF_Queue::processItem') and the second + * is an array with: + * + * + * array('item' => $item, + * 'res' => array('OtherApp_Class::handler' => false, + * 'FooApp_Class::processItem' => true)); + * + * + * When you process an item, you need first to check if the type is + * corresponding to what you want to work with, then you need to check + * in 'res' if you have not already processed successfully the item, + * that is the key 'YourApp_Class::processItem' must be set to true, + * and then you can process the item. At the end of your processing, + * you need to modify by reference the 'res' key to add your status. + * + * All the data except for the type is in the payload, this makes the + * queue flexible to manage many different kind of tasks. + * + */ +class IDF_Queue extends Pluf_Model +{ + public $_model = __CLASS__; + + function init() + { + $this->_a['table'] = 'idf_queue'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + 'blank' => true, + ), + 'status' => + array( + 'type' => 'Pluf_DB_Field_Integer', + 'blank' => false, + 'choices' => array( + 'pending' => 0, + 'in_progress' => 1, + 'need_retry' => 2, + 'done' => 3, + 'error' => 4, + ), + 'default' => 0, + ), + 'trials' => + array( + 'type' => 'Pluf_DB_Field_Integer', + 'default' => 0, + ), + 'type' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 50, + ), + 'payload' => + array( + 'type' => 'Pluf_DB_Field_Serialized', + 'blank' => false, + ), + 'results' => + array( + 'type' => 'Pluf_DB_Field_Serialized', + 'blank' => false, + ), + 'lasttry_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + ), + 'creation_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + ), + ); + } + + function preSave($create=false) + { + if ($create) { + $this->creation_dtime = gmdate('Y-m-d H:i:s'); + $this->lasttry_dtime = gmdate('Y-m-d H:i:s'); + $this->results = array(); + $this->trials = 0; + $this->status = 0; + } + } + + /** + * The current item is going to be processed. + */ + function processItem() + { + /** + * [signal] + * + * IDF_Queue::processItem + * + * [sender] + * + * IDF_Queue + * + * [description] + * + * This signal allows an application to run an asynchronous + * job. The handler gets the queue item and the results from + * the previous run. If the handler key is not set, then the + * job was not run. If set it can be either true (already done) + * or false (error at last run). + * + * [parameters] + * + * array('item' => $item, 'res' => $res) + * + */ + $params = array('item' => $this, 'res' => $this->results); + Pluf_Signal::send('IDF_Queue::processItem', + 'IDF_Queue', $params); + $this->status = 3; // Success + foreach ($params['res'] as $handler=>$ok) { + if (!$ok) { + $this->status = 2; // Set to need retry + $this->trials += 1; + break; + } + } + $this->results = $params['res']; + $this->lasttry_dtime = gmdate('Y-m-d H:i:s'); + $this->update(); + } + + /** + * Parse the queue. + * + * It is a signal handler to just hook itself at the right time in + * the cron job performing the maintainance work. + * + * The processing relies on the fact that no other processing jobs + * must run at the same time. That is, your cron job must use a + * lock file or something like to not run in parallel. + * + * The processing is simple, first get 500 queue items, mark them + * as being processed and for each of them call the processItem() + * method which will trigger another event for processing. + * + * If you are processing more than 500 items per batch, you need + * to switch to a different solution. + * + */ + public static function process($sender, &$params) + { + $where = 'status=0 OR status=2'; + $items = Pluf::factory('IDF_Queue')->getList(array('filter'=>$where, + 'nb'=> 500)); + Pluf_Log::event(array('IDF_Queue::process', $items->count())); + foreach ($items as $item) { + $item->status = 1; + $item->update(); + } + foreach ($items as $item) { + $item->status = 1; + $item->processItem(); + } + } +} diff --git a/indefero/src/IDF/Review.php b/indefero/src/IDF/Review.php new file mode 100644 index 0000000..2177aaf --- /dev/null +++ b/indefero/src/IDF/Review.php @@ -0,0 +1,198 @@ + Patch > Comment > Comment on file + * + * For each review, one can have several patches. Each patch, is + * getting a series of comments. A comment is tracking the state + * change in the review (like the issue comments). For each comment, + * we have a series of file comments. The file comments are associated + * to the a given modified file in the patch. + */ +class IDF_Review extends Pluf_Model +{ + public $_model = __CLASS__; + + function init() + { + $this->_a['table'] = 'idf_reviews'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + 'blank' => true, + ), + 'project' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_Project', + 'blank' => false, + 'verbose' => __('project'), + 'relate_name' => 'reviews', + ), + 'summary' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 250, + 'verbose' => __('summary'), + ), + 'submitter' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'Pluf_User', + 'blank' => false, + 'verbose' => __('submitter'), + 'relate_name' => 'submitted_review', + ), + 'interested' => + array( + 'type' => 'Pluf_DB_Field_Manytomany', + 'model' => 'Pluf_User', + 'blank' => true, + 'help_text' => 'Interested users will get an email notification when the review is changed.', + ), + 'tags' => + array( + 'type' => 'Pluf_DB_Field_Manytomany', + 'blank' => true, + 'model' => 'IDF_Tag', + 'verbose' => __('labels'), + ), + 'status' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'blank' => false, + 'model' => 'IDF_Tag', + 'verbose' => __('status'), + ), + 'creation_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('creation date'), + ), + 'modif_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('modification date'), + ), + ); + $this->_a['idx'] = array( + 'modif_dtime_idx' => + array( + 'col' => 'modif_dtime', + 'type' => 'normal', + ), + ); + $table = $this->_con->pfx.'idf_review_idf_tag_assoc'; + $this->_a['views'] = array( + 'join_tags' => + array( + 'join' => 'LEFT JOIN '.$table + .' ON idf_review_id=id', + ), + ); + } + + /** + * Iterate through the patches and comments to get the reviewers. + */ + function getReviewers() + { + $rev = new ArrayObject(); + foreach ($this->get_patches_list() as $p) { + foreach ($p->get_comments_list() as $c) { + $rev[] = $c->get_submitter(); + } + } + return Pluf_Model_RemoveDuplicates($rev); + } + + function __toString() + { + return $this->id.' - '.$this->summary; + } + + function _toIndex() + { + return ''; + } + + function preDelete() + { + IDF_Timeline::remove($this); + IDF_Search::remove($this); + } + + function preSave($create=false) + { + if ($create) { + $this->creation_dtime = gmdate('Y-m-d H:i:s'); + } + $this->modif_dtime = gmdate('Y-m-d H:i:s'); + } + + function postSave($create=false) + { + // At creation, we index after saving the associated patch. + if (!$create) IDF_Search::index($this); + } + + /** + * Returns an HTML fragment used to display this review in the + * timeline. + * + * The request object is given to be able to check the rights and + * as such create links to other items etc. You can consider that + * if displayed, you can create a link to it. + * + * @param Pluf_HTTP_Request + * @return Pluf_Template_SafeString + */ + public function timelineFragment($request) + { + return ''; + } + + public function feedFragment($request) + { + return ''; + } +} \ No newline at end of file diff --git a/indefero/src/IDF/Review/Comment.php b/indefero/src/IDF/Review/Comment.php new file mode 100644 index 0000000..3b6a0fd --- /dev/null +++ b/indefero/src/IDF/Review/Comment.php @@ -0,0 +1,242 @@ +_a['table'] = 'idf_review_comments'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + 'blank' => true, + ), + 'patch' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_Review_Patch', + 'blank' => false, + 'verbose' => __('patch'), + 'relate_name' => 'comments', + ), + 'content' => + array( + 'type' => 'Pluf_DB_Field_Text', + 'blank' => true, // if only commented on lines + 'verbose' => __('comment'), + ), + 'submitter' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'Pluf_User', + 'blank' => false, + 'verbose' => __('submitter'), + ), + 'changes' => + array( + 'type' => 'Pluf_DB_Field_Serialized', + 'blank' => true, + 'verbose' => __('changes'), + 'help_text' => 'Serialized array of the changes in the review.', + ), + 'vote' => + array( + 'type' => 'Pluf_DB_Field_Integer', + 'default' => 0, + 'blank' => true, + 'verbose' => __('vote'), + 'help_text' => '1, 0 or -1 for positive, neutral or negative vote.', + ), + 'creation_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('creation date'), + 'index' => true, + ), + ); + } + + function changedReview() + { + return (is_array($this->changes) and count($this->changes) > 0); + } + + function _toIndex() + { + return $this->content; + } + + function preDelete() + { + IDF_Timeline::remove($this); + } + + function preSave($create=false) + { + if ($create) { + $this->creation_dtime = gmdate('Y-m-d H:i:s'); + } + } + + function postSave($create=false) + { + if ($create) { + IDF_Timeline::insert($this, + $this->get_patch()->get_review()->get_project(), + $this->get_submitter()); + } + } + + public function timelineFragment($request) + { + $review = $this->get_patch()->get_review(); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Review::view', + array($request->project->shortname, + $review->id)); + $out = ''. + Pluf_esc(Pluf_Template_dateAgo($this->creation_dtime, 'without')). + ''; + $stag = new IDF_Template_ShowUser(); + $user = $stag->start($this->get_submitter(), $request, '', false); + $ic = (in_array($review->status, $request->project->getTagIdsByStatus('closed'))) ? 'issue-c' : 'issue-o'; + $out .= sprintf(__('Review %3$d, %4$s'), $url, $ic, $review->id, Pluf_esc($review->summary)).''; + $out .= "\n".' +
'.sprintf(__('Update of review %3$d, by %4$s'), $url, $ic, $review->id, $user).'
'; + return Pluf_Template::markSafe($out); + } + + public function feedFragment($request) + { + $review = $this->get_patch()->get_review(); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Review::view', + array($request->project->shortname, + $review->id)); + $title = sprintf(__('%1$s: Updated review %2$d - %3$s'), + Pluf_esc($request->project->name), + $review->id, Pluf_esc($review->summary)); + $url .= '#ic'.$this->id; + $date = Pluf_Date::gmDateToGmString($this->creation_dtime); + $context = new Pluf_Template_Context_Request( + $request, + array('url' => $url, + 'author' => $this->get_submitter(), + 'title' => $title, + 'c' => $this, + 'review' => $review, + 'date' => $date) + ); + $tmpl = new Pluf_Template('idf/review/feedfragment.xml'); + return $tmpl->render($context); + } + + /** + * Notify of the update of the review. + * + * + * @param IDF_Conf Current configuration + * @param bool Creation (true) + */ + public function notify($conf, $create=true) + { + $patch = $this->get_patch(); + $review = $patch->get_review(); + $prj = $review->get_project(); + $reviewers = $review->getReviewers(); + + if (!Pluf_Model_InArray($review->get_submitter(), $reviewers)) { + $reviewers[] = $review->get_submitter(); + } + + $comments = $patch->getFileComments(array('order' => 'id DESC')); + $gcomments = $patch->get_comments_list(array('order' => 'id DESC')); + + $recipients = $prj->getNotificationRecipientsForTab('review'); + + foreach ($reviewers as $user) { + if (array_key_exists($user->email, $recipients)) + continue; + $recipients[$user->email] = $user->language; + } + + $current_locale = Pluf_Translation::getLocale(); + + $from_email = Pluf::f('from_email'); + $messageId = '<'.md5('review'.$review->id.md5(Pluf::f('secret_key'))).'@'.Pluf::f('mail_host', 'localhost').'>'; + + foreach ($recipients as $address => $language) { + + if ($this->get_submitter()->email === $address) { + continue; + } + + Pluf_Translation::loadSetLocale($language); + + $context = new Pluf_Template_Context(array( + 'review' => $review, + 'patch' => $patch, + 'comments' => $comments, + 'gcomments' => $gcomments, + 'project' => $prj, + 'url_base' => Pluf::f('url_base'), + )); + + // reviews only updated through comments, see IDF_Review_Patch::notify() + $tplfile = 'idf/review/review-updated-email.txt'; + $subject = __('Updated Code Review %1$s - %2$s (%3$s)'); + $headers = array('References' => $messageId); + + $tmpl = new Pluf_Template($tplfile); + $text_email = $tmpl->render($context); + + $email = new Pluf_Mail($from_email, $address, + sprintf($subject, $review->id, $review->summary, $prj->shortname)); + $email->addTextMessage($text_email); + $email->addHeaders($headers); + $email->sendMail(); + } + + Pluf_Translation::loadSetLocale($current_locale); + } + + public function get_submitter_data() + { + return IDF_UserData::factory($this->get_submitter()); + } +} diff --git a/indefero/src/IDF/Review/FileComment.php b/indefero/src/IDF/Review/FileComment.php new file mode 100644 index 0000000..803f4c9 --- /dev/null +++ b/indefero/src/IDF/Review/FileComment.php @@ -0,0 +1,110 @@ +_a['table'] = 'idf_review_filecomments'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + 'blank' => true, + ), + 'comment' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_Review_Comment', + 'blank' => false, + 'relate_name' => 'filecomments', + 'verbose' => __('comment'), + ), + 'cfile' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 250, + 'help_text' => 'The changed file, for example src/foo/bar.txt, this is the path to access it in the repository.', + ), + 'cline' => + array( + 'type' => 'Pluf_DB_Field_Integer', + 'blank' => false, + 'default' => 0, + 'help_text' => 'The commented line, negative value is the old file, positive the new, 0 general comment.', + ), + 'content' => + array( + 'type' => 'Pluf_DB_Field_Text', + 'blank' => false, + 'verbose' => __('comment'), + ), + 'creation_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('creation date'), + 'index' => true, + ), + ); + } + + function _toIndex() + { + return $this->cfile.' '.$this->content; + } + + function preDelete() + { + } + + function preSave($create=false) + { + if ($create) { + $this->creation_dtime = gmdate('Y-m-d H:i:s'); + } + } + + function postSave($create=false) + { + } + + public function timelineFragment($request) + { + return ''; + } + + public function feedFragment($request) + { + return ''; + } +} diff --git a/indefero/src/IDF/Review/Patch.php b/indefero/src/IDF/Review/Patch.php new file mode 100644 index 0000000..c24e77a --- /dev/null +++ b/indefero/src/IDF/Review/Patch.php @@ -0,0 +1,227 @@ +_a['table'] = 'idf_review_patches'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + 'blank' => true, + ), + 'review' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_Review', + 'blank' => false, + 'verbose' => __('review'), + 'relate_name' => 'patches', + ), + 'summary' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 250, + 'verbose' => __('summary'), + ), + 'commit' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_Commit', + 'blank' => false, + 'verbose' => __('commit'), + 'relate_name' => 'patches', + ), + 'description' => + array( + 'type' => 'Pluf_DB_Field_Text', + 'blank' => false, + 'verbose' => __('description'), + ), + 'patch' => + array( + 'type' => 'Pluf_DB_Field_File', + 'blank' => false, + 'verbose' => __('patch'), + 'help_text' => 'The patch is stored at the same place as the issue attachments with the same approach for the name.', + ), + 'creation_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('creation date'), + 'index' => true, + ), + ); + } + + /** + * Get the list of file comments. + * + * It will go through the patch comments and find for each the + * file comments. + * + * @param array Filter to apply to the file comment list (array()) + */ + function getFileComments($filter=array()) + { + $files = new ArrayObject(); + foreach ($this->get_comments_list(array('order'=>'creation_dtime ASC')) as $ct) { + foreach ($ct->get_filecomments_list($filter) as $fc) { + $files[] = $fc; + } + } + return $files; + } + + function _toIndex() + { + return ''; + } + + function preDelete() + { + IDF_Timeline::remove($this); + } + + function preSave($create=false) + { + if ($create) { + $this->creation_dtime = gmdate('Y-m-d H:i:s'); + } + } + + function postSave($create=false) + { + if ($create) { + IDF_Timeline::insert($this, + $this->get_review()->get_project(), + $this->get_review()->get_submitter()); + IDF_Search::index($this->get_review()); + } + } + + public function timelineFragment($request) + { + $review = $this->get_review(); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Review::view', + array($request->project->shortname, + $review->id)); + $out = ''. + Pluf_esc(Pluf_Template_dateAgo($this->creation_dtime, 'without')). + ''; + $stag = new IDF_Template_ShowUser(); + $user = $stag->start($review->get_submitter(), $request, '', false); + $ic = (in_array($review->status, $request->project->getTagIdsByStatus('closed'))) ? 'issue-c' : 'issue-o'; + $out .= sprintf(__('Review %3$d, %4$s'), $url, $ic, $review->id, Pluf_esc($review->summary)).''; + $out .= "\n".' +
'.sprintf(__('Creation of review %3$d, by %4$s'), $url, $ic, $review->id, $user).'
'; + return Pluf_Template::markSafe($out); + } + + public function feedFragment($request) + { + $review = $this->get_review(); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Review::view', + array($request->project->shortname, + $review->id)); + $title = sprintf(__('%1$s: Creation of Review %2$d - %3$s'), + Pluf_esc($request->project->name), + $review->id, Pluf_esc($review->summary)); + $date = Pluf_Date::gmDateToGmString($this->creation_dtime); + $context = new Pluf_Template_Context_Request( + $request, + array('url' => $url, + 'author' => $review->get_submitter(), + 'title' => $title, + 'p' => $this, + 'review' => $review, + 'date' => $date) + ); + $tmpl = new Pluf_Template('idf/review/feedfragment.xml'); + return $tmpl->render($context); + } + + public function notify($conf, $create=true) + { + $review = $this->get_review(); + $project = $review->get_project(); + $current_locale = Pluf_Translation::getLocale(); + + $from_email = Pluf::f('from_email'); + $messageId = '<'.md5('review'.$review->id.md5(Pluf::f('secret_key'))).'@'.Pluf::f('mail_host', 'localhost').'>'; + $recipients = $project->getNotificationRecipientsForTab('review'); + + foreach ($recipients as $address => $language) { + + if ($review->get_submitter()->email === $address) { + continue; + } + + Pluf_Translation::loadSetLocale($language); + + $context = new Pluf_Template_Context(array( + 'review' => $review, + 'patch' => $this, + 'comments' => array(), + 'project' => $project, + 'url_base' => Pluf::f('url_base'), + )); + + // reviews are updated through comments, see IDF_Review_Comment::notify() + $tplfile = 'idf/review/review-created-email.txt'; + $subject = __('New Code Review %1$s - %2$s (%3$s)'); + $headers = array('Message-ID' => $messageId); + + $tmpl = new Pluf_Template($tplfile); + $text_email = $tmpl->render($context); + + $email = new Pluf_Mail($from_email, + $address, + sprintf($subject, + $review->id, + $review->summary, + $project->shortname)); + $email->addTextMessage($text_email); + $email->addHeaders($headers); + $email->sendMail(); + } + + Pluf_Translation::loadSetLocale($current_locale); + } +} diff --git a/indefero/src/IDF/Scm.php b/indefero/src/IDF/Scm.php new file mode 100644 index 0000000..350b073 --- /dev/null +++ b/indefero/src/IDF/Scm.php @@ -0,0 +1,506 @@ +getConf()->getVal('scm', 'git'); + $scms = Pluf::f('allowed_scm'); + return call_user_func(array($scms[$scm], 'factory'), $project); + } + + /** + * Runs the given command and log some information. + * + * A previous version used plain exec(), but this should not be used + * for various reasons, one being that this command does not preserve + * trailing whitespace, which is essential for proper diff parsing. + * + * @param $caller Calling method + * @param $cmd Command to run + * @param &$out Array of output + * @param &$return Return value + */ + public static function exec($caller, $cmd, &$out=null, &$return=null) + { + $return = -1; + Pluf_Log::stime('timer'); + $fp = popen($cmd, 'r'); + $buf = ''; + if ($fp !== false) { + while (!feof($fp)) { + $buf .= fread($fp, 1024); + } + $return = pclose($fp); + } + $out = preg_split('/\r\n|\r|\n/', $buf); + $elem = count($out); + if ($elem > 0 && $out[$elem-1] === '') + unset($out[$elem-1]); + Pluf_Log::perf(array($caller, $cmd, Pluf_Log::etime('timer', 'total_exec'))); + Pluf_Log::debug(array($caller, $cmd, $out)); + Pluf_Log::inc('exec_calls'); + } + + /** + * Run shell_exec and log some information. + * + * @param $caller Calling method + * @param $cmd Command to run + * @return string The output + */ + public static function shell_exec($caller, $cmd) + { + Pluf_Log::stime('timer'); + $ret = shell_exec($cmd); + Pluf_Log::perf(array($caller, $cmd, Pluf_Log::etime('timer', 'total_exec'))); + Pluf_Log::debug(array($caller, $cmd, $ret)); + Pluf_Log::inc('exec_calls'); + return $ret; + } + + /** + * Return the size of the repository in bytes. + * + * @return int Size in byte, -1 if the size cannot be evaluated. + */ + public function getRepositorySize() + { + return -1; + } + + /** + * Returns the URL of the git daemon. + * + * @param IDF_Project + * @return string URL + */ + public static function getAnonymousAccessUrl($project) + { + throw new Pluf_Exception_NotImplemented(); + } + + /** + * Returns the URL for SSH access + * + * @param IDF_Project + * @param Pluf_User + * @return string URL + */ + public static function getAuthAccessUrl($project, $user) + { + throw new Pluf_Exception_NotImplemented(); + } + + /** + * Check if the backend is available for display. + * + * @return bool Available + */ + public function isAvailable() + { + throw new Pluf_Exception_NotImplemented(); + } + + const REVISION_VALID = 0; + const REVISION_INVALID = 1; + const REVISION_AMBIGUOUS = 2; + + /** + * Check if a revision or commit is valid, invalid or ambiguous. + * + * @param string Revision or commit + * @return int One of REVISION_VALID, REVISION_INVALID or REVISION_AMBIGIOUS + */ + public function validateRevision($rev) + { + throw new Pluf_Exception_NotImplemented(); + } + + /** + * Returns an array of single commit objects for ambiguous commit identifiers + * + * @param string Ambiguous commit identifier + * @return array of objects + */ + public function disambiguateRevision($commit) + { + throw new Pluf_Exception_NotImplemented(); + } + + /** + * Returns in which branches a commit/path is. + * + * A commit can be in several branches and some of the SCMs are + * managing branches using subfolders (like Subversion). + * + * This means that to know in which branch we are at the moment, + * one needs to have both the path and the commit. + * + * @param string Commit + * @param string Path + * @return array Branches + */ + public function inBranches($commit, $path) + { + throw new Pluf_Exception_NotImplemented(); + } + + /** + * Returns the list of branches. + * + * The return value must be a branch indexed array with the + * optional path to access the branch as value. For example with + * git you would get (note that some people are using / in the + * name of their git branches): + * + *
+     * array('master' => '',
+     *       'foo-branch' => '',
+     *       'design/feature1' => '')
+     * 
+ * + * But with Subversion, as the branches are managed as subfolder + * with a special folder for trunk, you would get something like: + * + *
+     * array('trunk' => 'trunk',
+     *       'foo-branch' => 'branches/foo-branch',)
+     * 
+ * + * @return array Branches + */ + public function getBranches() + { + throw new Pluf_Exception_NotImplemented(); + } + + /** + * Returns the list of tags. + * + * The format is the same as for the branches. + * + * @see self::getBranches() + * + * @return array Tags + */ + public function getTags() + { + throw new Pluf_Exception_NotImplemented(); + } + + /** + * Returns in which tags a commit/path is. + * + * A commit can be in several tags and some of the SCMs are + * managing tags using subfolders (like Subversion). + * + * This means that to know in which tag we are at the moment, + * one needs to have both the path and the commit. + * + * @param string Commit + * @param string Path + * @return array Tags + */ + public function inTags($commit, $path) + { + throw new Pluf_Exception_NotImplemented(); + } + + /** + * Returns the main branch. + * + * The main branch is the one displayed by default. For example + * master, trunk or tip. + * + * @return string + */ + public function getMainBranch() + { + throw new Pluf_Exception_NotImplemented(); + } + + /** + * Returns the list of files in a given folder. + * + * The list is an array of standard class objects with attributes + * for each file/directory/external element. + * + * This is the most important method of the SCM backend as this is + * the one conveying the speed feeling of the application. All the + * dirty optimization tricks are allowed there. + * + * @param string Revision or commit + * @param string Folder ('/') + * @param string Branch (null) + * @return array + */ + public function getTree($rev, $folder='/', $branch=null) + { + throw new Pluf_Exception_NotImplemented(); + } + + /** + * Get commit details. + * + * @param string Commit or revision number + * @param bool Get commit diff (false) + * @return stdClass + */ + public function getCommit($commit, $getdiff=false) + { + throw new Pluf_Exception_NotImplemented(); + } + + /** + * Returns all recorded changes which lead to the particular commit + * or revision. + * + * Example output: + * + * stdClass object { + * 'additions' => array('path/to/file', 'path/to/directory', ...), + * 'deletions' => array('path/to/file', 'path/to/directory', ...), + * 'renames' => array('old/path/to/file' => 'new/path/to/file', ...), + * 'copies' => array('path/to/source' => 'path/to/target', ...), + * 'patches' => array('path/to/file', ...), + * 'properties' => array('path/to/file' => array( + * 'propname' => 'propvalue', 'deletedprop' => null, ...) + * ), + * ...) + * } + * + * Each member of the returned object is mandatory, but may contain + * an empty array if no changes were recorded. + * + * @param string A commit identifier + * @return object with arrays of individual changes + */ + public function getChanges($commit) + { + throw new Pluf_Exception_NotImplemented(); + } + + /** + * Get latest changes. + * + * It default to the main branch. If possible you should code in a + * way to avoid repetitive calls to getCommit. Try to be + * efficient. + * + * @param string Branch (null) + * @param int Number of changes (25) + * @return array List of commits + */ + public function getChangeLog($branch=null, $n=10) + { + throw new Pluf_Exception_NotImplemented(); + } + + /** + * Given the string describing the author from the log find the + * author in the database. + * + * If the input is an array, it will return an array of results. + * + * @param mixed string/array Author + * @return mixed Pluf_User or null or array + */ + public function findAuthor($author) + { + throw new Pluf_Exception_NotImplemented(); + } + + /** + * Given a revision and a file path, retrieve the file content. + * + * The $cmd_only parameter is to only request the command that is + * used to get the file content. This is used when downloading a + * file at a given revision as it can be passed to a + * Pluf_HTTP_Response_CommandPassThru reponse. This allows to + * stream a large response without buffering it in memory. + * + * The file definition is coming from getPathInfo(). + * + * @see self::getPathInfo() + * + * @param stdClass File definition + * @param bool Returns command only (false) + * @return string File content + */ + public function getFile($def, $cmd_only=false) + { + throw new Pluf_Exception_NotImplemented(); + } + + /** + * Get information about a file or a path. + * + * @param string File or path + * @param string Revision (null) + * @return mixed False or stdClass with info + */ + public function getPathInfo($file, $rev=null) + { + throw new Pluf_Exception_NotImplemented(); + } + + /** + * Given a revision and possible path returns additional properties. + * + * @param string Revision + * @param string Path ('') + * @return mixed null or array of properties + */ + public function getProperties($rev, $path='') + { + return null; + } + + /** + * Given a changelog parsed node, returns extra data. + * + * For example, if the node is a commit object from git, it will a + * stdClass object with the parents array. The extra value could + * then be the parent(s) commit(s). + * + * @param stdClass Commit object/Parse object + * @return array Extra properties + */ + public function getExtraProperties($obj) + { + return array(); + } + + /** + * Generate a zip archive at a given commit, wrapped in a HTTP response, suitable for pushing to client. + * + * @param string Commit + * @param string Prefix ('repository/') + * @return Pluf_HTTP_Response The HTTP Response containing the zip archive + */ + public function getArchiveStream($commit, $prefix='repository/') + { + throw new Pluf_Exception_NotImplemented(); + } + + /** + * Sync the changes in the repository with the timeline. + * + */ + public static function syncTimeline($project, $force=false) + { + $cache = Pluf_Cache::factory(); + $key = 'IDF_Scm:'.$project->shortname.':lastsync'; + if ($force or null === ($res=$cache->get($key))) { + $scm = IDF_Scm::get($project); + if ($scm->isAvailable()) { + foreach ($scm->getChangeLog($scm->getMainBranch(), 25) as $change) { + IDF_Commit::getOrAdd($change, $project); + } + $cache->set($key, true, (int)(Pluf::f('cache_timeout', 300)/2)); + } + } + } + + /** + * Given a path, encode everything but the / + */ + public static function smartEncode($path) + { + return str_replace('%2F', '/', rawurlencode($path)); + } + + /** + * Returns the number of slashes and preceeding path components + * that should be stripped from paths in the SCM's diff output + */ + public function getDiffPathStripLevel() + { + return 0; + } + + public function repository($request, $match) + { + throw new Exception('This repository does not support web based repository access'); + } +} + diff --git a/indefero/src/IDF/Scm/Cache/Git.php b/indefero/src/IDF/Scm/Cache/Git.php new file mode 100644 index 0000000..499f69c --- /dev/null +++ b/indefero/src/IDF/Scm/Cache/Git.php @@ -0,0 +1,138 @@ +project = $this->_project; + $cache->githash = $blob->hash; + $blob->title = IDF_Commit::toUTF8($blob->title); + $cache->content = IDF_Commit::toUTF8($blob->date) . chr(31) + . IDF_Commit::toUTF8($blob->author) . chr(31) + . IDF_Commit::toUTF8($blob->title); + $sql = new Pluf_SQL('project=%s AND githash=%s', + array($this->_project->id, $blob->hash)); + if (0 == Pluf::factory(__CLASS__)->getCount(array('filter' => $sql->gen()))) { + $cache->create(); + } + } + } + + /** + * Get for the given hashes the corresponding date, title and + * author. + * + * It returns an hash indexed array with the info. If an hash is + * not in the db, the key is not set. + * + * Note that the hashes must always come from internal tools. + * + * @param array Hashes to get info + * @return array Blob infos + */ + public function retrieve($hashes) + { + $res = array(); + $db = $this->getDbConnection(); + $hashes = array_map(array($db, 'esc'), $hashes); + $sql = new Pluf_SQL('project=%s AND githash IN ('.implode(', ', $hashes).')', + array($this->_project->id)); + foreach (Pluf::factory(__CLASS__)->getList(array('filter' => $sql->gen())) as $blob) { + $tmp = explode(chr(31), $blob->content, 3); + // sometimes the title might be empty + if (!isset($tmp[2])) $tmp[2] = ''; + + $res[$blob->githash] = (object) array( + 'hash' => $blob->githash, + 'date' => $tmp[0], + 'title' => $tmp[2], + 'author' => $tmp[1], + ); + } + return $res; + } + + /** + * The storage is composed of 4 columns, id, project, hash and the + * raw data. + */ + function init() + { + $this->_a['table'] = 'idf_scm_cache_git'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + 'blank' => true, + ), + 'project' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_Project', + 'blank' => false, + ), + 'githash' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 40, + 'index' => true, + ), + 'content' => + array( + 'type' => 'Pluf_DB_Field_Text', + 'blank' => false, + ), + ); + } +} diff --git a/indefero/src/IDF/Scm/Exception.php b/indefero/src/IDF/Scm/Exception.php new file mode 100644 index 0000000..7d4514b --- /dev/null +++ b/indefero/src/IDF/Scm/Exception.php @@ -0,0 +1,26 @@ +%nTree: %T%nParents: %P%nDate: %ai%n%n%s%n%n%b'; + + /* ============================================== * + * * + * Common Methods Implemented By All The SCMs * + * * + * ============================================== */ + + public function __construct($repo, $project=null) + { + $this->repo = $repo; + $this->project = $project; + } + + /** + * @see IDF_Scm::getChanges() + * + * Git command output is like : + * M doc/Guide utilisateur/Manuel_distrib.tex + * M doc/Guide utilisateur/Manuel_intro.tex + * M doc/Guide utilisateur/Manuel_libpegase_exemples.tex + * M doc/Guide utilisateur/Manuel_page1_version.tex + * A doc/Guide utilisateur/images/ftp-nautilus.png + * M doc/Guide utilisateur/textes/log_boot_PEGASE.txt + * + * Status letters mean : Added (A), Copied (C), Deleted (D), Modified (M), Renamed (R) + */ + public function getChanges($commit) + { + $cmd = sprintf('GIT_DIR=%s '.Pluf::f('git_path', 'git').' show %s --name-status --pretty="format:" --diff-filter="[A|C|D|M|R]" -C -C', + escapeshellarg($this->repo), + escapeshellarg($commit)); + $out = array(); + $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; + self::exec('IDF_Scm_Git::getChanges', $cmd, $out); + + $return = (object) array( + 'additions' => array(), + 'deletions' => array(), + 'renames' => array(), + 'copies' => array(), + 'patches' => array(), + 'properties' => array(), + ); + + foreach ($out as $line) { + $line = trim($line); + if ($line != '') { + $action = $line[0]; + + if ($action == 'A') { + $filename = trim(substr($line, 1)); + $return->additions[] = $filename; + } else if ($action == 'D') { + $filename = trim(substr($line, 1)); + $return->deletions[] = $filename; + } else if ($action == 'M') { + $filename = trim(substr($line, 1)); + $return->patches[] = $filename; + } else if ($action == 'R') { + $matches = preg_split("/\t/", $line); + $return->renames[$matches[1]] = $matches[2]; + } else if ($action == 'C') { + $matches = preg_split("/\t/", $line); + $return->copies[$matches[1]] = $matches[2]; + } + } + } + + return $return; + } + + public function getRepositorySize() + { + if (!file_exists($this->repo)) { + return 0; + } + $cmd = Pluf::f('idf_exec_cmd_prefix', '').'du -sk ' + .escapeshellarg($this->repo); + $out = explode(' ', + self::shell_exec('IDF_Scm_Git::getRepositorySize', $cmd), + 2); + return (int) $out[0]*1024; + } + + public function isAvailable() + { + try { + $branches = $this->getBranches(); + } catch (IDF_Scm_Exception $e) { + return false; + } + return (count($branches) > 0); + } + + public function getBranches() + { + if (isset($this->cache['branches'])) { + return $this->cache['branches']; + } + $cmd = Pluf::f('idf_exec_cmd_prefix', '') + .sprintf('GIT_DIR=%s '.Pluf::f('git_path', 'git').' branch', + escapeshellarg($this->repo)); + self::exec('IDF_Scm_Git::getBranches', + $cmd, $out, $return); + if ($return != 0) { + throw new IDF_Scm_Exception(sprintf($this->error_tpl, + $cmd, $return, + implode("\n", $out))); + } + $res = array(); + foreach ($out as $b) { + $b = substr($b, 2); + if (false !== strpos($b, '/')) { + $res[$this->getCommit($b)->commit] = $b; + } else { + $res[$b] = ''; + } + } + $this->cache['branches'] = $res; + return $res; + } + + public function getMainBranch() + { + $branches = $this->getBranches(); + if (array_key_exists('master', $branches)) + return 'master'; + static $possible = array('main', 'trunk', 'local'); + for ($i = 0; 3 > $i; ++$i) { + if (array_key_exists($possible[$i], $branches)) + return $possible[$i]; + } + return key($branches); + } + + /** + * Note: Running the `git branch --contains $commit` is + * theoritically the best way to do it, until you figure out that + * you cannot cache the result and that it takes several seconds + * to execute on a big tree. + */ + public function inBranches($commit, $path) + { + if (isset($this->cache['inBranches'][$commit])) { + return $this->cache['inBranches'][$commit]; + } + + $cmd = Pluf::f('idf_exec_cmd_prefix', '') + .sprintf('GIT_DIR=%s %s branch --contains %s', + escapeshellarg($this->repo), + Pluf::f('git_path', 'git'), + escapeshellarg($commit)); + self::exec('IDF_Scm_Git::inBranches', $cmd, $out, $return); + if (0 != $return) { + throw new IDF_Scm_Exception(sprintf($this->error_tpl, + $cmd, $return, + implode("\n", $out))); + } + + $res = array(); + foreach ($out as $line) { + $res[] = substr($line, 2); + } + + $this->cache['inBranches'][$commit] = $res; + return $res; + } + + /** + * Will find the parents if available. + */ + public function getExtraProperties($obj) + { + return (isset($obj->parents)) ? array('parents' => $obj->parents) : array(); + } + + /** + * @see IDF_Scm::getTags() + **/ + public function getTags() + { + if (isset($this->cache['tags'])) { + return $this->cache['tags']; + } + $cmd = Pluf::f('idf_exec_cmd_prefix', '') + .sprintf('GIT_DIR=%s %s for-each-ref --format="%%(objectname) %%(refname)" refs/tags', + escapeshellarg($this->repo), + Pluf::f('git_path', 'git')); + self::exec('IDF_Scm_Git::getTags', $cmd, $out, $return); + if (0 != $return) { + throw new IDF_Scm_Exception(sprintf($this->error_tpl, + $cmd, $return, + implode("\n", $out))); + } + $res = array(); + foreach ($out as $b) { + $elts = explode(' ', $b, 2); + $tag = substr(trim($elts[1]), 10); // Remove refs/tags/ prefix + $res[$tag] = ''; + } + krsort($res); + $this->cache['tags'] = $res; + + return $res; + } + + /** + * @see IDF_Scm::inTags() + **/ + public function inTags($commit, $path) + { + if (isset($this->cache['inTags'][$commit])) { + return $this->cache['inTags'][$commit]; + } + + $cmd = Pluf::f('idf_exec_cmd_prefix', '') + .sprintf('GIT_DIR=%s %s tag --contains %s', + escapeshellarg($this->repo), + Pluf::f('git_path', 'git'), + escapeshellarg($commit)); + self::exec('IDF_Scm_Git::inTags', $cmd, $out, $return); + // `git tag` gained the `--contains` option in 1.6.2, earlier + // versions report a bad usage error (129) which we ignore here + if (129 == $return) { + $this->cache['inTags'][$commit] = array(); + return array(); + } + // any other error should of course get noted + if (0 != $return) { + throw new IDF_Scm_Exception(sprintf($this->error_tpl, + $cmd, $return, + implode("\n", $out))); + } + + $res = array(); + foreach ($out as $line) { + $res[] = $line; + } + + $this->cache['inTags'][$commit] = $res; + return $res; + } + + /** + * Git "tree" is not the same as the tree we get here. + * + * With git each commit object stores a related tree object. This + * tree is basically providing what is in the given folder at the + * given commit. It looks something like that: + * + *
+     * 100644 blob bcd155e609c51b4651aab9838b270cce964670af	AUTHORS
+     * 100644 blob 87b44c5c7df3cc90c031317c1ac8efcfd8a13631	COPYING
+     * 100644 blob 2a0f899cbfe33ea755c343b06a13d7de6c22799f	INSTALL.mdtext
+     * 040000 tree 2f469c4c5318aa4ad48756874373370f6112f77b	doc
+     * 040000 tree 911e0bd2706f0069b04744d6ef41353faf06a0a7	logo
+     * 
+ * + * You can then follow what is in the given folder (let say doc) + * by using the hash. + * + * This means that you will have not to confuse the git tree and + * the output tree in the following method. + * + * @see http://www.kernel.org/pub/software/scm/git/docs/git-ls-tree.html + * + */ + public function getTree($commit, $folder='/', $branch=null) + { + $folder = ($folder == '/') ? '' : $folder; + // now we grab the info about this commit including its tree. + if (false == ($co = $this->getCommit($commit))) { + return false; + } + if ($folder) { + // As we are limiting to a given folder, we need to find + // the tree corresponding to this folder. + $tinfo = $this->getTreeInfo($commit, $folder); + if (isset($tinfo[0]) and $tinfo[0]->type == 'tree') { + $tree = $tinfo[0]->hash; + } else { + throw new Exception(sprintf(__('Folder %1$s not found in commit %2$s.'), $folder, $commit)); + } + } else { + $tree = $co->tree; + } + $res = array(); + foreach ($this->getTreeInfo($tree) as $file) { + // Now we grab the files in the current tree with as much + // information as possible. + if ($file->type == 'blob') { + $file->date = $co->date; + $file->log = '----'; + $file->author = 'Unknown'; + } + $file->fullpath = ($folder) ? $folder.'/'.$file->file : $file->file; + $file->efullpath = self::smartEncode($file->fullpath); + if ($file->type == 'commit') { + // We have a submodule + $file = $this->getSubmodule($file, $commit); + } + $res[] = $file; + } + // Grab the details for each blob and return the list. + return $this->getTreeDetails($res); + } + + /** + * Given the string describing the author from the log find the + * author in the database. + * + * @param string Author + * @return mixed Pluf_User or null + */ + public function findAuthor($author) + { + // We extract the email. + $match = array(); + if (!preg_match('/<(.*)>/', $author, $match)) { + return null; + } + // FIXME: newer git versions know a i18n.commitencoding setting which + // leads to another header, "encoding", with which we _could_ try to + // decode the string into utf8. Unfortunately this does not always + // work, especially not in older repos, so we would then still have + // to supply some fallback. + if (!mb_check_encoding($match[1], 'UTF-8')) { + return null; + } + $sql = new Pluf_SQL('login=%s', array($match[1])); + $users = Pluf::factory('Pluf_User')->getList(array('filter'=>$sql->gen())); + if ($users->count() > 0) { + return $users[0]; + } + return Pluf::factory('IDF_EmailAddress')->get_user_for_email_address($match[1]); + } + + public static function getAnonymousAccessUrl($project, $commit=null) + { + return sprintf(Pluf::f('git_remote_url'), $project->shortname); + } + + public static function getAuthAccessUrl($project, $user, $commit=null) + { + // if the user haven't registred a public ssh key, + // he can't use the write url which use the SSH authentification + if ($user != null) { + $keys = $user->get_idf_key_list(); + if (count ($keys) == 0) + return self::getAnonymousAccessUrl($project); + } + + return sprintf(Pluf::f('git_write_remote_url'), $project->shortname); + } + + /** + * Returns this object correctly initialized for the project. + * + * @param IDF_Project + * @return IDF_Scm_Git + */ + public static function factory($project) + { + $rep = sprintf(Pluf::f('git_repositories'), $project->shortname); + return new IDF_Scm_Git($rep, $project); + } + + + public function validateRevision($commit) + { + $type = $this->testHash($commit); + if ('commit' == $type || 'tag' == $type) + return IDF_Scm::REVISION_VALID; + return IDF_Scm::REVISION_INVALID; + } + + /** + * Test a given object hash. + * + * @param string Object hash. + * @return mixed false if not valid or 'blob', 'tree', 'commit', 'tag' + */ + public function testHash($hash) + { + $cmd = sprintf('GIT_DIR=%s '.Pluf::f('git_path', 'git').' cat-file -t %s', + escapeshellarg($this->repo), + escapeshellarg($hash)); + $ret = 0; $out = array(); + $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; + self::exec('IDF_Scm_Git::testHash', $cmd, $out, $ret); + if ($ret != 0) return false; + return trim($out[0]); + } + + /** + * Get the tree info. + * + * @param string Tree hash + * @param bool Do we recurse in subtrees (true) + * @param string Folder in which we want to get the info ('') + * @return array Array of file information. + */ + public function getTreeInfo($tree, $folder='') + { + if (!in_array($this->testHash($tree), array('tree', 'commit', 'tag'))) { + throw new Exception(sprintf(__('Not a valid tree: %s.'), $tree)); + } + $cmd_tmpl = 'GIT_DIR=%s '.Pluf::f('git_path', 'git').' ls-tree -l %s %s'; + $cmd = Pluf::f('idf_exec_cmd_prefix', '') + .sprintf($cmd_tmpl, escapeshellarg($this->repo), + escapeshellarg($tree), escapeshellarg($folder)); + $out = array(); + $res = array(); + self::exec('IDF_Scm_Git::getTreeInfo', $cmd, $out); + foreach ($out as $line) { + list($perm, $type, $hash, $size, $file) = preg_split('/ |\t/', $line, 5, PREG_SPLIT_NO_EMPTY); + $res[] = (object) array('perm' => $perm, 'type' => $type, + 'size' => $size, 'hash' => $hash, + 'file' => $file); + } + return $res; + } + + /** + * Get the file info. + * + * @param string File + * @param string Commit ('HEAD') + * @return false Information + */ + public function getPathInfo($totest, $commit='HEAD') + { + $cmd_tmpl = 'GIT_DIR=%s '.Pluf::f('git_path', 'git').' ls-tree -r -t -l %s'; + $cmd = sprintf($cmd_tmpl, + escapeshellarg($this->repo), + escapeshellarg($commit)); + $out = array(); + $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; + self::exec('IDF_Scm_Git::getPathInfo', $cmd, $out); + foreach ($out as $line) { + list($perm, $type, $hash, $size, $file) = preg_split('/ |\t/', $line, 5, PREG_SPLIT_NO_EMPTY); + if ($totest == $file) { + $pathinfo = pathinfo($file); + return (object) array('perm' => $perm, 'type' => $type, + 'size' => $size, 'hash' => $hash, + 'fullpath' => $file, + 'file' => $pathinfo['basename']); + } + } + return false; + } + + public function getFile($def, $cmd_only=false) + { + $cmd = sprintf(Pluf::f('idf_exec_cmd_prefix', ''). + 'GIT_DIR=%s '.Pluf::f('git_path', 'git').' cat-file blob %s', + escapeshellarg($this->repo), + escapeshellarg($def->hash)); + return ($cmd_only) + ? $cmd : self::shell_exec('IDF_Scm_Git::getFile', $cmd); + } + + /** + * Get commit details. + * + * @param string Commit + * @param bool Get commit diff (false) + * @return array Changes + */ + public function getCommit($commit, $getdiff=false) + { + if ($getdiff) { + $cmd = sprintf('GIT_DIR=%s '.Pluf::f('git_path', 'git').' show --date=iso --pretty=format:%s %s', + escapeshellarg($this->repo), + "'".$this->mediumtree_fmt."'", + escapeshellarg($commit)); + } else { + $cmd = sprintf('GIT_DIR=%s '.Pluf::f('git_path', 'git').' log -1 --date=iso --pretty=format:%s %s', + escapeshellarg($this->repo), + "'".$this->mediumtree_fmt."'", + escapeshellarg($commit)); + } + $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; + $out = self::shell_exec('IDF_Scm_Git::getCommit', $cmd); + if (strlen($out) == 0) { + return false; + } + + $diffStart = false; + if (preg_match('/^diff (?:--git a|--cc)/m', $out, $m, PREG_OFFSET_CAPTURE)) { + $diffStart = $m[0][1]; + } + + $diff = ''; + if ($diffStart !== false) { + $log = substr($out, 0, $diffStart); + $diff = substr($out, $diffStart); + } else { + $log = $out; + } + + $out = self::parseLog(preg_split('/\r\n|\n/', $log)); + $out[0]->diff = $diff; + $out[0]->branch = implode(', ', $this->inBranches($out[0]->commit, null)); + return $out[0]; + } + + /** + * Check if a commit is big. + * + * @param string Commit ('HEAD') + * @return bool The commit is big + */ + public function isCommitLarge($commit='HEAD') + { + $cmd = sprintf('GIT_DIR=%s '.Pluf::f('git_path', 'git').' log --numstat -1 --pretty=format:%s %s', + escapeshellarg($this->repo), + "'commit %H%n'", + escapeshellarg($commit)); + $out = array(); + $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; + self::exec('IDF_Scm_Git::isCommitLarge', $cmd, $out); + $affected = count($out) - 2; + $added = 0; + $removed = 0; + $c=0; + foreach ($out as $line) { + $c++; + if ($c < 3) { + continue; + } + list($a, $r, $f) = preg_split("/[\s]+/", $line, 3, PREG_SPLIT_NO_EMPTY); + $added+=$a; + $removed+=$r; + } + return ($affected > 100 or ($added + $removed) > 20000); + } + + /** + * Get latest changes. + * + * @param string Commit ('HEAD'). + * @param int Number of changes (10). + * @return array Changes. + */ + public function getChangeLog($commit='HEAD', $n=10) + { + if ($n === null) $n = ''; + else $n = ' -'.$n; + $cmd = sprintf('GIT_DIR=%s '.Pluf::f('git_path', 'git').' log%s --date=iso --pretty=format:\'%s\' %s', + escapeshellarg($this->repo), $n, $this->mediumtree_fmt, + escapeshellarg($commit)); + $out = array(); + $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; + self::exec('IDF_Scm_Git::getChangeLog', $cmd, $out); + return self::parseLog($out); + } + + /** + * Parse the log lines of a --pretty=medium log output. + * + * @param array Lines. + * @return array Change log. + */ + public static function parseLog($lines) + { + $res = array(); + $c = array(); + $inheads = true; + $next_is_title = false; + foreach ($lines as $line) { + if (preg_match('/^commit (\w{40})$/', $line)) { + if (count($c) > 0) { + $c['full_message'] = trim($c['full_message']); + $c['full_message'] = IDF_Commit::toUTF8($c['full_message']); + $c['title'] = IDF_Commit::toUTF8($c['title']); + if (isset($c['parents'])) { + $c['parents'] = explode(' ', trim($c['parents'])); + } + $res[] = (object) $c; + } + $c = array(); + $c['commit'] = trim(substr($line, 7, 40)); + $c['full_message'] = ''; + $inheads = true; + $next_is_title = false; + continue; + } + if ($next_is_title) { + $c['title'] = trim($line); + $next_is_title = false; + continue; + } + $match = array(); + if ($inheads and preg_match('/(\S+)\s*:\s*(.*)/', $line, $match)) { + $match[1] = strtolower($match[1]); + $c[$match[1]] = trim($match[2]); + if ($match[1] == 'date') { + $c['date'] = gmdate('Y-m-d H:i:s', strtotime($match[2])); + } + continue; + } + if ($inheads and !$next_is_title and $line == '') { + $next_is_title = true; + $inheads = false; + } + if (!$inheads) { + $c['full_message'] .= trim($line)."\n"; + continue; + } + } + $c['full_message'] = !empty($c['full_message']) ? trim($c['full_message']) : ''; + $c['full_message'] = IDF_Commit::toUTF8($c['full_message']); + $c['title'] = IDF_Commit::toUTF8($c['title']); + if (isset($c['parents'])) { + $c['parents'] = preg_split('/ /', trim($c['parents']), -1, PREG_SPLIT_NO_EMPTY); + } else { + // this is actually an error state because we should _always_ + // be able to parse the parents line with every git version + $c['parents'] = null; + } + $res[] = (object) $c; + return $res; + } + + public function getArchiveStream($commit, $prefix='repository/') + { + $cmd = sprintf(Pluf::f('idf_exec_cmd_prefix', ''). + 'GIT_DIR=%s '.Pluf::f('git_path', 'git').' archive --format=zip --prefix=%s %s', + escapeshellarg($this->repo), + escapeshellarg($prefix), + escapeshellarg($commit)); + return new Pluf_HTTP_Response_CommandPassThru($cmd, 'application/x-zip'); + } + + /** + * @see IDF_Scm::getDiffPathStripLevel() + */ + public function getDiffPathStripLevel() + { + return 1; + } + + /* + * ===================================================== + * Specific Git Commands + * ===================================================== + */ + + /** + * Get submodule details. + * + * Given a "commit" file in the tree, find the submodule details. + * + * @param stdClass File description of the module + * @param string Current commit + * @return stdClass File description + */ + public function getSubmodule($file, $commit) + { + $file->type = 'extern'; + $file->extern = ''; + $info = $this->getPathInfo('.gitmodules', $commit); + if ($info == false) { + return $file; + } + $gitmodules = $this->getFile($info); + if (preg_match('#\[submodule\s+\"'.$file->fullpath.'\"\]\s+path\s=\s(\S+)\s+url\s=\s(\S+)#mi', $gitmodules, $matches)) { + $file->extern = $matches[2]; + } + return $file; + } + + /** + * Foreach file in the tree, find the details. + * + * @param array Tree information + * @return array Updated tree information + */ + public function getTreeDetails($tree) + { + $n = count($tree); + $details = array(); + for ($i=0;$i<$n;$i++) { + if ($tree[$i]->type == 'blob') { + $details[$tree[$i]->hash] = $i; + } + } + if (!count($details)) { + return $tree; + } + $res = $this->getCachedBlobInfo($details); + $toapp = array(); + foreach ($details as $blob => $idx) { + if (isset($res[$blob])) { + $tree[$idx]->date = $res[$blob]->date; + $tree[$idx]->log = $res[$blob]->title; + $tree[$idx]->author = $res[$blob]->author; + } else { + $toapp[$blob] = $idx; + } + } + if (count($toapp)) { + $res = $this->appendBlobInfoCache($toapp); + foreach ($details as $blob => $idx) { + if (isset($res[$blob])) { + $tree[$idx]->date = $res[$blob]->date; + $tree[$idx]->log = $res[$blob]->title; + $tree[$idx]->author = $res[$blob]->author; + } + } + } + return $tree; + } + + /** + * Append build info cache. + * + * The append method tries to get only the necessary details, so + * instead of going through all the commits one at a time, it will + * try to find a smarter way with regex. + * + * @see self::buildBlobInfoCache + * + * @param array The blob for which we need the information + * @return array The information + */ + public function appendBlobInfoCache($blobs) + { + $rawlog = array(); + $cmd = Pluf::f('idf_exec_cmd_prefix', '') + .sprintf('GIT_DIR=%s '.Pluf::f('git_path', 'git').' log --raw --abbrev=40 --pretty=oneline -5000 --skip=%%s', + escapeshellarg($this->repo)); + $skip = 0; + $res = array(); + self::exec('IDF_Scm_Git::appendBlobInfoCache', + sprintf($cmd, $skip), $rawlog); + while (count($rawlog) and count($blobs)) { + $rawlog = implode("\n", array_reverse($rawlog)); + foreach ($blobs as $blob => $idx) { + if (preg_match('/^\:\d{6} \d{6} [0-9a-f]{40} ' + .$blob.' .*^([0-9a-f]{40})/msU', + $rawlog, $matches)) { + $fc = $this->getCommit($matches[1]); + $res[$blob] = (object) array('hash' => $blob, + 'date' => $fc->date, + 'title' => $fc->title, + 'author' => $fc->author); + unset($blobs[$blob]); + } + } + $rawlog = array(); + $skip += 5000; + if ($skip > 20000) { + // We are in the case of the import of a big old + // repository, we can store as unknown the commit info + // not to try to retrieve them each time. + foreach ($blobs as $blob => $idx) { + $res[$blob] = (object) array('hash' => $blob, + 'date' => '0', + 'title' => '----', + 'author' => 'Unknown'); + } + break; + } + self::exec('IDF_Scm_Git::appendBlobInfoCache', + sprintf($cmd, $skip), $rawlog); + } + $this->cacheBlobInfo($res); + return $res; + } + + /** + * Build the blob info cache. + * + * We build the blob info cache 500 commits at a time. + */ + public function buildBlobInfoCache() + { + $rawlog = array(); + $cmd = Pluf::f('idf_exec_cmd_prefix', '') + .sprintf('GIT_DIR=%s '.Pluf::f('git_path', 'git').' log --raw --abbrev=40 --pretty=oneline -500 --skip=%%s', + escapeshellarg($this->repo)); + $skip = 0; + self::exec('IDF_Scm_Git::buildBlobInfoCache', + sprintf($cmd, $skip), $rawlog); + while (count($rawlog)) { + $commit = ''; + $data = array(); + foreach ($rawlog as $line) { + if (substr($line, 0, 1) != ':') { + $commit = $this->getCommit(substr($line, 0, 40)); + continue; + } + $blob = substr($line, 56, 40); + $data[] = (object) array('hash' => $blob, + 'date' => $commit->date, + 'title' => $commit->title, + 'author' => $commit->author); + } + $this->cacheBlobInfo($data); + $rawlog = array(); + $skip += 500; + self::exec('IDF_Scm_Git::buildBlobInfoCache', + sprintf($cmd, $skip), $rawlog); + } + } + + /** + * Get blob info. + * + * When we display the tree, we want to know when a given file was + * created, who was the author and at which date. This is a very + * slow operation for git as we need to go through the full + * history, find when then blob was introduced, then grab the + * corresponding commit. This is why we need a cache. + * + * @param array List as keys of blob hashs to get info for + * @return array Hash indexed results, when not found not set + */ + public function getCachedBlobInfo($hashes) + { + $cache = new IDF_Scm_Cache_Git(); + $cache->_project = $this->project; + return $cache->retrieve(array_keys($hashes)); + } + + /** + * Cache blob info. + * + * Given a series of blob info, cache them. + * + * @param array Blob info + * @return bool Success + */ + public function cacheBlobInfo($info) + { + $cache = new IDF_Scm_Cache_Git(); + $cache->_project = $this->project; + return $cache->store($info); + } + + public function getFileCachedBlobInfo($hashes) + { + $res = array(); + $cache = Pluf::f('tmp_folder').'/IDF_Scm_Git-'.md5($this->repo).'.cache.db'; + if (!file_exists($cache)) { + return $res; + } + $data = file_get_contents($cache); + if (false === $data) { + return $res; + } + $data = explode(chr(30), $data); + foreach ($data as $rec) { + if (isset($hashes[substr($rec, 0, 40)])) { + $tmp = explode(chr(31), substr($rec, 40), 3); + $res[substr($rec, 0, 40)] = + (object) array('hash' => substr($rec, 0, 40), + 'date' => $tmp[0], + 'title' => $tmp[2], + 'author' => $tmp[1]); + } + } + return $res; + } + + /** + * File cache blob info. + * + * Given a series of blob info, cache them. + * + * @param array Blob info + * @return bool Success + */ + public function fileCacheBlobInfo($info) + { + // Prepare the data + $data = array(); + foreach ($info as $file) { + $data[] = $file->hash.$file->date.chr(31).$file->author.chr(31).$file->title; + } + $data = implode(chr(30), $data).chr(30); + $cache = Pluf::f('tmp_folder').'/IDF_Scm_Git-'.md5($this->repo).'.cache.db'; + $fp = fopen($cache, 'ab'); + if ($fp) { + flock($fp, LOCK_EX); + fwrite($fp, $data, strlen($data)); + fclose($fp); // releases the lock too + return true; + } + return false; + } + + public function repository($request, $match) + { + // authenticate: authenticate connection through "extra" password + if (isset($_SERVER['HTTP_AUTHORIZATION']) && $_SERVER['HTTP_AUTHORIZATION'] != '') + list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) = explode(':' , base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6))); + + if (isset($_SERVER['PHP_AUTH_USER'])) { + $sql = new Pluf_SQL('login=%s', array($_SERVER['PHP_AUTH_USER'])); + $users = Pluf::factory('Pluf_User')->getList(array('filter'=>$sql->gen())); + if ((count($users) == 1) && ($users[0]->active)) { + $user = $users[0]; + $realkey = substr(sha1($user->password.Pluf::f('secret_key')), 0, 8); + if ($_SERVER['PHP_AUTH_PW'] == $realkey) { + $request->user = $user; + } + } + } + + if (IDF_Precondition::accessSource($request) !== true) { + $response = new Pluf_HTTP_Response(""); + $response->status_code = 401; + $response->headers['WWW-Authenticate']='Basic realm="git for '.$this->project.'"'; + return $response; + } + + $path = $match[2]; + + // update files before delivering them + if (($path == 'objects/info/pack') || ($path == 'info/refs')) { + $cmd = sprintf(Pluf::f('idf_exec_cmd_prefix', ''). + 'GIT_DIR=%s '.Pluf::f('git_path', 'git').' update-server-info -f', + escapeshellarg($this->repo)); + self::shell_exec('IDF_Scm_Git::repository', $cmd); + } + + // smart HTTP discovery + if (($path == 'info/refs') && + (array_key_exists('service', $request->GET))){ + $service = $request->GET["service"]; + switch ($service) { + case 'git-upload-pack': + case 'git-receive-pack': + $content = sprintf('%04x',strlen($service)+15). + '# service='.$service."\n0000"; + $content .= self::shell_exec('IDF_Scm_Git::repository', + $service.' --stateless-rpc --advertise-refs '. + $this->repo); + $response = new Pluf_HTTP_Response($content, + 'application/x-'.$service.'-advertisement'); + return $response; + default: + throw new Exception('unknown service: '.$service); + } + } + + switch($path) { + // smart HTTP RPC + case 'git-upload-pack': + case 'git-receive-pack': + $response = new Pluf_HTTP_Response_CommandPassThru($path. + ' --stateless-rpc '.$this->repo, + 'application/x-'.$path.'-result'); + $response->addStdin('php://input'); + return $response; + + // regular file + default: + // make sure we're inside the repo hierarchy (ie. no break-out) + if (is_file($this->repo.'/'.$path) && + strpos(realpath($this->repo.'/'.$path), $this->repo.'/') == 0) { + return new Pluf_HTTP_Response_File($this->repo.'/'.$path, + 'application/octet-stream'); + } else { + return new Pluf_HTTP_Response_NotFound($request); + } + } + } +} diff --git a/indefero/src/IDF/Scm/Mercurial.php b/indefero/src/IDF/Scm/Mercurial.php new file mode 100644 index 0000000..484f3a2 --- /dev/null +++ b/indefero/src/IDF/Scm/Mercurial.php @@ -0,0 +1,611 @@ +file = tempnam(Pluf::f('tmp_folder'), 'hg-log-style-'); + + if ($type == self::FULL_LOG) { + $style = 'changeset = "' + . 'changeset: {node|short}\n' + . 'branch: {branch}\n' + . 'author: {author}\n' + . 'date: {date|isodate}\n' + . 'parents: {parents}\n\n' + . '{desc}\n' + . '\0\n"' + . "\n" + . 'parent = "{node|short} "' + . "\n"; + } elseif ($type == self::CHANGES) { + $style = 'changeset = "' + . 'file_mods: {file_mods}\n' + . 'file_adds: {file_adds}\n' + . 'file_dels: {file_dels}\n' + . 'file_copies: {file_copies}\n\n' + . '\0\n"' + . "\n" + . 'file_mod = "{file_mod}\0"' + . "\n" + . 'file_add = "{file_add}\0"' + . "\n" + . 'file_del = "{file_del}\0"' + . "\n" + . 'file_copy = "{source}\0{name}\0"' + . "\n"; + } else { + throw new IDF_Scm_Exception('invalid type ' . $type); + } + + file_put_contents($this->file, $style); + } + + public function __destruct() + { + @unlink($this->file); + } + + public function get() + { + return $this->file; + } +} + +/** + * Main SCM class for Mercurial + * + * Note: Some commands take a --debug option, this is not lousy coding, but + * totally wanted, as hg returns additional / different data in this + * mode on which this largely depends. + */ +class IDF_Scm_Mercurial extends IDF_Scm +{ + public function __construct($repo, $project=null) + { + $this->repo = $repo; + $this->project = $project; + } + + public function getRepositorySize() + { + $cmd = Pluf::f('idf_exec_cmd_prefix', '').'du -sk ' + .escapeshellarg($this->repo); + $out = explode(' ', + self::shell_exec('IDF_Scm_Mercurial::getRepositorySize', + $cmd), + 2); + return (int) $out[0]*1024; + } + + public static function factory($project) + { + $rep = sprintf(Pluf::f('mercurial_repositories'), $project->shortname); + return new IDF_Scm_Mercurial($rep, $project); + } + + public function isAvailable() + { + try { + $branches = $this->getBranches(); + } catch (IDF_Scm_Exception $e) { + return false; + } + return (count($branches) > 0); + } + + public function findAuthor($author) + { + // We extract the email. + $match = array(); + if (!preg_match('/<(.*)>/', $author, $match)) { + return null; + } + return Pluf::factory('IDF_EmailAddress')->get_user_for_email_address($match[1]); + } + + public function getMainBranch() + { + return 'tip'; + } + + public static function getAnonymousAccessUrl($project, $commit=null) + { + return sprintf(Pluf::f('mercurial_remote_url'), $project->shortname); + } + + public static function getAuthAccessUrl($project, $user, $commit=null) + { + return sprintf(Pluf::f('mercurial_remote_url'), $project->shortname); + } + + public function validateRevision($rev) + { + $cmd = sprintf(Pluf::f('hg_path', 'hg').' log -R %s -r %s', + escapeshellarg($this->repo), + escapeshellarg($rev)); + $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; + self::exec('IDF_Scm_Mercurial::validateRevision', $cmd, $out, $ret); + + // FIXME: apparently a given hg revision can also be ambigious - + // handle this case here sometime + if ($ret == 0 && count($out) > 0) + return IDF_Scm::REVISION_VALID; + return IDF_Scm::REVISION_INVALID; + } + + /** + * Test a given object hash. + * + * @param string Object hash. + * @param null to be svn client compatible + * @return mixed false if not valid or 'blob', 'tree', 'commit' + */ + public function testHash($hash, $dummy=null) + { + $cmd = sprintf(Pluf::f('hg_path', 'hg').' log -R %s -r %s', + escapeshellarg($this->repo), + escapeshellarg($hash)); + $ret = 0; + $out = array(); + $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; + self::exec('IDF_Scm_Mercurial::testHash', $cmd, $out, $ret); + return ($ret != 0) ? false : 'commit'; + } + + public function getTree($commit, $folder='/', $branch=null) + { + // now we grab the info about this commit including its tree. + $folder = ($folder == '/') ? '' : $folder; + $co = $this->getCommit($commit); + if ($folder) { + // As we are limiting to a given folder, we need to find + // the tree corresponding to this folder. + $found = false; + foreach ($this->getTreeInfo($co->tree, true, '', true) as $file) { + if ($file->type == 'tree' and $file->file == $folder) { + $found = true; + break; + } + } + if (!$found) { + throw new Exception(sprintf(__('Folder %1$s not found in commit %2$s.'), $folder, $commit)); + } + } + $res = $this->getTreeInfo($commit, $recurse=true, $folder); + return $res; + } + + /** + * Get the tree info. + * + * @param string Tree hash + * @param bool Do we recurse in subtrees (true) + * @return array Array of file information. + */ + public function getTreeInfo($tree, $recurse=true, $folder='', $root=false) + { + if ('commit' != $this->testHash($tree)) { + throw new Exception(sprintf(__('Not a valid tree: %s.'), $tree)); + } + $cmd_tmpl = Pluf::f('hg_path', 'hg').' manifest -R %s --debug -r %s'; + $cmd = sprintf($cmd_tmpl, escapeshellarg($this->repo), + escapeshellarg($tree)); + $out = array(); + $res = array(); + $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; + self::exec('IDF_Scm_Mercurial::getTreeInfo', $cmd, $out); + $tmp_hack = array(); + while (null !== ($line = array_pop($out))) { + list($hash, $perm, $exec, $file) = preg_split('/ |\t/', $line, 4); + $file = trim($file); + $dir = explode('/', $file, -1); + $tmp = ''; + for ($i=0, $n=count($dir); $i<$n; $i++) { + if ($i > 0) { + $tmp .= '/'; + } + $tmp .= $dir[$i]; + if (!isset($tmp_hack["empty\t000\t\t$tmp/"])) { + $out[] = "empty\t000\t\t$tmp/"; + $tmp_hack["empty\t000\t\t$tmp/"] = 1; + } + } + if (preg_match('/^(.*)\/$/', $file, $match)) { + $type = 'tree'; + $file = $match[1]; + } else { + $type = 'blob'; + } + if (!$root and !$folder and preg_match('/^.*\/.*$/', $file)) { + continue; + } + if ($folder) { + preg_match('|^'.$folder.'[/]?([^/]+)?$|', $file,$match); + if (count($match) > 1) { + $file = $match[1]; + } else { + continue; + } + } + $fullpath = ($folder) ? $folder.'/'.$file : $file; + $efullpath = self::smartEncode($fullpath); + $res[] = (object) array('perm' => $perm, 'type' => $type, + 'hash' => $hash, 'fullpath' => $fullpath, + 'efullpath' => $efullpath, 'file' => $file); + } + return $res; + } + + public function getPathInfo($totest, $commit='tip') + { + $cmd_tmpl = Pluf::f('hg_path', 'hg').' manifest -R %s --debug -r %s'; + $cmd = sprintf($cmd_tmpl, escapeshellarg($this->repo), + escapeshellarg($commit)); + $out = array(); + $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; + self::exec('IDF_Scm_Mercurial::getPathInfo', $cmd, $out); + $tmp_hack = array(); + while (null !== ($line = array_pop($out))) { + list($hash, $perm, $exec, $file) = preg_split('/ |\t/', $line, 4); + $file = trim($file); + $dir = explode('/', $file, -1); + $tmp = ''; + for ($i=0, $n=count($dir); $i<$n; $i++) { + if ($i > 0) { + $tmp .= '/'; + } + $tmp .= $dir[$i]; + if ($tmp == $totest) { + $pathinfo = pathinfo($totest); + return (object) array('perm' => '000', 'type' => 'tree', + 'hash' => $hash, + 'fullpath' => $totest, + 'file' => $pathinfo['basename'], + 'commit' => $commit + ); + } + if (!isset($tmp_hack["empty\t000\t\t$tmp/"])) { + $out[] = "empty\t000\t\t$tmp/"; + $tmp_hack["empty\t000\t\t$tmp/"] = 1; + } + } + if (preg_match('/^(.*)\/$/', $file, $match)) { + $type = 'tree'; + $file = $match[1]; + } else { + $type = 'blob'; + } + if ($totest == $file) { + $pathinfo = pathinfo($totest); + return (object) array('perm' => $perm, 'type' => $type, + 'hash' => $hash, + 'fullpath' => $totest, + 'file' => $pathinfo['basename'], + 'commit' => $commit + ); + } + } + return false; + } + + public function getFile($def, $cmd_only=false) + { + $cmd = sprintf(Pluf::f('hg_path', 'hg').' cat -R %s -r %s %s', + escapeshellarg($this->repo), + escapeshellarg($def->commit), + escapeshellarg($this->repo.'/'.$def->fullpath)); + $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; + return ($cmd_only) ? + $cmd : self::shell_exec('IDF_Scm_Mercurial::getFile', $cmd); + } + + /** + * Get the branches. + * + * @return array Branches. + */ + public function getBranches() + { + if (isset($this->cache['branches'])) { + return $this->cache['branches']; + } + $out = array(); + $cmd = sprintf(Pluf::f('hg_path', 'hg').' branches -R %s', + escapeshellarg($this->repo)); + $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; + self::exec('IDF_Scm_Mercurial::getBranches', $cmd, $out); + $res = array(); + foreach ($out as $b) { + preg_match('/(.+?)\s+\S+:(\S+)/', $b, $match); + $res[$match[1]] = ''; + } + $this->cache['branches'] = $res; + return $res; + } + + /** + * Get the tags. + * + * @return array Tags. + */ + public function getTags() + { + if (isset($this->cache['tags'])) { + return $this->cache['tags']; + } + $out = array(); + $cmd = sprintf(Pluf::f('hg_path', 'hg').' tags -R %s', + escapeshellarg($this->repo)); + $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; + self::exec('IDF_Scm_Mercurial::getTags', $cmd, $out); + $res = array(); + foreach ($out as $b) { + preg_match('/(.+?)\s+\S+:(\S+)/', $b, $match); + $res[$match[1]] = ''; + } + $this->cache['tags'] = $res; + return $res; + } + + public function inBranches($commit, $path) + { + return (in_array($commit, array_keys($this->getBranches()))) + ? array($commit) : array(); + } + + public function inTags($commit, $path) + { + return (in_array($commit, array_keys($this->getTags()))) + ? array($commit) : array(); + } + + /** + * Get commit details. + * + * @param string Commit ('HEAD') + * @param bool Get commit diff (false) + * @return array Changes + */ + public function getCommit($commit, $getdiff=false) + { + if ($this->validateRevision($commit) != IDF_Scm::REVISION_VALID) { + return false; + } + + $logStyle = new IDF_Scm_Mercurial_LogStyle(IDF_Scm_Mercurial_LogStyle::FULL_LOG); + $tmpl = ($getdiff) + ? Pluf::f('hg_path', 'hg').' log --debug -p -r %s -R %s --style %s' + : Pluf::f('hg_path', 'hg').' log --debug -r %s -R %s --style %s'; + $cmd = sprintf($tmpl, + escapeshellarg($commit), + escapeshellarg($this->repo), + escapeshellarg($logStyle->get())); + $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; + $out = self::shell_exec('IDF_Scm_Mercurial::getCommit', $cmd); + if (strlen($out) == 0) { + return false; + } + + $diffStart = strpos($out, 'diff -r'); + $diff = ''; + if ($diffStart !== false) { + $log = substr($out, 0, $diffStart); + $diff = substr($out, $diffStart); + } else { + $log = $out; + } + + $out = self::parseLog(preg_split('/\r\n|\n/', $log)); + $out[0]->diff = $diff; + return $out[0]; + } + + /** + * @see IDF_Scm::getChanges() + */ + public function getChanges($commit) + { + if ($this->validateRevision($commit) != IDF_Scm::REVISION_VALID) { + return null; + } + + $logStyle = new IDF_Scm_Mercurial_LogStyle(IDF_Scm_Mercurial_LogStyle::CHANGES); + $tmpl = Pluf::f('hg_path', 'hg').' log --debug -r %s -R %s --style %s'; + $cmd = sprintf($tmpl, + escapeshellarg($commit), + escapeshellarg($this->repo), + escapeshellarg($logStyle->get())); + $out = array(); + $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; + self::exec('IDF_Scm_Mercurial::getChanges', $cmd, $out); + $log = self::parseLog($out); + // we expect only one log entry that contains all the needed information + $log = $log[0]; + + $return = (object) array( + 'additions' => preg_split('/\0/', $log->file_adds, -1, PREG_SPLIT_NO_EMPTY), + 'deletions' => preg_split('/\0/', $log->file_dels, -1, PREG_SPLIT_NO_EMPTY), + 'patches' => preg_split('/\0/', $log->file_mods, -1, PREG_SPLIT_NO_EMPTY), + // hg has no support for built-in attributes, so this keeps empty + 'properties' => array(), + // these two are filled below + 'copies' => array(), + 'renames' => array(), + ); + + $file_copies = preg_split('/\0/', $log->file_copies, -1, PREG_SPLIT_NO_EMPTY); + + // copies are treated as renames if they have an add _and_ a drop; + // only if they only have an add, but no drop, they're treated as copies + for ($i=0; $ideletions); + $trgidx = array_search($trg, $return->additions); + if ($srcidx !== false && $trgidx !== false) { + $return->renames[$src] = $trg; + unset($return->deletions[$srcidx]); + unset($return->additions[$trgidx]); + continue; + } + if ($srcidx === false && $trgidx !== false) { + $return->copies[$src] = $trg; + unset($return->additions[$trgidx]); + continue; + } + // file sutures (counter-operation to copy) not supported + } + + return $return; + } + + /** + * Check if a commit is big. + * + * @param string Commit ('HEAD') + * @return bool The commit is big + */ + public function isCommitLarge($commit='HEAD') + { + return false; + } + + /** + * Get latest changes. + * + * @param string Commit ('HEAD'). + * @param int Number of changes (10). + * @return array Changes. + */ + public function getChangeLog($commit='tip', $n=10) + { + $logStyle = new IDF_Scm_Mercurial_LogStyle(IDF_Scm_Mercurial_LogStyle::FULL_LOG); + + // hg accepts revision IDs as arguments to --branch / -b as well and + // uses the branch of the revision in question to filter the other + // revisions + $cmd = sprintf(Pluf::f('hg_path', 'hg').' log --debug -R %s -l%s --style %s -b %s', + escapeshellarg($this->repo), + $n, + escapeshellarg($logStyle->get()), + escapeshellarg($commit)); + $out = array(); + $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; + self::exec('IDF_Scm_Mercurial::getChangeLog', $cmd, $out); + return self::parseLog($out); + } + + /** + * Parse the log lines of our custom style format. + * + * @param array Lines. + * @return array Change log. + */ + public static function parseLog($lines) + { + $res = array(); + $c = array(); + $headers_processed = false; + foreach ($lines as $line) { + if ($line == "\0") { + $headers_processed = false; + if (count($c) > 0) { + if (array_key_exists('full_message', $c)) + $c['full_message'] = trim($c['full_message']); + $res[] = (object) $c; + } + continue; + } + if (!$headers_processed && empty($line)) { + $headers_processed = true; + continue; + } + if (!$headers_processed && preg_match('/^(\S+):\s*(.*)/', $line, $match)) { + $match[1] = strtolower($match[1]); + if ($match[1] == 'changeset') { + $c = array(); + $c['commit'] = $match[2]; + $c['tree'] = $c['commit']; + $c['full_message'] = ''; + } elseif ($match[1] == 'author') { + $c['author'] = $match[2]; + } elseif ($match[1] == 'branch') { + $c['branch'] = empty($match[2]) ? 'default' : $match[2]; + } elseif ($match[1] == 'parents') { + $parents = preg_split('/\s+/', $match[2], -1, PREG_SPLIT_NO_EMPTY); + for ($i=0, $j=count($parents); $i<$j; ++$i) { + if ($parents[$i] == '000000000000') + unset($parents[$i]); + } + $c['parents'] = $parents; + } else { + $c[$match[1]] = trim($match[2]); + } + if ($match[1] == 'date') { + $c['date'] = gmdate('Y-m-d H:i:s', strtotime($match[2])); + } + continue; + } + if ($headers_processed) { + if (empty($c['title'])) + $c['title'] = trim($line); + else + $c['full_message'] .= trim($line)."\n"; + continue; + } + } + return $res; + } + + /** + * Generate a zip archive at a given commit. + * + * @param string Commit + * @param string Prefix ('git-repo-dump') + * @return Pluf_HTTP_Response The HTTP response containing the zip archive + */ + public function getArchiveStream($commit, $prefix='') + { + $cmd = sprintf(Pluf::f('idf_exec_cmd_prefix', ''). + Pluf::f('hg_path', 'hg').' archive --type=zip -R %s -r %s -', + escapeshellarg($this->repo), + escapeshellarg($commit)); + return new Pluf_HTTP_Response_CommandPassThru($cmd, 'application/x-zip'); + } + + /** + * @see IDF_Scm::getDiffPathStripLevel() + */ + public function getDiffPathStripLevel() + { + return 1; + } +} diff --git a/indefero/src/IDF/Scm/Monotone.php b/indefero/src/IDF/Scm/Monotone.php new file mode 100644 index 0000000..63f40e3 --- /dev/null +++ b/indefero/src/IDF/Scm/Monotone.php @@ -0,0 +1,819 @@ + + */ +class IDF_Scm_Monotone extends IDF_Scm +{ + /** the minimum supported interface version */ + public static $MIN_INTERFACE_VERSION = 13.0; + + private static $instances = array(); + + private $stdio; + + /** + * Constructor + */ + public function __construct(IDF_Project $project, IDF_Scm_Monotone_IStdio $stdio) + { + $this->project = $project; + $this->stdio = $stdio; + } + + /** + * Returns the stdio instance in use + * + * @return IDF_Scm_Monotone_Stdio + */ + public function getStdio() + { + return $this->stdio; + } + + /** + * @see IDF_Scm::getRepositorySize() + */ + public function getRepositorySize() + { + // FIXME: this obviously won't work with remote databases - upstream + // needs to implement mtn db info in automate at first + $repo = sprintf(Pluf::f('mtn_repositories'), $this->project->shortname); + if (!file_exists($repo)) { + return 0; + } + + $cmd = Pluf::f('idf_exec_cmd_prefix', '').'du -sk ' + .escapeshellarg($repo); + $out = explode(' ', + self::shell_exec('IDF_Scm_Monotone::getRepositorySize', $cmd), + 2); + return (int) $out[0]*1024; + } + + /** + * @see IDF_Scm::isAvailable() + */ + public function isAvailable() + { + try + { + $out = $this->stdio->exec(array('interface_version')); + return floatval($out) >= self::$MIN_INTERFACE_VERSION; + } + catch (IDF_Scm_Exception $e) {} + + return false; + } + + /** + * @see IDF_Scm::getBranches() + */ + public function getBranches() + { + if (isset($this->cache['branches'])) { + return $this->cache['branches']; + } + // FIXME: we could / should introduce handling of suspended + // (i.e. dead) branches here by hiding them from the user's eye... + $out = $this->stdio->exec(array('branches')); + + // note: we could expand each branch with one of its head revisions + // here, but these would soon become bogus anyway and we cannot + // map multiple head revisions here either, so we just use the + // selector as placeholder + $res = array(); + foreach (preg_split("/\n/", $out, -1, PREG_SPLIT_NO_EMPTY) as $b) { + $res["h:$b"] = $b; + } + + $this->cache['branches'] = $res; + return $res; + } + + /** + * monotone has no concept of a "main" branch, so just return + * the configured one. Ensure however that we can select revisions + * with it at all. + * + * @see IDF_Scm::getMainBranch() + */ + public function getMainBranch() + { + $conf = $this->project->getConf(); + if (false === ($branch = $conf->getVal('mtn_master_branch', false)) + || empty($branch)) { + $branch = "*"; + } + + return $branch; + } + + /** + * @see IDF_Scm::getArchiveStream + */ + public function getArchiveStream($commit, $prefix = null) + { + $revs = $this->_resolveSelector($commit); + // sanity: this should actually not happen, because the + // revision is validated before already + if (count($revs) == 0) { + throw new IDF_Scm_Exception("$commit is not a valid revision"); + } + return new IDF_Scm_Monotone_ZipRender($this->stdio, $revs[0]); + } + + /** + * expands a selector or a partial revision id to zero, one or + * multiple 40 byte revision ids + * + * @param string $selector + * @return array + */ + private function _resolveSelector($selector) + { + $out = $this->stdio->exec(array('select', $selector)); + return preg_split("/\n/", $out, -1, PREG_SPLIT_NO_EMPTY); + } + + /** + * Queries the certs for a given revision and returns them in an + * associative array array("branch" => array("branch1", ...), ...) + * + * @param string + * @param array + */ + private function _getCerts($rev) + { + $cache = Pluf_Cache::factory(); + $cachekey = 'mtn-plugin-certs-for-rev-' . $rev; + $certs = $cache->get($cachekey); + + if ($certs === null) { + $out = $this->stdio->exec(array('certs', $rev)); + + $stanzas = IDF_Scm_Monotone_BasicIO::parse($out); + $certs = array(); + foreach ($stanzas as $stanza) { + $certname = null; + foreach ($stanza as $stanzaline) { + // luckily, name always comes before value + if ($stanzaline['key'] == 'name') { + $certname = $stanzaline['values'][0]; + continue; + } + + if ($stanzaline['key'] == 'value') { + if (!array_key_exists($certname, $certs)) { + $certs[$certname] = array(); + } + + $certs[$certname][] = $stanzaline['values'][0]; + break; + } + } + } + $cache->set($cachekey, $certs); + } + + return $certs; + } + + /** + * Returns unique certificate values for the given revs and the specific + * cert name, optionally prefixed with $prefix + * + * @param array + * @param string + * @param string + * @return array + */ + private function _getUniqueCertValuesFor($revs, $certName, $prefix) + { + $certValues = array(); + foreach ($revs as $rev) { + $certs = $this->_getCerts($rev); + if (!array_key_exists($certName, $certs)) + continue; + foreach ($certs[$certName] as $certValue) { + $certValues[] = "$prefix$certValue"; + } + } + return array_unique($certValues); + } + + /** + * @see IDF_Scm::inBranches() + */ + public function inBranches($commit, $path) + { + $revs = $this->_resolveSelector($commit); + if (count($revs) == 0) return array(); + return $this->_getUniqueCertValuesFor($revs, 'branch', 'h:'); + } + + /** + * @see IDF_Scm::getTags() + */ + public function getTags() + { + if (isset($this->cache['tags'])) { + return $this->cache['tags']; + } + + $out = $this->stdio->exec(array('tags')); + + $tags = array(); + $stanzas = IDF_Scm_Monotone_BasicIO::parse($out); + foreach ($stanzas as $stanza) { + $tagname = null; + foreach ($stanza as $stanzaline) { + // revision comes directly after the tag stanza + if ($stanzaline['key'] == 'tag') { + $tagname = $stanzaline['values'][0]; + continue; + } + if ($stanzaline['key'] == 'revision') { + // FIXME: warn if multiple revisions have + // equally named tags + if (!array_key_exists("t:$tagname", $tags)) { + $tags["t:$tagname"] = $tagname; + } + break; + } + } + } + + $this->cache['tags'] = $tags; + return $tags; + } + + /** + * @see IDF_Scm::inTags() + */ + public function inTags($commit, $path) + { + $revs = $this->_resolveSelector($commit); + if (count($revs) == 0) return array(); + return $this->_getUniqueCertValuesFor($revs, 'tag', 't:'); + } + + /** + * Takes a single stanza coming from an extended manifest output + * and converts it into a file structure used by IDF + * + * @param string $forceBasedir If given then the element's path is checked + * to be directly beneath the given directory. + * If not, null is returned and the parsing is + * aborted. + * @return array | null + */ + private function _fillFileEntry(array $manifestEntry, $forceBasedir = null) + { + $fullpath = $manifestEntry[0]['values'][0]; + $filename = basename($fullpath); + $dirname = dirname($fullpath); + $dirname = $dirname == '.' ? '' : $dirname; + + if ($forceBasedir !== null && $forceBasedir != $dirname) { + return null; + } + + $file = array(); + $file['file'] = $filename; + $file['fullpath'] = $fullpath; + $file['efullpath'] = self::smartEncode($fullpath); + + $wanted_mark = ''; + if ($manifestEntry[0]['key'] == 'dir') { + $file['type'] = 'tree'; + $file['size'] = 0; + $wanted_mark = 'path_mark'; + } + else { + $file['type'] = 'blob'; + $file['hash'] = $manifestEntry[1]['hash']; + $size = 0; + foreach ($manifestEntry as $line) { + if ($line['key'] == 'size') { + $size = $line['values'][0]; + break; + } + } + $file['size'] = $size; + $wanted_mark = 'content_mark'; + } + + $rev_mark = null; + foreach ($manifestEntry as $line) { + if ($line['key'] == $wanted_mark) { + $rev_mark = $line['hash']; + break; + } + } + + if ($rev_mark !== null) { + $file['rev'] = $rev_mark; + $certs = $this->_getCerts($rev_mark); + + // FIXME: this assumes that author, date and changelog are always given + $file['author'] = implode(", ", $certs['author']); + + $dates = array(); + foreach ($certs['date'] as $date) + $dates[] = date('Y-m-d H:i:s', strtotime($date)); + $file['date'] = implode(', ', $dates); + $combinedChangelog = implode("\n---\n", $certs['changelog']); + $split = preg_split("/[\n\r]/", $combinedChangelog, 2); + // FIXME: the complete log message is currently not used in the + // tree view (the same is true for the other SCM implementations) + // but we _should_ really use or at least return that here + // in case we want to do fancy stuff like described in + // issue 492 + $file['log'] = $split[0]; + } + + return $file; + } + + /** + * @see IDF_Scm::getTree() + */ + public function getTree($commit, $folder='/', $branch=null) + { + $revs = $this->_resolveSelector($commit); + if (count($revs) == 0) { + return array(); + } + + $out = $this->stdio->exec(array( + 'get_extended_manifest_of', $revs[0] + )); + + $files = array(); + $stanzas = IDF_Scm_Monotone_BasicIO::parse($out); + $folder = $folder == '/' || empty($folder) ? '' : $folder; + + foreach ($stanzas as $stanza) { + if ($stanza[0]['key'] == 'format_version') + continue; + + $file = $this->_fillFileEntry($stanza, $folder); + if ($file === null) + continue; + + $files[] = (object) $file; + } + return $files; + } + + /** + * @see IDF_Scm::findAuthor() + */ + public function findAuthor($author) + { + // We extract anything which looks like an email. + $match = array(); + if (!preg_match('/([^ ]+@[^ ]+)/', $author, $match)) { + return null; + } + $sql = new Pluf_SQL('login=%s', array($match[1])); + $users = Pluf::factory('Pluf_User')->getList(array('filter'=>$sql->gen())); + if ($users->count() > 0) { + return $users[0]; + } + return Pluf::factory('IDF_EmailAddress')->get_user_for_email_address($match[1]); + } + + /** + * @see IDF_Scm::getAnonymousAccessUrl() + */ + public static function getAnonymousAccessUrl($project, $commit = null) + { + $scm = IDF_Scm::get($project); + $branch = $scm->getMainBranch(); + + if (!empty($commit)) { + $revs = $scm->_resolveSelector($commit); + if (count($revs) > 0) { + $certs = $scm->_getCerts($revs[0]); + // for the very seldom case that a revision + // has no branch certificate + if (!array_key_exists('branch', $certs)) { + $branch = '*'; + } + else + { + $branch = $certs['branch'][0]; + } + } + } + + $remote_url = Pluf::f('mtn_remote_url', ''); + if (empty($remote_url)) { + return ''; + } + + return sprintf($remote_url, $project->shortname).'?'.$branch; + } + + /** + * @see IDF_Scm::getAuthAccessUrl() + */ + public static function getAuthAccessUrl($project, $user, $commit = null) + { + $url = self::getAnonymousAccessUrl($project, $commit); + return preg_replace("#^ssh://#", "ssh://$user@", $url); + } + + /** + * Returns this object correctly initialized for the project. + * + * @param IDF_Project + * @return IDF_Scm_Monotone + */ + public static function factory($project) + { + if (!array_key_exists($project->shortname, self::$instances)) { + $stdio = new IDF_Scm_Monotone_Stdio($project); + self::$instances[$project->shortname] = + new IDF_Scm_Monotone($project, $stdio); + } + return self::$instances[$project->shortname]; + } + + /** + * @see IDF_Scm::validateRevision() + */ + public function validateRevision($commit) + { + $revs = $this->_resolveSelector($commit); + if (count($revs) == 0) + return IDF_Scm::REVISION_INVALID; + + if (count($revs) > 1) + return IDF_Scm::REVISION_AMBIGUOUS; + + return IDF_Scm::REVISION_VALID; + } + + /** + * @see IDF_Scm::disambiguateRevision + */ + public function disambiguateRevision($commit) + { + $revs = $this->_resolveSelector($commit); + + $out = array(); + foreach ($revs as $rev) + { + $certs = $this->_getCerts($rev); + + $log = array(); + $log['author'] = implode(', ', $certs['author']); + + $log['branch'] = implode(', ', $certs['branch']); + + $dates = array(); + foreach ($certs['date'] as $date) + $dates[] = date('Y-m-d H:i:s', strtotime($date)); + $log['date'] = implode(', ', $dates); + + $combinedChangelog = implode("\n---\n", $certs['changelog']); + $split = preg_split("/[\n\r]/", $combinedChangelog, 2); + $log['title'] = $split[0]; + $log['full_message'] = (isset($split[1])) ? trim($split[1]) : ''; + + $log['commit'] = $rev; + + $out[] = (object)$log; + } + + return $out; + } + + /** + * @see IDF_Scm::getPathInfo() + */ + public function getPathInfo($file, $commit = null) + { + if ($commit === null) { + $commit = 'h:' . $this->getMainBranch(); + } + + $revs = $this->_resolveSelector($commit); + if (count($revs) == 0) + return false; + + $out = $this->stdio->exec(array( + 'get_extended_manifest_of', $revs[0] + )); + + $files = array(); + $stanzas = IDF_Scm_Monotone_BasicIO::parse($out); + + foreach ($stanzas as $stanza) { + if ($stanza[0]['values'][0] != $file) + continue; + + $file = $this->_fillFileEntry($stanza); + return (object) $file; + } + return false; + } + + /** + * @see IDF_Scm::getFile() + */ + public function getFile($def, $cmd_only=false) + { + // this won't work with remote databases + if ($cmd_only) { + throw new Pluf_Exception_NotImplemented(); + } + + return $this->stdio->exec(array('get_file', $def->hash)); + } + + /** + * Returns the differences between two revisions as unified diff + * + * @param string The target of the diff + * @param string The source of the diff, if not given, the first + * parent of the target is used + * @return string + */ + private function _getDiff($target, $source = null) + { + if (empty($source)) { + $source = "p:$target"; + } + + // FIXME: add real support for merge revisions here which have + // two distinct diff sets + $targets = $this->_resolveSelector($target); + $sources = $this->_resolveSelector($source); + + if (count($targets) == 0 || count($sources) == 0) { + return ''; + } + + // if target contains a root revision, we cannot produce a diff + if (empty($sources[0])) { + return ''; + } + + return $this->stdio->exec( + array('content_diff'), + array('r' => array($sources[0], $targets[0])) + ); + } + + /** + * @see IDF_Scm::getChanges() + */ + public function getChanges($commit) + { + $revs = $this->_resolveSelector($commit); + if (count($revs) == 0) + return false; + + $revision = $revs[0]; + $out = $this->stdio->exec(array('get_revision', $revision)); + $stanzas = IDF_Scm_Monotone_BasicIO::parse($out); + + $return = (object) array( + 'additions' => array(), + 'deletions' => array(), + 'renames' => array(), + 'copies' => array(), + 'patches' => array(), + 'properties' => array(), + ); + + foreach ($stanzas as $stanza) { + if ($stanza[0]['key'] == 'format_version' || + $stanza[0]['key'] == 'old_revision' || + $stanza[0]['key'] == 'new_manifest') + continue; + + if ($stanza[0]['key'] == 'add_file' || + $stanza[0]['key'] == 'add_dir') { + $return->additions[] = $stanza[0]['values'][0]; + continue; + } + + if ($stanza[0]['key'] == 'delete') { + $return->deletions[] = $stanza[0]['values'][0]; + continue; + } + + if ($stanza[0]['key'] == 'rename') { + $return->renames[$stanza[0]['values'][0]] = + $stanza[1]['values'][0]; + continue; + } + + if ($stanza[0]['key'] == 'patch') { + $return->patches[] = $stanza[0]['values'][0]; + continue; + } + + if ($stanza[0]['key'] == 'clear' || + $stanza[0]['key'] == 'set') { + + $filename = $stanza[0]['values'][0]; + if (!array_key_exists($filename, $return->properties)) { + $return->properties[$filename] = array(); + } + $key = $stanza[1]['values'][0]; + $value = null; + if (isset($stanza[2])) { + $value = $stanza[2]['values'][0]; + } + $return->properties[$filename][$key] = $value; + continue; + } + } + + return $return; + } + + /** + * @see IDF_Scm::getCommit() + */ + public function getCommit($commit, $getdiff=false) + { + $revs = $this->_resolveSelector($commit); + if (count($revs) == 0) + return false; + + $res = array(); + + $parents = $this->stdio->exec(array('parents', $revs[0])); + $res['parents'] = preg_split("/\n/", $parents, -1, PREG_SPLIT_NO_EMPTY); + + $certs = $this->_getCerts($revs[0]); + + // FIXME: this assumes that author, date and changelog are always given + $res['author'] = implode(', ', $certs['author']); + + $dates = array(); + foreach ($certs['date'] as $date) + $dates[] = date('Y-m-d H:i:s', strtotime($date)); + $res['date'] = implode(', ', $dates); + + $combinedChangelog = implode("\n---\n", $certs['changelog']); + $split = preg_split("/[\n\r]/", $combinedChangelog, 2); + $res['title'] = $split[0]; + $res['full_message'] = (isset($split[1])) ? trim($split[1]) : ''; + + $res['branch'] = implode(', ', $certs['branch']); + $res['commit'] = $revs[0]; + + $res['diff'] = ($getdiff) ? $this->_getDiff($revs[0]) : ''; + + return (object) $res; + } + + /** + * @see IDF_Scm::getProperties() + */ + public function getProperties($rev, $path='') + { + $out = $this->stdio->exec(array('interface_version')); + // support for querying file attributes of committed revisions + // was added for mtn 1.1 (interface version 13.1) + if (floatval($out) < 13.1) + return array(); + + $out = $this->stdio->exec(array('get_attributes', $path), array('r' => $rev)); + $stanzas = IDF_Scm_Monotone_BasicIO::parse($out); + $res = array(); + + foreach ($stanzas as $stanza) { + $line = $stanza[0]; + $res[$line['values'][0]] = $line['values'][1]; + } + + return $res; + } + + /** + * @see IDF_Scm::getExtraProperties + */ + public function getExtraProperties($obj) + { + return (isset($obj->parents)) ? array('parents' => $obj->parents) : array(); + } + + /** + * @see IDF_Scm::isCommitLarge() + */ + public function isCommitLarge($commit=null) + { + if (empty($commit)) { + $commit = 'h:'.$this->getMainBranch(); + } + + $revs = $this->_resolveSelector($commit); + if (count($revs) == 0) + return false; + + $out = $this->stdio->exec(array( + 'get_revision', $revs[0] + )); + + $newAndPatchedFiles = 0; + $stanzas = IDF_Scm_Monotone_BasicIO::parse($out); + + foreach ($stanzas as $stanza) { + if ($stanza[0]['key'] == 'patch' || $stanza[0]['key'] == 'add_file') + $newAndPatchedFiles++; + } + + return $newAndPatchedFiles > 100; + } + + /** + * @see IDF_Scm::getChangeLog() + */ + public function getChangeLog($commit=null, $n=10) + { + $horizont = $this->_resolveSelector($commit); + $initialBranches = array(); + $logs = array(); + + while (!empty($horizont) && $n > 0) { + if (count($horizont) > 1) { + $out = $this->stdio->exec(array('toposort') + $horizont); + $horizont = preg_split("/\n/", $out, -1, PREG_SPLIT_NO_EMPTY); + } + + $rev = array_shift($horizont); + $certs = $this->_getCerts($rev); + + // read in the initial branches we should follow + if (count($initialBranches) == 0) { + if (!isset($certs['branch'])) { + // this revision has no branch cert, we cannot start logging + // from this revision + continue; + } + $initialBranches = $certs['branch']; + } + + // only add it to our log if it is on one of the initial branches + // ignore revisions without any branch certificate + if (count(array_intersect($initialBranches, (array)@$certs['branch'])) > 0) { + --$n; + + $log = array(); + $log['author'] = implode(', ', $certs['author']); + + $dates = array(); + foreach ($certs['date'] as $date) + $dates[] = date('Y-m-d H:i:s', strtotime($date)); + $log['date'] = implode(', ', $dates); + + $combinedChangelog = implode("\n---\n", $certs['changelog']); + $split = preg_split("/[\n\r]/", $combinedChangelog, 2); + $log['title'] = $split[0]; + $log['full_message'] = (isset($split[1])) ? trim($split[1]) : ''; + + $log['commit'] = $rev; + + $logs[] = (object)$log; + + $out = $this->stdio->exec(array('parents', $rev)); + $horizont += preg_split("/\n/", $out, -1, PREG_SPLIT_NO_EMPTY); + } + } + + return $logs; + } +} + diff --git a/indefero/src/IDF/Scm/Monotone/BasicIO.php b/indefero/src/IDF/Scm/Monotone/BasicIO.php new file mode 100644 index 0000000..80ca611 --- /dev/null +++ b/indefero/src/IDF/Scm/Monotone/BasicIO.php @@ -0,0 +1,186 @@ + + */ +class IDF_Scm_Monotone_BasicIO +{ + /** + * Parses monotone's basic_io format + * + * Known quirks: + * - does not handle multi-values starting with a hash '[]' (no known output) + * - does not validate hashes (should be /[0-9a-f]{40}/i) + * - does not handle forbidden \0 + * + * @param string $in + * @return array of arrays + */ + public static function parse($in) + { + $pos = 0; + $stanzas = array(); + $length = strlen($in); + + while ($pos < $length) { + $stanza = array(); + while ($pos < $length) { + if ($in[$pos] == "\n") break; + + $stanzaLine = array('key' => '', 'values' => array(), 'hash' => null); + while ($pos < $length) { + $ch = $in[$pos]; + if ($ch == '"' || $ch == '[') break; + ++$pos; + if ($ch == ' ') continue; + $stanzaLine['key'] .= $ch; + } + + // ensure we don't look at a symbol w/o a value list + if ($pos >= $length || $in[$pos] == "\n") { + unset($stanzaLine['values']); + unset($stanzaLine['hash']); + } + else { + if ($in[$pos] == '[') { + unset($stanzaLine['values']); + ++$pos; // opening square bracket + while ($pos < $length && $in[$pos] != ']') { + $stanzaLine['hash'] .= $in[$pos]; + ++$pos; + } + ++$pos; // closing square bracket + } + else + { + unset($stanzaLine['hash']); + $valCount = 0; + // if hashs and plain values are encountered in the same + // value list, we add the hash values as simple values as well + while ($in[$pos] == '"' || $in[$pos] == '[') { + $isHashValue = $in[$pos] == '['; + ++$pos; // opening quote / bracket + $stanzaLine['values'][$valCount] = ''; + while ($pos < $length) { + $ch = $in[$pos]; $pr = $in[$pos-1]; + if (($isHashValue && $ch == ']') + ||(!$isHashValue && $ch == '"' && $pr != '\\')) + break; + ++$pos; + $stanzaLine['values'][$valCount] .= $ch; + } + ++$pos; // closing quote + + if (!$isHashValue) { + $stanzaLine['values'][$valCount] = str_replace( + array("\\\\", "\\\""), + array("\\", "\""), + $stanzaLine['values'][$valCount] + ); + } + + if ($pos >= $length) + break; + + if ($in[$pos] == ' ') { + ++$pos; // space + ++$valCount; + } + } + } + } + + $stanza[] = $stanzaLine; + ++$pos; // newline + } + $stanzas[] = $stanza; + ++$pos; // newline + } + return $stanzas; + } + + /** + * Compiles monotone's basicio format + * + * Known quirks: + * - does not validate keys for /[a-z_]+/ + * - does not validate hashes (should be /[0-9a-f]{40}/i) + * - does not support intermixed value / hash formats + * - does not handle forbidden \0 + * + * @param array $in Array of arrays + * @return string + */ + public static function compile($in) + { + $out = ""; + $first = true; + foreach ((array)$in as $sx => $stanza) { + if ($first) + $first = false; + else + $out .= "\n"; + + $maxkeylength = 0; + foreach ((array)$stanza as $lx => $line) { + if (!array_key_exists('key', $line) || empty($line['key'])) { + throw new IDF_Scm_Exception( + '"key" not found in basicio stanza '.$sx.', line '.$lx + ); + } + $maxkeylength = max($maxkeylength, strlen($line['key'])); + } + + foreach ((array)$stanza as $lx => $line) { + $out .= str_pad($line['key'], $maxkeylength, ' ', STR_PAD_LEFT); + + if (array_key_exists('hash', $line)) { + $out .= ' ['.$line['hash'].']'; + } else + if (array_key_exists('values', $line)) { + if (!is_array($line['values']) || count($line['values']) == 0) { + throw new IDF_Scm_Exception( + '"values" must be an array of a size >= 1 '. + 'in basicio stanza '.$sx.', line '.$lx + ); + } + foreach ($line['values'] as $value) { + $out .= ' "'.str_replace( + array("\\", "\""), + array("\\\\", "\\\""), + $value).'"'; + } + } + + $out .= "\n"; + } + } + return $out; + } +} + diff --git a/indefero/src/IDF/Scm/Monotone/IStdio.php b/indefero/src/IDF/Scm/Monotone/IStdio.php new file mode 100644 index 0000000..9e4665f --- /dev/null +++ b/indefero/src/IDF/Scm/Monotone/IStdio.php @@ -0,0 +1,66 @@ + + */ +interface IDF_Scm_Monotone_IStdio +{ + /** + * Constructor + */ + public function __construct(IDF_Project $project); + + /** + * Starts the stdio process and resets the command counter + */ + public function start(); + + /** + * Stops the stdio process and closes all pipes + */ + public function stop(); + + /** + * Executes a command over stdio and returns its result + * + * @param array Array of arguments + * @param array Array of options as key-value pairs. Multiple options + * can be defined in sub-arrays, like + * "r" => array("123...", "456...") + * @return string + */ + public function exec(array $args, array $options = array()); + + /** + * Returns the last out-of-band output for a previously executed + * command as associative array with 'e' (error), 'w' (warning), + * 'p' (progress) and 't' (ticker, unparsed) as keys + * + * @return array + */ + public function getLastOutOfBandOutput(); +} + diff --git a/indefero/src/IDF/Scm/Monotone/Stdio.php b/indefero/src/IDF/Scm/Monotone/Stdio.php new file mode 100644 index 0000000..a9e6c7b --- /dev/null +++ b/indefero/src/IDF/Scm/Monotone/Stdio.php @@ -0,0 +1,405 @@ + + */ +class IDF_Scm_Monotone_Stdio implements IDF_Scm_Monotone_IStdio +{ + /** this is the most recent STDIO version. The number is output + at the protocol start. Older versions of monotone (prior 0.47) + do not output it and are therefor incompatible */ + public static $SUPPORTED_STDIO_VERSION = 2; + + private $project; + private $proc; + private $pipes; + private $oob; + private $cmdnum; + private $lastcmd; + + /** + * Constructor - starts the stdio process + * + * @param IDF_Project + */ + public function __construct(IDF_Project $project) + { + $this->project = $project; + $this->start(); + } + + /** + * Destructor - stops the stdio process + */ + public function __destruct() + { + $this->stop(); + } + + /** + * Returns a string with additional options which are passed to + * an mtn instance connecting to remote databases + * + * @return string + */ + private function _getAuthOptions() + { + $prjconf = $this->project->getConf(); + $name = $prjconf->getVal('mtn_client_key_name', false); + $hash = $prjconf->getVal('mtn_client_key_hash', false); + + if (!$name || !$hash) { + throw new IDF_Scm_Exception(sprintf( + __('Monotone client key name or hash not in project conf.') + )); + } + + $keydir = Pluf::f('tmp_folder').'/mtn-client-keys'; + if (!file_exists($keydir)) { + if (!mkdir($keydir)) { + throw new IDF_Scm_Exception(sprintf( + __('The key directory %s could not be created.'), $keydir + )); + } + } + + // in case somebody cleaned out the cache, we restore the key here + $keyfile = $keydir . '/' . $name .'.'. $hash; + if (!file_exists($keyfile)) { + $data = $prjconf->getVal('mtn_client_key_data'); + if (!file_put_contents($keyfile, $data, LOCK_EX)) { + throw new IDF_Scm_Exception(sprintf( + __('Could not write client key "%s"'), $keyfile + )); + } + } + + return sprintf('--keydir=%s --key=%s ', + escapeshellarg($keydir), + escapeshellarg($hash) + ); + } + + /** + * Starts the stdio process and resets the command counter + */ + public function start() + { + if (is_resource($this->proc)) + $this->stop(); + + $remote_db_access = Pluf::f('mtn_db_access', 'remote') == 'remote'; + + $cmd = Pluf::f('idf_exec_cmd_prefix', '') . + escapeshellarg(Pluf::f('mtn_path', 'mtn')) . ' '; + + $opts = Pluf::f('mtn_opts', array()); + foreach ($opts as $opt) { + $cmd .= sprintf('%s ', escapeshellarg($opt)); + } + + if ($remote_db_access) { + $cmd .= $this->_getAuthOptions(); + $host = sprintf(Pluf::f('mtn_remote_url'), $this->project->shortname); + $cmd .= sprintf('automate remote_stdio %s', escapeshellarg($host)); + } + else + { + $repo = sprintf(Pluf::f('mtn_repositories'), $this->project->shortname); + if (!file_exists($repo)) { + throw new IDF_Scm_Exception( + "repository file '$repo' does not exist" + ); + } + $cmd .= sprintf('--db %s automate stdio', escapeshellarg($repo)); + } + + $descriptors = array( + 0 => array('pipe', 'r'), + 1 => array('pipe', 'w'), + 2 => array('pipe', 'w'), + ); + + $env = array('LANG' => 'en_US.UTF-8'); + $this->proc = proc_open($cmd, $descriptors, $this->pipes, + null, $env); + + if (!is_resource($this->proc)) { + throw new IDF_Scm_Exception('could not start stdio process'); + } + + $this->_checkVersion(); + + $this->cmdnum = -1; + } + + /** + * Stops the stdio process and closes all pipes + */ + public function stop() + { + if (!is_resource($this->proc)) + return; + + fclose($this->pipes[0]); + fclose($this->pipes[1]); + fclose($this->pipes[2]); + + proc_close($this->proc); + $this->proc = null; + } + + /** + * select()'s on stdout and returns true as soon as we got new + * data to read, false if the select() timed out + * + * @return boolean + * @throws IDF_Scm_Exception + */ + private function _waitForReadyRead() + { + if (!is_resource($this->pipes[1])) + return false; + + $read = array($this->pipes[1], $this->pipes[2]); + $write = $except = null; + $streamsChanged = stream_select( + $read, $write, $except, 0, 20000 + ); + + if ($streamsChanged === false) { + throw new IDF_Scm_Exception( + 'Could not select() on read pipe' + ); + } + + if ($streamsChanged == 0) { + return false; + } + + return true; + } + + /** + * Checks the version of the used stdio protocol + * + * @throws IDF_Scm_Exception + */ + private function _checkVersion() + { + $this->_waitForReadyRead(); + + $version = fgets($this->pipes[1]); + if ($version === false) { + throw new IDF_Scm_Exception( + "Could not determine stdio version, stderr is:\n". + $this->_readStderr() + ); + } + + if (!preg_match('/^format-version: (\d+)$/', $version, $m) || + $m[1] != self::$SUPPORTED_STDIO_VERSION) + { + throw new IDF_Scm_Exception( + 'stdio format version mismatch, expected "'. + self::$SUPPORTED_STDIO_VERSION.'", got "'.@$m[1].'"' + ); + } + + fgets($this->pipes[1]); + } + + /** + * Writes a command to stdio + * + * @param array + * @param array + * @throws IDF_Scm_Exception + */ + private function _write(array $args, array $options = array()) + { + $cmd = ''; + if (count($options) > 0) { + $cmd = 'o'; + foreach ($options as $k => $vals) { + if (!is_array($vals)) + $vals = array($vals); + + foreach ($vals as $v) { + $cmd .= strlen((string)$k) . ':' . (string)$k; + $cmd .= strlen((string)$v) . ':' . (string)$v; + } + } + $cmd .= 'e '; + } + + $cmd .= 'l'; + foreach ($args as $arg) { + $cmd .= strlen((string)$arg) . ':' . (string)$arg; + } + $cmd .= "e\n"; + + if (!fwrite($this->pipes[0], $cmd)) { + throw new IDF_Scm_Exception("could not write '$cmd' to process"); + } + + $this->lastcmd = $cmd; + $this->cmdnum++; + } + + /** + * Reads all output from stderr and returns it + * + * @return string + */ + private function _readStderr() + { + $err = ""; + while (($line = fgets($this->pipes[2])) !== false) { + $err .= $line; + } + return empty($err) ? '' : $err; + } + + /** + * Reads the last output from the stdio process, parses and returns it + * + * @return string + * @throws IDF_Scm_Exception + */ + private function _readStdout() + { + $this->oob = array('w' => array(), + 'p' => array(), + 't' => array(), + 'e' => array()); + + $output = ""; + $errcode = 0; + + while (true) { + if (!$this->_waitForReadyRead()) + continue; + + $data = array(0,"",0); + $idx = 0; + while (true) { + $c = fgetc($this->pipes[1]); + if ($c === false) { + throw new IDF_Scm_Exception( + "No data on stdin, stderr is:\n". + $this->_readStderr() + ); + } + + if ($c == ':') { + if ($idx == 2) + break; + + ++$idx; + continue; + } + + if (is_numeric($c)) + $data[$idx] = $data[$idx] * 10 + $c; + else + $data[$idx] .= $c; + } + + // sanity + if ($this->cmdnum != $data[0]) { + throw new IDF_Scm_Exception( + 'command numbers out of sync; expected '. + $this->cmdnum .', got '. $data[0] + ); + } + + $toRead = $data[2]; + $buffer = ""; + while ($toRead > 0) { + $buffer .= fread($this->pipes[1], $toRead); + $toRead = $data[2] - strlen($buffer); + } + + switch ($data[1]) { + case 'w': + case 'p': + case 't': + case 'e': + $this->oob[$data[1]][] = $buffer; + continue; + case 'm': + $output .= $buffer; + continue; + case 'l': + $errcode = $buffer; + break 2; + } + } + + if ($errcode != 0) { + throw new IDF_Scm_Exception( + "command '{$this->lastcmd}' returned error code $errcode: ". + implode(' ', $this->oob['e']) + ); + } + + return $output; + } + + /** + * Executes a command over stdio and returns its result + * + * @param array Array of arguments + * @param array Array of options as key-value pairs. Multiple options + * can be defined in sub-arrays, like + * "r" => array("123...", "456...") + * @return string + */ + public function exec(array $args, array $options = array()) + { + $this->_write($args, $options); + return $this->_readStdout(); + } + + /** + * Returns the last out-of-band output for a previously executed + * command as associative array with 'e' (error), 'w' (warning), + * 'p' (progress) and 't' (ticker, unparsed) as keys + * + * @return array + */ + public function getLastOutOfBandOutput() + { + return $this->oob; + } +} + diff --git a/indefero/src/IDF/Scm/Monotone/Usher.php b/indefero/src/IDF/Scm/Monotone/Usher.php new file mode 100644 index 0000000..4d389bf --- /dev/null +++ b/indefero/src/IDF/Scm/Monotone/Usher.php @@ -0,0 +1,269 @@ + + */ +class IDF_Scm_Monotone_Usher +{ + /** + * Without giving a specific state, returns an array of all servers. + * When a state is given, the array contains only servers which are + * in the given state. + * + * @param string $state One of REMOTE, ACTIVE, WAITING, SLEEPING, + * STOPPING, STOPPED, SHUTTINGDOWN or SHUTDOWN + * @return array + */ + public static function getServerList($state = null) + { + $conn = self::_triggerCommand('LIST '.$state); + if ($conn == 'none') + return array(); + + return preg_split('/[ ]/', $conn, -1, PREG_SPLIT_NO_EMPTY); + } + + /** + * Returns an array of all open connections to the given server, or to + * any server if no server is specified. + * If there are no connections to list, an empty array is returned. + * + * Example: + * array("server1" => array( + * array("address" => "192.168.1.0", "port" => "13456"), + * ... + * ), + * "server2" => ... + * ) + * + * @param string $server + * @return array + */ + public static function getConnectionList($server = null) + { + $conn = self::_triggerCommand('LISTCONNECTIONS '.$server); + if ($conn == 'none') + return array(); + + $single_conns = preg_split('/[ ]/', $conn, -1, PREG_SPLIT_NO_EMPTY); + $ret = array(); + foreach ($single_conns as $conn) { + preg_match('/\(([^)]+)\)([^:]+):(\d+)/', $conn, $matches); + $ret[$matches[1]][] = (object)array( + 'server' => $matches[1], + 'address' => $matches[2], + 'port' => $matches[3], + ); + } + + if ($server !== null) { + if (array_key_exists($server, $ret)) + return $ret[$server]; + return array(); + } + + return $ret; + } + + /** + * Get the status of a particular server, or of the usher as a whole if + * no server is specified. + * + * @param string $server + * @return One of REMOTE, SLEEPING, STOPPING, STOPPED for servers or + * ACTIVE, WAITING, SHUTTINGDOWN or SHUTDOWN for usher itself + */ + public static function getStatus($server = null) + { + return self::_triggerCommand('STATUS '.$server); + } + + /** + * Looks up the name of the server that would be used for an incoming + * connection having the given host and pattern. + * + * @param string $host Host + * @param string $pattern Branch pattern + * @return server name + * @throws IDF_Scm_Exception + */ + public static function matchServer($host, $pattern) + { + $ret = self::_triggerCommand('MATCH '.$host.' '.$pattern); + if (preg_match('/^OK: (.+)/', $ret, $m)) + return $m[1]; + preg_match('/^ERROR: (.+)/', $ret, $m); + throw new IDF_Scm_Exception('could not match server: '.$m[1]); + } + + /** + * Prevent the given local server from receiving further connections, + * and stop it once all connections are closed. The return value will + * be the new status of that server: ACTIVE local servers will become + * STOPPING, and WAITING and SLEEPING serveres become STOPPED. + * Servers in other states are not affected. + * + * @param string $server + * @return string State of the server after the command + */ + public static function stopServer($server) + { + return self::_triggerCommand("STOP $server"); + } + + /** + * Allow a STOPPED or STOPPING server to receive connections again. + * The return value is the new status of that server: STOPPING servers + * become ACTIVE, and STOPPED servers become SLEEPING. Servers in other + * states are not affected. + * + * @param string $server + * @return string State of the server after the command + */ + public static function startServer($server) + { + return self::_triggerCommand('START '.$server); + } + + /** + * Immediately kill the given local server, dropping any open connections, + * and prevent is from receiving new connections and restarting. The named + * server will immediately change to state STOPPED. + * + * @param string $server + * @return bool True if successful + */ + public static function killServer($server) + { + return self::_triggerCommand('KILL_NOW '.$server) == 'ok'; + } + + /** + * Do not accept new connections for any servers, local or remote. + * + * @return bool True if successful + */ + public static function shutDown() + { + return self::_triggerCommand('SHUTDOWN') == 'ok'; + } + + /** + * Begin accepting connections after a SHUTDOWN. + * + * @return bool True if successful + */ + public static function startUp() + { + return self::_triggerCommand('STARTUP') == 'ok'; + } + + /** + * Reload the config file, the same as sending SIGHUP. + * + * @return bool True if successful (after the configuration was reloaded) + */ + public static function reload() + { + return self::_triggerCommand('RELOAD') == 'ok'; + } + + private static function _triggerCommand($cmd) + { + $uc = Pluf::f('mtn_usher_conf', false); + if (!$uc || !is_readable($uc)) { + throw new IDF_Scm_Exception( + '"mtn_usher_conf" is not configured or not readable' + ); + } + + $parsed_config = + IDF_Scm_Monotone_BasicIO::parse(file_get_contents($uc)); + $host = $port = $user = $pass = null; + foreach ($parsed_config as $stanza) { + foreach ($stanza as $line) { + if ($line['key'] == 'adminaddr') { + list($host, $port) = explode(":", @$line['values'][0]); + break; + } + if ($line['key'] == 'userpass') { + $user = @$line['values'][0]; + $pass = @$line['values'][1]; + } + } + } + + if (empty($host)) { + throw new IDF_Scm_Exception('usher host is empty'); + } + if (!preg_match('/^\d+$/', $port)) + { + throw new IDF_Scm_Exception('usher port is invalid'); + } + + if (empty($user)) { + throw new IDF_Scm_Exception('usher user is empty'); + } + + if (empty($pass)) { + throw new IDF_Scm_Exception('usher pass is empty'); + } + + $sock = @fsockopen($host, $port, $errno, $errstr); + if (!$sock) { + throw new IDF_Scm_Exception( + "could not connect to usher: $errstr ($errno)" + ); + } + + fwrite($sock, 'USERPASS '.$user.' '.$pass."\n"); + if (feof($sock)) { + throw new IDF_Scm_Exception( + 'usher closed the connection - this should not happen' + ); + } + + fwrite($sock, $cmd."\n"); + $out = ''; + while (!feof($sock)) { + $out .= fgets($sock); + } + fclose($sock); + $out = rtrim($out); + + if ($out == 'unknown command') { + throw new IDF_Scm_Exception('unknown command: '.$cmd); + } + + return $out; + } +} + diff --git a/indefero/src/IDF/Scm/Monotone/ZipRender.php b/indefero/src/IDF/Scm/Monotone/ZipRender.php new file mode 100644 index 0000000..3a6a3f7 --- /dev/null +++ b/indefero/src/IDF/Scm/Monotone/ZipRender.php @@ -0,0 +1,102 @@ +stdio = $stdio; + $this->revision = $revision; + } + + /** + * Render a response object. + */ + function render($output_body=true) + { + $this->outputHeaders(); + + if ($output_body) { + $certs = $this->stdio->exec(array('certs', $this->revision)); + $stanzas = IDF_Scm_Monotone_BasicIO::parse($certs); + + // use the revision's date (if there is one) as timestamp + // for all file entries + $timestamp = time(); + foreach ($stanzas as $stanza) { + $next_is_date = false; + foreach ($stanza as $line) { + if ($line['key'] == 'name' && $line['values'][0] == 'date') { + $next_is_date = true; + continue; + } + if ($next_is_date && $line['key'] == 'value') { + $timestamp = strtotime($line['values'][0]); + break; + } + } + } + + $manifest = $this->stdio->exec(array('get_manifest_of', $this->revision)); + $stanzas = IDF_Scm_Monotone_BasicIO::parse($manifest); + + $zip = new ZipStream(); + + foreach ($stanzas as $stanza) { + if ($stanza[0]['key'] != 'file') + continue; + $content = $this->stdio->exec(array('get_file', $stanza[1]['hash'])); + $zip->add_file( + $stanza[0]['values'][0], + $content, + array('time' => $timestamp) + ); + } + + $zip->finish(); + } + } +} diff --git a/indefero/src/IDF/Scm/Svn.php b/indefero/src/IDF/Scm/Svn.php new file mode 100644 index 0000000..a7dc707 --- /dev/null +++ b/indefero/src/IDF/Scm/Svn.php @@ -0,0 +1,636 @@ + 'tree', + 'file' => 'blob'); + + public function __construct($repo, $project=null) + { + $this->repo = $repo; + $this->project = $project; + $this->cache['commitmess'] = array(); + } + + public function isAvailable() + { + $cmd = $this->svnCmd(array('info', '--xml'), $this->repo); + $xmlInfo = self::shell_exec('IDF_Scm_Svn::isAvailable', $cmd); + + try { + $xml = simplexml_load_string($xmlInfo); + } + catch (Exception $e) { + return false; + } + if (!isset($xml->entry->commit['revision'])) { + return false; + } + if (0 == (int)$xml->entry->commit['revision']) { + return false; + } + return true; + } + + public function getRepositorySize() + { + if (strpos($this->repo, 'file://') !== 0) { + return -1; + } + $cmd = Pluf::f('idf_exec_cmd_prefix', '').'du -sk ' + .escapeshellarg(substr($this->repo, 7)); + $out = explode(' ', self::shell_exec('IDF_Scm_Svn::getRepositorySize', $cmd), 2); + return (int) $out[0]*1024; + } + + /** + * Given the string describing the author from the log find the + * author in the database. + * + * @param string Author + * @return mixed Pluf_User or null + */ + public function findAuthor($author) + { + $sql = new Pluf_SQL('login=%s', array(trim($author))); + $users = Pluf::factory('Pluf_User')->getList(array('filter'=>$sql->gen())); + return ($users->count() > 0) ? $users[0] : null; + } + + /** + * Returns the URL of the subversion repository. + * + * @param IDF_Project + * @param string + * @return string URL + */ + public static function getAnonymousAccessUrl($project,$commit=null) + { + $conf = $project->getConf(); + if (false !== ($url=$conf->getVal('svn_remote_url', false)) + && !empty($url)) { + // Remote repository + return $url; + } + return sprintf(Pluf::f('svn_remote_url'), $project->shortname); + } + + /** + * Returns the URL of the subversion repository. + * + * @param IDF_Project + * @param string + * @return string URL + */ + public static function getAuthAccessUrl($project, $user, $commit=null) + { + $conf = $project->getConf(); + if (false !== ($url=$conf->getVal('svn_remote_url', false)) + && !empty($url)) { + // Remote repository + return $url; + } + return sprintf(Pluf::f('svn_remote_url'), $project->shortname); + } + + /** + * Returns this object correctly initialized for the project. + * + * @param IDF_Project + * @return IDF_Scm_Svn + */ + public static function factory($project) + { + $conf = $project->getConf(); + // Find the repository + if (false !== ($rep=$conf->getVal('svn_remote_url', false)) + && !empty($rep)) { + // Remote repository + $scm = new IDF_Scm_Svn($rep, $project); + $scm->username = $conf->getVal('svn_username'); + $scm->password = $conf->getVal('svn_password'); + return $scm; + } else { + $rep = sprintf(Pluf::f('svn_repositories'), $project->shortname); + return new IDF_Scm_Svn($rep, $project); + } + } + + /** + * Subversion revisions are either a number or 'HEAD'. + */ + public function validateRevision($rev) + { + if ($rev == 'HEAD') { + return IDF_Scm::REVISION_VALID; + } + + $cmd = $this->svnCmd(array('info'), $this->repo, $rev); + self::exec('IDF_Scm_Svn::validateRevision', $cmd, $out, $ret); + + if ($ret == 0) + return IDF_Scm::REVISION_VALID; + return IDF_Scm::REVISION_INVALID; + } + + /** + * Test a given object hash. + * + * @param string Object hash. + * @return mixed false if not valid or 'blob', 'tree', 'commit' + */ + public function testHash($rev, $path='') + { + // OK if HEAD on / + if ($rev === 'HEAD' && $path === '') { + return 'commit'; + } + + // Else, test the path on revision + $cmd = $this->svnCmd(array('info', '--xml'), + $this->repo.'/'.self::smartEncode($path), + $rev); + $xmlInfo = self::shell_exec('IDF_Scm_Svn::testHash', $cmd); + + // If exception is thrown, return false + try { + $xml = simplexml_load_string($xmlInfo); + } + catch (Exception $e) { + return false; + } + + // If the entry node does exists, params are wrong + if (!isset($xml->entry)) { + return false; + } + + // Else, enjoy it :) + return 'commit'; + } + + public function getTree($commit, $folder='/', $branch=null) + { + $cmd = $this->svnCmd(array('ls', '--xml'), + $this->repo.'/'.self::smartEncode($folder), + $commit); + $xml = simplexml_load_string(self::shell_exec('IDF_Scm_Svn::getTree', $cmd)); + $res = array(); + $folder = (strlen($folder) and ($folder != '/')) ? $folder.'/' : ''; + foreach ($xml->list->entry as $entry) { + $file = array(); + $file['type'] = $this->assoc[(string) $entry['kind']]; + $file['file'] = (string) $entry->name; + $file['fullpath'] = $folder.((string) $entry->name); + $file['efullpath'] = self::smartEncode($file['fullpath']); + $file['date'] = gmdate('Y-m-d H:i:s', + strtotime((string) $entry->commit->date)); + $file['rev'] = (string) $entry->commit['revision']; + $file['log'] = $this->getCommitMessage($file['rev']); + // Get the size if the type is blob + if ($file['type'] == 'blob') { + $file['size'] = (string) $entry->size; + } + $file['author'] = (string) $entry->commit->author; + $file['perm'] = ''; + $res[] = (object) $file; + } + return $res; + } + + /** + * Get the commit message of a revision revision. + * + * @param string Commit ('HEAD') + * @return String commit message + */ + private function getCommitMessage($rev='HEAD') + { + if (isset($this->cache['commitmess'][$rev])) { + return $this->cache['commitmess'][$rev]; + } + $cmd = $this->svnCmd(array('log', '--xml', '--limit', '1'), $this->repo, $rev); + try { + $xml = simplexml_load_string(self::shell_exec('IDF_Scm_Svn::getCommitMessage', $cmd)); + $this->cache['commitmess'][$rev] = (string) $xml->logentry->msg; + } + catch (Exception $e) { + $this->cache['commitmess'][$rev] = ''; + } + return $this->cache['commitmess'][$rev]; + } + + public function getPathInfo($filename, $rev=null) + { + if ($rev == null) { + $rev = 'HEAD'; + } + $cmd = $this->svnCmd(array('info', '--xml'), + $this->repo.'/'.self::smartEncode($filename), $rev); + $xml = simplexml_load_string(self::shell_exec('IDF_Scm_Svn::getPathInfo', $cmd)); + if (!isset($xml->entry)) { + return false; + } + $entry = $xml->entry; + $file = array(); + $file['fullpath'] = $filename; + $file['hash'] = (string) $entry->repository->uuid; + $file['type'] = $this->assoc[(string) $entry['kind']]; + $pathinfo = pathinfo($filename); + $file['file'] = $pathinfo['basename']; + $file['rev'] = $rev; + $file['author'] = (string) $entry->author; + $file['date'] = gmdate('Y-m-d H:i:s', strtotime((string) $entry->commit->date)); + $file['size'] = (string) $entry->size; + $file['log'] = ''; + return (object) $file; + } + + public function getFile($def, $cmd_only=false) + { + $cmd = $this->svnCmd(array('cat'), + $this->repo.'/'.self::smartEncode($def->fullpath), + $def->rev); + return ($cmd_only) ? + $cmd : self::shell_exec('IDF_Scm_Svn::getFile', $cmd); + } + + /** + * Subversion branches are folder based. + * + * One need to list the folder to know them. + */ + public function getBranches() + { + if (isset($this->cache['branches'])) { + return $this->cache['branches']; + } + $res = array(); + $cmd = $this->svnCmd(array('ls'), $this->repo.'/branches', 'HEAD'); + self::exec('IDF_Scm_Svn::getBranches', $cmd, $out, $ret); + if ($ret == 0) { + foreach ($out as $entry) { + if (substr(trim($entry), -1) == '/') { + $branch = substr(trim($entry), 0, -1); + $res[$branch] = 'branches/'.$branch; + } + } + } + ksort($res); + + $cmd = $this->svnCmd(array('info'), $this->repo.'/trunk', 'HEAD'); + self::exec('IDF_Scm_Svn::getBranches', $cmd, $out, $ret); + if ($ret == 0) { + $res = array('trunk' => 'trunk') + $res; + } + $this->cache['branches'] = $res; + return $res; + } + + /** + * Subversion tags are folder based. + * + * One need to list the folder to know them. + */ + public function getTags() + { + if (isset($this->cache['tags'])) { + return $this->cache['tags']; + } + $res = array(); + $cmd = $this->svnCmd(array('ls'), $this->repo.'/tags', 'HEAD'); + self::exec('IDF_Scm_Svn::getTags', $cmd, $out, $ret); + if ($ret == 0) { + foreach ($out as $entry) { + if (substr(trim($entry), -1) == '/') { + $tag = substr(trim($entry), 0, -1); + $res[$tag] = 'tags/'.$tag; + } + } + } + ksort($res); + $this->cache['tags'] = $res; + return $res; + } + + public function getMainBranch() + { + return 'HEAD'; + } + + public function inBranches($commit, $path) + { + foreach ($this->getBranches() as $branch => $bpath) { + if ($bpath and 0 === strpos($path, $bpath)) { + return array($branch); + } + } + return array(); + } + + public function inTags($commit, $path) + { + foreach ($this->getTags() as $tag => $tpath) { + if ($tpath and 0 === strpos($path, $tpath)) { + return array($tag); + } + } + return array(); + } + + /** + * Get commit details. + * + * @param string Commit + * @param bool Get commit diff (false) + * @return array Changes + */ + public function getCommit($commit, $getdiff=false) + { + if ($this->validateRevision($commit) != IDF_Scm::REVISION_VALID) { + return false; + } + $res = array(); + $cmd = $this->svnCmd(array('log', '--xml', '--limit', '1', '-v'), + $this->repo, $commit); + $xmlRes = self::shell_exec('IDF_Scm_Svn::getCommit', $cmd); + $xml = simplexml_load_string($xmlRes); + $res['author'] = (string) $xml->logentry->author; + $res['date'] = gmdate('Y-m-d H:i:s', strtotime((string) $xml->logentry->date)); + $res['title'] = (string) $xml->logentry->msg; + $res['commit'] = (string) $xml->logentry['revision']; + $res['parents'] = $xml->logentry['revision'] > 1 + ? array((string) $xml->logentry['revision'] - 1) + : array(); + $res['diff'] = ($getdiff) ? $this->getDiff($commit) : ''; + $res['tree'] = ''; + $res['branch'] = ''; + return (object) $res; + } + + /** + * Check if a commit is big. + * + * @param string Commit ('HEAD') + * @return bool The commit is big + */ + public function isCommitLarge($commit='HEAD') + { + if (substr($this->repo, 0, 7) != 'file://') { + return false; + } + // We have a locally hosted repository, we can query it with + // svnlook + $repo = substr($this->repo, 7); + $cmd = sprintf(Pluf::f('svnlook_path', 'svnlook').' changed -r %s %s', + escapeshellarg($commit), + escapeshellarg($repo)); + $cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd; + $out = self::shell_exec('IDF_Scm_Svn::isCommitLarge', $cmd); + $lines = preg_split("/\015\012|\015|\012/", $out); + return (count($lines) > 100); + } + + private function getDiff($rev='HEAD') + { + $res = array(); + $cmd = $this->svnCmd(array('diff', '-c', $rev), $this->repo); + return self::shell_exec('IDF_Scm_Svn::getDiff', $cmd); + } + + /** + * @see IDF_Scm::getChanges() + */ + public function getChanges($commit) + { + if ($this->validateRevision($commit) != IDF_Scm::REVISION_VALID) { + return null; + } + $cmd = $this->svnCmd(array('log', '--xml', '-v'), $this->repo, $commit); + $out = array(); + $out = self::shell_exec('IDF_Scm_Svn::getChanges', $cmd); + $xml = simplexml_load_string($out); + if (count($xml) == 0) { + return null; + } + $entry = current($xml); + + $return = (object) array( + 'additions' => array(), + 'deletions' => array(), + 'patches' => array(), + // while SVN has support for attributes, we cannot see their changes + // in the log's XML unfortunately + 'properties' => array(), + 'copies' => array(), + 'renames' => array(), + ); + + foreach ($entry->paths->path as $p) { + $path = (string) $p; + foreach ($p->attributes() as $k => $v) { + $key = (string) $k; + $val = (string) $v; + if ($key != 'action') + continue; + if ($val == 'M') + $return->patches[] = $path; + else if ($val == 'A') + $return->additions[] = $path; + else if ($val == 'D') + $return->deletions[] = $path; + } + } + + // copies are treated as renames if they have an add _and_ a drop; + // only if they only have an add, but no drop, they're treated as copies + foreach ($entry->paths->path as $p) { + $trg = (string) $p; + $src = null; + foreach ($p->attributes() as $k => $v) { + if ((string) $k == 'copyfrom-path') { + $src = (string) $v; + break; + } + } + + if ($src == null) + continue; + + $srcidx = array_search($src, $return->deletions); + $trgidx = array_search($trg, $return->additions); + if ($srcidx !== false && $trgidx !== false) { + $return->renames[$src] = $trg; + unset($return->deletions[$srcidx]); + unset($return->additions[$trgidx]); + continue; + } + if ($srcidx === false && $trgidx !== false) { + $return->copies[$src] = $trg; + unset($return->additions[$trgidx]); + continue; + } + // file sutures (counter-operation to copy) not supported + } + + return $return; + } + + /** + * Get latest changes. + * + * @param string Revision or ('HEAD'). + * @param int Number of changes (10). + * + * @return array Changes. + */ + public function getChangeLog($rev=null, $n=10) + { + if ($rev != 'HEAD' and !preg_match('/^\d+$/', $rev)) { + // we accept only revisions or HEAD + $rev = 'HEAD'; + } + $res = array(); + $cmd = $this->svnCmd(array('log', '--xml', '-v', '--limit', $n), + $this->repo.'@'.$rev); + $xmlRes = self::shell_exec('IDF_Scm_Svn::getChangeLog', $cmd); + $xml = simplexml_load_string($xmlRes); + foreach ($xml->logentry as $entry) { + $log = array(); + $log['author'] = (string) $entry->author; + $log['date'] = gmdate('Y-m-d H:i:s', strtotime((string) $entry->date)); + $split = preg_split("[\n\r]", (string) $entry->msg, 2); + $log['title'] = $split[0]; + $log['commit'] = (string) $entry['revision']; + $log['full_message'] = (isset($split[1])) ? trim($split[1]) : ''; + $res[] = (object) $log; + } + return $res; + } + + /** + * Get additionnals properties on path and revision + * + * @param string File + * @param string Commit ('HEAD') + * @return array + */ + public function getProperties($rev, $path='') + { + $res = array(); + $cmd = $this->svnCmd(array('proplist', '--xml'), + $this->repo.'/'.self::smartEncode($path), $rev); + $xmlProps = self::shell_exec('IDF_Scm_Svn::getProperties', $cmd); + $props = simplexml_load_string($xmlProps); + + // No properties, returns an empty array + if (!isset($props->target)) { + return $res; + } + + // Get the value of each property + foreach ($props->target->property as $prop) { + $key = (string) $prop['name']; + $res[$key] = $this->getProperty($key, $rev, $path); + } + + return $res; + } + + /** + * Get a specific additionnal property on path and revision + * + * @param string Property + * @param string File + * @param string Commit ('HEAD') + * @return string the property value + */ + private function getProperty($property, $rev, $path='') + { + $res = array(); + $cmd = $this->svnCmd(array('propget', $property, '--xml'), + $this->repo.'/'.self::smartEncode($path), $rev); + $xmlProp = self::shell_exec('IDF_Scm_Svn::getProperty', $cmd); + $prop = simplexml_load_string($xmlProp); + + return (string) $prop->target->property; + } + + /** + * Get the number of the last commit in the repository. + * + * @param string Commit ('HEAD'). + * + * @return String last number commit + */ + public function getLastCommit($rev='HEAD') + { + $xmlInfo = ''; + $cmd = $this->svnCmd(array('info', '--xml'), $this->repo, $rev); + $xmlInfo = self::shell_exec('IDF_Scm_Svn::getLastCommit', $cmd); + + $xml = simplexml_load_string($xmlInfo); + return (string) $xml->entry->commit['revision']; + } + + private function svnCmd($args = array(), $repoarg = null, $revarg = null) + { + $cmdline = array(); + $cmdline[] = Pluf::f('idf_exec_cmd_prefix', ''); + $cmdline[] = Pluf::f('svn_path', 'svn'); + $cmdline[] = '--no-auth-cache'; + $cmdline[] = '--username='.escapeshellarg($this->username); + $cmdline[] = '--password='.escapeshellarg($this->password); + + foreach ($args as $arg) { + $cmdline[] = escapeshellarg($arg); + } + + if ($repoarg != null) { + if ($revarg != null) { + $repoarg .= '@'.$revarg; + } + $cmdline[] = escapeshellarg($repoarg); + } + + if ($revarg != null) { + $cmdline[] = '--revision='.escapeshellarg($revarg); + } + + return implode(' ', $cmdline); + } +} + diff --git a/indefero/src/IDF/Search.php b/indefero/src/IDF/Search.php new file mode 100644 index 0000000..39ea073 --- /dev/null +++ b/indefero/src/IDF/Search.php @@ -0,0 +1,202 @@ +$c) { + $words_flat[] = $word; + } + $word_ids = self::getWordIds($words_flat); + if (in_array(null, $word_ids) or count($word_ids) == 0) { + return array(); + } + return self::mySearchDocuments($word_ids, $project, $model); + } + + /** + * Search documents. + * + * Only the total of the ponderated occurences is used to sort the + * results. + * + * @param array Ids. + * @param IDF_Project Project to limit the search. + * @param string Model class to limit the search. + * @return array Sorted by score, returns model_class, model_id and score. + */ + public static function mySearchDocuments($wids, $project, $model) + { + $db =& Pluf::db(); + $gocc = new IDF_Search_Occ(); + $where = array(); + foreach ($wids as $id) { + $where[] = $db->qn('word').'='.(int)$id; + } + $prj = (is_null($project)) ? '' : ' AND project='.(int)$project->id; + $md = (is_null($model)) ? '' : ' AND model_class='.$db->esc($model); + $select = 'SELECT model_class, model_id, SUM(pondocc) AS score FROM '.$gocc->getSqlTable().' WHERE '.implode(' OR ', $where).$prj.$md.' GROUP BY model_class, model_id HAVING COUNT(*)='.count($wids).' ORDER BY score DESC'; + return $db->select($select); + } + + /** + * Index a document. + * + * See Pluf_Search for the disclaimer and informations. + * + * @param Pluf_Model Document to index. + * @param Stemmer used. ('Pluf_Text_Stemmer_Porter') + * @return array Statistics. + */ + public static function index($doc, $stemmer='Pluf_Text_Stemmer_Porter') + { + $words = Pluf_Text::tokenize($doc->_toIndex()); + if ($stemmer != null) { + $words = self::stem($words, $stemmer); + } + // Get the total number of words. + $total = 0.0; + $words_flat = array(); + foreach ($words as $word => $occ) { + $total += (float) $occ; + $words_flat[] = $word; + } + // Drop the last indexation. + $gocc = new IDF_Search_Occ(); + $sql = new Pluf_SQL('DELETE FROM '.$gocc->getSqlTable().' WHERE model_class=%s AND model_id=%s', array($doc->_model, $doc->id)); + $db =& Pluf::db(); + $db->execute($sql->gen()); + // Get the ids for each word. + $ids = self::getWordIds($words_flat); + // Insert a new word for the missing words and add the occ. + $n = count($ids); + $new_words = 0; + $done = array(); + for ($i=0;$i<$n;$i++) { + if ($ids[$i] === null) { + $word = new Pluf_Search_Word(); + $word->word = $words_flat[$i]; + try { + $word->create(); + $new_words++; + $ids[$i] = $word->id; + } catch (Exception $e) { + // 100% of the time, the word has been created + // by another process in the background. + $r_ids = self::getWordIds(array($word->word)); + if ($r_ids[0]) { + $ids[$i] = $r_ids[0]; + } else { + // give up for this word + continue; + } + } + } + if (isset($done[$ids[$i]])) { + continue; + } + $done[$ids[$i]] = true; + $occ = new IDF_Search_Occ(); + $occ->word = new Pluf_Search_Word($ids[$i]); + $occ->model_class = $doc->_model; + $occ->model_id = $doc->id; + $occ->project = $doc->get_project(); + $occ->occ = $words[$words_flat[$i]]; + $occ->pondocc = $words[$words_flat[$i]]/$total; + $occ->create(); + } + // update the stats + $sql = new Pluf_SQL('model_class=%s AND model_id=%s', + array($doc->_model, $doc->id)); + $last_index = Pluf::factory('Pluf_Search_Stats')->getList(array('filter' => $sql->gen())); + if ($last_index->count() == 0) { + $stats = new Pluf_Search_Stats(); + $stats->model_class = $doc->_model; + $stats->model_id = $doc->id; + $stats->indexations = 1; + $stats->create(); + } else { + $last_index[0]->indexations += 1; + $last_index[0]->update(); + } + return array('total' => $total, 'new' => $new_words, 'unique'=>$n); + } + + /** + * Remove an item from the index. + * + * You must call this function when you delete items wich are + * indexed. Just add the call: + * + * IDF_Search::remove($this); + * + * in the preDelete() method of your object. + * + * @param mixed Item to be removed + * @return bool Success + */ + public static function remove($item) + { + if ($item->id > 0) { + $sql = new Pluf_SQL('model_id=%s AND model_class=%s', + array($item->id, $item->_model)); + $items = Pluf::factory('IDF_Search_Occ')->getList(array('filter'=>$sql->gen())); + foreach ($items as $tl) { + $tl->delete(); + } + } + return true; + } + +} \ No newline at end of file diff --git a/indefero/src/IDF/Search/Occ.php b/indefero/src/IDF/Search/Occ.php new file mode 100644 index 0000000..46b868f --- /dev/null +++ b/indefero/src/IDF/Search/Occ.php @@ -0,0 +1,99 @@ +_a['verbose'] = __('occurrence'); + $this->_a['table'] = 'idf_search_occs'; + $this->_a['model'] = 'IDF_Search_Occ'; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + //It is automatically added. + 'blank' => true, + ), + 'word' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'Pluf_Search_Word', + 'blank' => false, + 'verbose' => __('word'), + ), + 'model_class' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 150, + 'verbose' => __('model class'), + ), + 'model_id' => + array( + 'type' => 'Pluf_DB_Field_Integer', + 'blank' => false, + 'verbose' => __('model id'), + ), + 'project' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_Project', + 'blank' => false, + 'verbose' => __('project'), + ), + 'occ' => + array( + 'type' => 'Pluf_DB_Field_Integer', + 'blank' => false, + 'verbose' => __('occurrences'), + ), + 'pondocc' => + array( + 'type' => 'Pluf_DB_Field_Float', + 'blank' => false, + 'verbose' => __('ponderated occurrence'), + ), + ); + $this->_a['idx'] = array( + 'model_class_id_combo_word_idx' => + array( + 'type' => 'unique', + 'col' => 'model_class, model_id, word', + ), + ); + + } + + function __toString() + { + return $this->word; + } +} + diff --git a/indefero/src/IDF/Tag.php b/indefero/src/IDF/Tag.php new file mode 100644 index 0000000..6809bc2 --- /dev/null +++ b/indefero/src/IDF/Tag.php @@ -0,0 +1,175 @@ +_a['table'] = 'idf_tags'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + //It is automatically added. + 'blank' => true, + ), + 'project' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_Project', + 'blank' => true, + 'is_null' => true, + 'default' => null, + 'verbose' => __('project'), + ), + 'class' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'default' => IDF_TAG_DEFAULT_CLASS, + 'verbose' => __('tag class'), + 'help_text' => __('The class of the tag.'), + ), + 'name' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'verbose' => __('name'), + ), + 'lcname' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'editable' => false, + 'verbose' => __('lcname'), + 'help_text' => __('Lower case version of the name for fast searching.'), + ), + ); + + $table = $this->_con->pfx.'idf_project_idf_tag_assoc'; + $cols = implode(', ', array_keys($this->_a['cols'])); + $this->_a['views'] = array( + 'join_projects' => + array( + 'join' => 'LEFT JOIN '.$table + .' ON idf_tag_id=id', + 'select' => $this->getSelect().',COUNT(idf_project_id) as project_count', + 'group' => $cols, + 'props' => array('project_count' => 'project_count'), + ), + ); + + $this->_a['idx'] = array( + 'lcname_idx' => + array( + 'col' => 'lcname', + 'type' => 'normal', + ), + 'class_idx' => + array( + 'col' => 'class', + 'type' => 'normal', + ), + ); + } + + function preSave($create=false) + { + $this->lcname = mb_strtolower($this->name); + } + + /** + * Add a project-specific tag if not already existing. + * + * @param string Name of the tag. + * @param IDF_Project Project of the tag. + * @param string Class of the tag (IDF_TAG_DEFAULT_CLASS) + * @return IDF_Tag The tag. + */ + public static function add($name, $project, $class=IDF_TAG_DEFAULT_CLASS) + { + $class = trim($class); + $name = trim($name); + $gtag = new IDF_Tag(); + $sql = new Pluf_SQL('class=%s AND lcname=%s AND project=%s', + array($class, mb_strtolower($name), $project->id)); + $tags = $gtag->getList(array('filter' => $sql->gen())); + if ($tags->count() < 1) { + // create a new tag + $tag = new IDF_Tag(); + $tag->name = $name; + $tag->class = $class; + $tag->project = $project; + $tag->create(); + return $tag; + } + return $tags[0]; + } + + /** + * Add a global tag if not already existing + * + * @param string Name of the tag. + * @param string Class of the tag (IDF_TAG_DEFAULT_CLASS) + * @return IDF_Tag The tag. + */ + public static function addGlobal($name, $class=IDF_TAG_DEFAULT_CLASS) + { + $class = trim($class); + $name = trim($name); + $gtag = new IDF_Tag(); + $sql = new Pluf_SQL('class=%s AND lcname=%s AND project IS NULL', + array($class, mb_strtolower($name))); + $tags = $gtag->getList(array('filter' => $sql->gen())); + if ($tags->count() < 1) { + // create a new tag + $tag = new IDF_Tag(); + $tag->name = $name; + $tag->class = $class; + $tag->project = null; + $tag->create(); + return $tag; + } + return $tags[0]; + } + + function __toString() + { + if ($this->class != IDF_TAG_DEFAULT_CLASS) { + return $this->class.':'.$this->name; + } + return $this->name; + } + +} diff --git a/indefero/src/IDF/Template.php b/indefero/src/IDF/Template.php new file mode 100644 index 0000000..21f9c10 --- /dev/null +++ b/indefero/src/IDF/Template.php @@ -0,0 +1,51 @@ +'."\n"; + } + + if (array_key_exists('revision', $info)) { + if (strpos($info['revision'], '$') !== false) { + $info['revision'] = 'unknown'; + $cmd = Pluf::f('idf_exec_cmd_prefix', ''). + Pluf::f('git_path', 'git'). + ' log -1 --format=%H'; + + if (IDF_Scm::exec('IDF_Template_AppVersion::start', $cmd, $output)) { + $info['revision'] = trim(@$output[0]); + } + } + echo ''."\n"; + } + } +} + diff --git a/indefero/src/IDF/Template/AssignShowUser.php b/indefero/src/IDF/Template/AssignShowUser.php new file mode 100644 index 0000000..b07c514 --- /dev/null +++ b/indefero/src/IDF/Template/AssignShowUser.php @@ -0,0 +1,55 @@ +context); + $this->context->set($var, + Pluf_Template::markSafe($t->start($user, $request, $text, false))); + } +} diff --git a/indefero/src/IDF/Template/HotKey.php b/indefero/src/IDF/Template/HotKey.php new file mode 100644 index 0000000..3606e92 --- /dev/null +++ b/indefero/src/IDF/Template/HotKey.php @@ -0,0 +1,36 @@ +project = $request->project; + $this->request = $request; + $this->scm = IDF_Scm::get($request->project); + if ($esc) $text = Pluf_esc($text); + if ($autolink) { + $text = IDF_Template_safePregReplace('#([a-z]+://[^\s\(\)]+)#i', + '\1', $text); + } + if ($request->rights['hasIssuesAccess']) { + $text = IDF_Template_safePregReplace('#((?:issue|bug|ticket)(s)?\s+|\s+\#)(\d+)(\#ic\d+)?(?(2)((?:[, \w]+(?:\s+\#)?)?\d+(?:\#ic\d+)?){0,})#im', + array($this, 'callbackIssues'), $text); + } + if ($request->rights['hasReviewAccess']) { + $text = IDF_Template_safePregReplace('#(reviews?\s+)(\d+(?:(?:\s+and|\s+or|,)\s+\d+)*)\b#i', + array($this, 'callbackReviews'), $text); + } + if ($request->rights['hasSourceAccess']) { + $verbs = array('added', 'fixed', 'reverted', 'changed', 'removed'); + $nouns = array('commit', 'commits', 'revision', 'revisions', 'rev', 'revs'); + $prefix = implode(' in|', $verbs).' in' . '|'. + implode('|', $nouns); + $text = IDF_Template_safePregReplace('#((?:'.$prefix.')(?:\s+r?))([0-9a-f]{1,40}((?:\s+and|\s+or|,)\s+r?[0-9a-f]{1,40})*)\b#i', + array($this, 'callbackCommits'), $text); + $text = IDF_Template_safePregReplace('=(src:)([^\s@#,\(\)\\\\]+(?:(\\\\)[\s@#][^\s@#,\(\)\\\\]+){0,})+(?:\@([^\s#,]+))?(?:#(\d+))?=im', + array($this, 'callbackSource'), $text); + } + if ($wordwrap) $text = Pluf_Text::wrapHtml($text, 69, "\n"); + if ($nl2br) $text = nl2br($text); + if ($echo) { + echo $text; + } else { + return $text; + } + } + + /** + * General call back for the issues. + */ + function callbackIssues($m) + { + $c = count($m); + if (4 === $c || 5 === $c) { + $issue = new IDF_Issue($m[3]); + if (0 < $issue->id and $issue->project == $this->project->id) { + $m[1] = trim($m[1]); + $prefix = ''; + if ('#' === $m[1]) { + $title = $m[1].$m[3]; + $prefix = mb_substr($m[0], 0, strpos($m[0], $m[1])); // fixes \n matches + } else { + $title = $m[1].' '.$m[3]; + } + if (4 === $c) { + return $prefix.$this->linkIssue($issue, $title); + } else { + return $prefix.$this->linkIssue($issue, $title, $m[4]); + } + } + return $m[0]; // not existing issue. + } + return IDF_Template_safePregReplace('#(\#)?(\d+)(\#ic\d+)?#', + array($this, 'callbackIssue'), + $m[0]); + } + + /** + * Call back for the case of multiple issues like 'issues 1, 2 and 3'. + * + * Called from callbackIssues, it is linking only the number of + * the issues. + */ + function callbackIssue($m) + { + $issue = new IDF_Issue($m[2]); + if (0 < $issue->id and $issue->project == $this->project->id) { + if (4 === count($m)) { + return $this->linkIssue($issue, $m[1].$m[2], $m[3]); + } + return $this->linkIssue($issue, $m[1].$m[2]); + } + return $m[0]; // not existing issue. + } + + /** + * General call back to convert commits to HTML links. + * + * @param array $m Single regex match. + * @return string Content with converted commits. + */ + function callbackCommits($m) + { + $keyword = rtrim($m[1]); + if (empty($m[3])) { + // Single commit like 'commit 6e030e6'. + return $m[1].call_user_func(array($this, 'callbackCommit'), array($m[2])); + } + // Multiple commits like 'commits 6e030e6, a25bfc1 and 3c094f8'. + return $m[1].IDF_Template_safePregReplace('#\b[0-9a-f]{1,40}\b#i', array($this, 'callbackCommit'), $m[2]); + } + + /** + * Convert plaintext commit to HTML link. Called from callbackCommits. + * + * Regex callback for {@link IDF_Template_IssueComment::callbackCommits()}. + * + * @param array Single regex match. + * @return string HTML A element with commit. + */ + function callbackCommit($m) + { + $co = $this->scm->getCommit($m[0]); + if (!$co) { + return $m[0]; // not a commit. + } + return ''.$m[0].''; + } + + /** + * General call back to convert reviews to HTML links. + * + * @param array $m Single regex match. + * @return string Content with converted reviews. + */ + function callbackReviews($m) + { + $keyword = rtrim($m[1]); + if ('reviews' === $keyword) { + return $m[1].IDF_Template_safePregReplace('#\b(\d+)\b#i', array($this, 'callbackReview'), $m[2]); + } else if ('review' === $keyword) { + return $m[1].call_user_func(array($this, 'callbackReview'), array('', $m[2])); + } + return $m[0]; + } + + /** + * Convert plaintext commit to HTML link. Called from callbackReviews. + * + * Regex callback for {@link IDF_Template_IssueComment::callbackReviews()}. + * + * @param array Single regex match. + * @return string HTML A element with review. + */ + function callbackReview($m) + { + $review = new IDF_Review($m[1]); + if ($review->id > 0 and $review->project == $this->project->id) { + return $this->linkReview($review, $m[1]); + } else { + return $m[0]; // not existing issue. + } + } + + function callbackSource($m) + { + if (!$this->scm->isAvailable()) + return $m[0]; + $commit = null; + if (!empty($m[4])) { + if (!$this->scm->getCommit($m[4])) { + return $m[0]; + } + $commit = $m[4]; + } + $file = $m[2]; + if (!empty($m[3])) + $file = str_replace($m[3], '', $file); + $linktext = $file; + if (!empty($commit)) + $linktext .= '@'.$commit; + $request_file_info = $this->scm->getPathInfo($file, $commit); + if (!$request_file_info) { + return $m[0]; + } + if ($request_file_info->type == 'tree') { + return $m[0]; + } + $link = Pluf_HTTP_URL_urlForView('IDF_Views_Source::tree', array( + $this->project->shortname, + $commit == null ? $this->scm->getMainBranch() : $commit, + $file + )); + if (!empty($m[5])) { + $link .= '#L'.$m[5]; + $linktext .= '#'.$m[5]; + } + return $m[1].''.$linktext.''; + } + + /** + * Generate the link to an issue. + * + * @param IDF_Issue Issue. + * @param string Name of the link. + * @return string Linked issue. + */ + public function linkIssue($issue, $title, $anchor='') + { + $ic = (in_array($issue->status, $this->project->getTagIdsByStatus('closed'))) ? 'issue-c' : 'issue-o'; + return ''.Pluf_esc($title).''; + } + + /** + * Generate the link to a review. + * + * @param IDF_Review Review. + * @param string Name of the link. + * @return string Linked review. + */ + public function linkReview($review, $title, $anchor='') + { + $ic = (in_array($review->status, $this->project->getTagIdsByStatus('closed'))) ? 'issue-c' : 'issue-o'; + return ''.Pluf_esc($title).''; + } +} diff --git a/indefero/src/IDF/Template/Markdown.php b/indefero/src/IDF/Template/Markdown.php new file mode 100644 index 0000000..4c05704 --- /dev/null +++ b/indefero/src/IDF/Template/Markdown.php @@ -0,0 +1,199 @@ +project = $request->project; + $this->request = $request; + // Replace like in the issue text + $tag = new IDF_Template_IssueComment(); + $text = $tag->start($text, $request, false, false, false, false); + // Replace [[[path/to/file.mdtext, commit]]] with embedding + // the content of the file into the wki page + if ($this->request->rights['hasSourceAccess']) { + $text = IDF_Template_safePregReplace('#\[\[\[([^\,]+)(?:, ([^/]+))?\]\]\]#im', + array($this, 'callbackEmbeddedDoc'), + $text); + } + // Replace [Page]([[PageName]]) with corresponding link to the page, with link text being Page. + $text = IDF_Template_safePregReplace('#\[([^\]]+)\]\(\[\[([A-Za-z0-9\-]+)\]\]\)#im', + array($this, 'callbackWikiPage'), + $text); + // Replace [[PageName]] with corresponding link to the page. + $text = IDF_Template_safePregReplace('#\[\[([A-Za-z0-9\-]+)\]\]#im', + array($this, 'callbackWikiPageNoName'), + $text); + + $filter = new IDF_Template_MarkdownPrefilter(); + $text = $filter->go(Pluf_Text_MarkDown_parse($text)); + + // Replace [[!ResourceName]] with corresponding HTML for the resource; + // we need to do that after the HTML filtering as we'd otherwise be unable to use + // certain HTML elements, such as iframes, that are used to display text content + // FIXME: no support for escaping yet in place + echo IDF_Template_safePregReplace('#\[\[!([A-Za-z0-9\-]+)(?:,\s*([^\]]+))?\]\]#im', + array($this, 'callbackWikiResource'), + $text); + } + + function callbackWikiPageNoName($m) + { + $m[2] = $m[1]; //Set the link text to be the same as the page name. + return $this->callbackWikiPage($m); + } + + function callbackWikiPage($m) + { + $sql = new Pluf_SQL('project=%s AND title=%s', + array($this->project->id, $m[2])); + $pages = Pluf::factory('IDF_Wiki_Page')->getList(array('filter'=>$sql->gen())); + if ($pages->count() != 1 and $this->request->rights['hasWikiAccess'] + and !$this->request->user->isAnonymous()) { + return ' '.$m[1].''; + } + if (!$this->request->rights['hasWikiAccess'] or $pages->count() == 0) { + return $m[1]; + } + return ''.$m[1].''; + } + + function callbackWikiResource($m) + { + @list($match, $resourceName, $opts) = $m; + + if (!$this->request->rights['hasWikiAccess']) { + return ''.$match.''; + } + + $sql = new Pluf_SQL('project=%s AND title=%s', + array($this->project->id, $resourceName)); + $resources = Pluf::factory('IDF_Wiki_Resource')->getList(array('filter'=>$sql->gen())); + + if ($resources->count() == 0) { + if ($this->request->user->isAnonymous()) { + return ''.$match.''; + } + + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::createResource', + array($this->project->shortname), + array('name' => $resourceName)); + return ' '. + ''.$match.''; + } + + // by default, render the most recent revision + $resourceRevision = $resources[0]->get_current_revision(); + + list($urlConf, $urlMatches) = $this->request->view; + + // if we currently look at an existing wiki page, look up its name and find the proper resource (if any) + if ($urlConf['model'] == 'IDF_Views_Wiki' && $urlConf['method'] == 'viewPage') { + $sql = new Pluf_SQL('project=%s AND title=%s', + array($this->project->id, $urlMatches[2])); + $pages = Pluf::factory('IDF_Wiki_Page')->getList(array('filter'=>$sql->gen())); + if ($pages->count() == 0) throw new Exception('page not found'); + $pageRevision = $pages[0]->get_current_revision(); + + // if we look at an old version of the page, figure out the resource version back then + if (isset($this->request->GET['rev']) and preg_match('/^[0-9]+$/', $this->request->GET['rev'])) { + $pageRevision = Pluf_Shortcuts_GetObjectOr404('IDF_Wiki_PageRevision', + $this->request->GET['rev']); + // this is actually an invariant since we came so far looking at + // and rendering the old revision already + if ($pageRevision == null) { + throw new Exception('page revision with id '.$this->request->GET['rev'].' not found'); + } + } + + $sql = new Pluf_SQL('wikiresource=%s AND idf_wiki_pagerevision_id=%s', + array($resources[0]->id, $pageRevision->id)); + $resourceRevision = Pluf::factory('IDF_Wiki_ResourceRevision')->getOne( + array('filter' => $sql->gen(), 'view' => 'join_pagerevision')); + + if ($resourceRevision == null) { + return ''.$match.''; + } + } + + $validOpts = array( + 'align' => '/^(left|right|center)$/', + 'width' => '/^\d+(%|px|em)?$/', + 'height' => '/^\d+(%|px|em)?$/', + 'preview' => '/^yes|no$/', + 'title' => '/.+/', + ); + + $parsedOpts = array(); + // FIXME: no support for escaping yet in place + $opts = preg_split('/\s*,\s*/', $opts, -1, PREG_SPLIT_NO_EMPTY); + foreach ((array)@$opts as $opt) + { + list($key, $value) = preg_split('/\s*=\s*/', $opt, 2); + if (!array_key_exists($key, $validOpts)) { + continue; + } + if (!preg_match($validOpts[$key], $value)) { + continue; + } + $parsedOpts[$key] = $value; + } + + return $resourceRevision->render($parsedOpts); + } + + function callbackEmbeddedDoc($m) + { + $scm = IDF_Scm::get($this->request->project); + if (!$scm->isAvailable()) { + return $m[0]; + } + $view_source = new IDF_Views_Source(); + $match = array('dummy', $this->request->project->shortname); + $match[] = (isset($m[2])) ? $m[2] : $scm->getMainBranch(); + $match[] = $m[1]; + $res = $view_source->getFile($this->request, $match); + if ($res->status_code != 200) { + return $m[0]; + } + $info = pathinfo($m[1]); + $fileinfo = array($res->headers['Content-Type'], $m[1], + isset($info['extension']) ? $info['extension'] : 'bin'); + if (!IDF_FileUtil::isText($fileinfo)) { + return $m[0]; + } + return $res->content; + } +} + diff --git a/indefero/src/IDF/Template/MarkdownForge.php b/indefero/src/IDF/Template/MarkdownForge.php new file mode 100644 index 0000000..fc18782 --- /dev/null +++ b/indefero/src/IDF/Template/MarkdownForge.php @@ -0,0 +1,119 @@ +request = $request; + $filter = new IDF_Template_MarkdownPrefilter(); + $text = $filter->go(Pluf_Text_MarkDown_parse($text)); + + // replace {}-macros with the corresponding template rendering + echo IDF_Template_safePregReplace('#\{(\w+)(?:,\s*([^\}]+))?\}#im', + array($this, 'callbackMacros'), + $text); + } + + public function callbackMacros($matches) + { + @list(, $macro, $opts) = $matches; + $known_macros = array('projectlist'); + if (!in_array($macro, $known_macros)) { + return $matches[0]; + } + $callbackName = 'callback'.ucfirst(strtolower($macro)).'Macro'; + return $this->callbackProjectlistMacro($opts); + } + + public function callbackProjectlistMacro($opts) + { + $validOpts = array( + 'label' => '/^\d+|(\w+:)?\w+$/', + 'order' => '/^name|activity$/', + 'limit' => '/^\d+$/', + ); + + $parsedOpts = array(); + // FIXME: no support for escaping yet in place + $opts = preg_split('/\s*,\s*/', $opts, -1, PREG_SPLIT_NO_EMPTY); + foreach ((array)@$opts as $opt) + { + list($key, $value) = preg_split('/\s*=\s*/', $opt, 2); + if (!array_key_exists($key, $validOpts)) { + continue; + } + if (!preg_match($validOpts[$key], $value)) { + continue; + } + $parsedOpts[$key] = $value; + } + + $tag = false; + if (!empty($parsedOpts['label'])) { + if (is_numeric($parsedOpts['label'])) { + $tag = Pluf::factory('IDF_Tag')->get($parsedOpts['label']); + } else { + @list($class, $name) = preg_split('/:/', $parsedOpts['label'], 2); + if (empty($name)) { + $name = $class; + $class = IDF_TAG_DEFAULT_CLASS; + } + $sql = new Pluf_SQL('class=%s AND lcname=%s AND project IS NULL', + array(strtolower($class), mb_strtolower($name))); + $tag = Pluf::factory('IDF_Tag')->getOne(array('filter' => $sql->gen())); + } + // ignore non-global tags + if ($tag !== false && $tag->project > 0) { + $tag = false; + } + } + + $order = 'name'; + if (!empty($parsedOpts['order'])) { + $order = $parsedOpts['order']; + } + + $projects = IDF_Views::getProjects($this->request->user, $tag, $order); + if (!empty($parsedOpts['limit']) && $parsedOpts['limit'] < count($projects)) { + // there is no array_slice on ArrayObject, do'h! + $projectsCopy = array(); + for ($i=0; $i<$parsedOpts['limit']; ++$i) + $projectsCopy[] = $projects[$i]; + $projects = $projectsCopy; + } + + $tmpl = new Pluf_Template('idf/project-list.html'); + $context = new Pluf_Template_Context(array( + 'projects' => $projects, + 'order' => 'name', + )); + return $tmpl->render($context); + } +} + diff --git a/indefero/src/IDF/Template/MarkdownPrefilter.php b/indefero/src/IDF/Template/MarkdownPrefilter.php new file mode 100644 index 0000000..ec88859 --- /dev/null +++ b/indefero/src/IDF/Template/MarkdownPrefilter.php @@ -0,0 +1,214 @@ + array('class', 'dir', 'id', 'style', 'title', + 'href', 'hreflang', 'rel'), + 'abbr' => array('class', 'dir', 'id', 'style', 'title'), + 'address' => array('class', 'dir', 'id', 'style', 'title'), + 'b' => array('class', 'dir', 'id', 'style', 'title'), + 'blockquote' => array('class', 'dir', 'id', 'style', 'title', + 'cite'), + 'br' => array('class', 'id', 'style', 'title'), + 'caption' => array('class', 'dir', 'id', 'style', 'title', + 'align'), // deprecated attribute), + 'code' => array('class', 'dir', 'id', 'style', 'title'), + 'dd' => array('class', 'dir', 'id', 'style', 'title'), + 'del' => array('class', 'dir', 'id', 'style', 'title', + 'cite', 'datetime'), + 'div' => array('class', 'dir', 'id', 'style', 'title', + 'align'), // deprecated attribute + 'dl' => array('class', 'dir', 'id', 'style', 'title'), + 'dt' => array('class', 'dir', 'id', 'style', 'title'), + 'em' => array('class', 'dir', 'id', 'style', 'title'), + 'font' => array('class', 'dir', 'id', 'style', 'title', // deprecated element + 'color', 'face', 'size'), // deprecated attribute + 'h1' => array('class', 'dir', 'id', 'style', 'title', + 'align'), // deprecated attribute + 'h2' => array('class', 'dir', 'id', 'style', 'title', + 'align'), // deprecated attribute + 'h3' => array('class', 'dir', 'id', 'style', 'title', + 'align'), // deprecated attribute + 'h4' => array('class', 'dir', 'id', 'style', 'title', + 'align'), // deprecated attribute + 'h5' => array('class', 'dir', 'id', 'style', 'title', + 'align'), // deprecated attribute + 'h6' => array('class', 'dir', 'id', 'style', 'title', + 'align'), // deprecated attribute + 'hr' => array('class', 'dir', 'id', 'style', 'title', + 'align', 'noshade', 'size', 'width'), // deprecated attribute + 'i' => array('class', 'dir', 'id', 'style', 'title'), + 'img' => array('class', 'dir', 'id', 'style', 'title', + 'src', 'alt', 'height', 'width'), + 'ins' => array('class', 'dir', 'id', 'style', 'title', + 'cite', 'datetime'), + 'li' => array('class', 'dir', 'id', 'style', 'title', + 'type'), // deprecated attribute + 'ol' => array('class', 'dir', 'id', 'style', 'title', + 'type'), // deprecated attribute + 'p' => array('class', 'dir', 'id', 'style', 'title', + 'align'), // deprecated attribute + 'pre' => array('class', 'dir', 'id', 'style', 'title', + 'width'), // deprecated attribute + 'strong' => array('class', 'dir', 'id', 'style', 'title'), + 'table' => array('class', 'dir', 'id', 'style', 'title', + 'border', 'cellpadding', 'cellspacing', 'frame', 'rules', 'summary', 'width', + 'align', 'bgcolor'), // deprecated attribute + 'td' => array('class', 'dir', 'id', 'style', 'title', + 'align', 'colspan', 'headers', 'rowspan', 'scope', 'valign', + 'bgcolor', 'height', 'nowrap', 'width'), // deprecated attribute + 'th' => array('class', 'dir', 'id', 'style', 'title', + 'align', 'colspan', 'rowspan', 'scope', 'valign', + 'bgcolor', 'height', 'nowrap', 'width'), // deprecated attribute + 'tr' => array('class', 'dir', 'id', 'style', 'title', + 'align', 'valign', + 'bgcolor'), // deprecated attribute + 'ul' => array('class', 'dir', 'id', 'style', 'title', + 'type'), // deprecated attribute + ); + // tags which should always be self-closing (e.g. "") + public $no_close = array( + 'img', + 'br', + 'hr', + ); + + // tags which must always have seperate opening and closing tags + // (e.g. "") + public $always_close = array( + 'strong', + 'em', + 'b', + 'code', + 'i', + 'ul', + 'ol', + 'li', + 'p', + 'table', + 'caption', + 'tr', + 'td', + 'span', + 'a', + 'blockquote', + 'pre', + 'iframe', + 'h1', 'h2', 'h3', 'address', + 'del', + 'ins', + ); + // attributes which should be checked for valid protocols + public $protocol_attributes = array( + 'src', + 'href', + ); + // protocols which are allowed + public $allowed_protocols = array( + 'http', + 'https', + 'ftp', + 'mailto', + 'irc' + ); + // tags which should be removed if they contain no content + // (e.g. "" or "") + public $remove_blanks = array( + 'p', + 'strong', + 'em', + 'caption', + 'li', + 'span', + 'del', + 'ins', + ); +} diff --git a/indefero/src/IDF/Template/ShowUser.php b/indefero/src/IDF/Template/ShowUser.php new file mode 100644 index 0000000..d4ba31b --- /dev/null +++ b/indefero/src/IDF/Template/ShowUser.php @@ -0,0 +1,67 @@ +isAnonymous() and $user->id == $request->user->id) { + $utext = __('Me'); + $url = Pluf_HTTP_URL_urlForView('idf_dashboard'); + } else { + $utext = Pluf_esc($user); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_User::view', + array($user->login)); + } + $out = sprintf('%s', + $url, $utext); + } + if ($echo) echo $out; + else return $out; + } +} diff --git a/indefero/src/IDF/Template/Tag/UploadUrl.php b/indefero/src/IDF/Template/Tag/UploadUrl.php new file mode 100644 index 0000000..a5461ff --- /dev/null +++ b/indefero/src/IDF/Template/Tag/UploadUrl.php @@ -0,0 +1,35 @@ +model_class, $item->model_id); + echo $m->timelineFragment($request); + } +} diff --git a/indefero/src/IDF/Tests/0001-Some-configuration-variables-have-been-added-in-orde.patch b/indefero/src/IDF/Tests/0001-Some-configuration-variables-have-been-added-in-orde.patch new file mode 100644 index 0000000..942396f --- /dev/null +++ b/indefero/src/IDF/Tests/0001-Some-configuration-variables-have-been-added-in-orde.patch @@ -0,0 +1,52 @@ +From ec6cb8b19ee3a08f48625181d6a74744b3950e90 Mon Sep 17 00:00:00 2001 +From: Manuel Eidenberger +Date: Mon, 2 Feb 2009 15:11:23 +0100 +Subject: [PATCH] Some configuration variables have been added in order to manually set svn and svnlook binarie paths (see issue 123) + +--- + src/IDF/Scm/Svn.php | 24 ++++++++++++------------ + src/IDF/conf/idf.php-dist | 8 ++++++++ + 2 files changed, 20 insertions(+), 12 deletions(-) + +diff --git a/src/IDF/Scm/Svn.php b/src/IDF/Scm/Svn.php +index e2f7a61..e1359c7 100644 +--- a/src/IDF/Scm/Svn.php ++++ b/src/IDF/Scm/Svn.php +@@ -108,7 +108,7 @@ class IDF_Scm_Svn + } + + // Else, test the path on revision +- $cmd = sprintf('svn info --xml --username=%s --password=%s %s@%s', ++ $cmd = sprintf(Pluf::f('svn_path').' info --xml --username=%s --password=%s %s@%s', + escapeshellarg($this->username), + escapeshellarg($this->password), + escapeshellarg($this->repo.'/'.$path), +@@ -190,7 +190,7 @@ class IDF_Scm_Svn + */ + private function getCommitMessage($file, $rev='HEAD') + { +- $cmd = sprintf('svn log --xml --limit 1 --username=%s --password=%s %s@%s', ++ $cmd = sprintf(Pluf::f('svn_path').' log --xml --limit 1 --username=%s --password=%s %s@%s', + escapeshellarg($this->username), + escapeshellarg($this->password), + escapeshellarg($file), +diff --git a/src/IDF/conf/idf.php-dist b/src/IDF/conf/idf.php-dist +index 8aca31f..abb4ecd 100644 +--- a/src/IDF/conf/idf.php-dist ++++ b/src/IDF/conf/idf.php-dist +@@ -208,4 +208,12 @@ $cfg['allowed_scm'] = array('git' => 'IDF_Scm_Git', + # variables not being set correctly. Note the trailing space. + # $cfg['idf_exec_cmd_prefix'] = '/usr/bin/env -i '; + ++# Path to svn and svnlook binaries. In some cases, it is sometimes ++# necessary to define absolut path to these two binaries, for example: ++# $cfg['svn_path'] = 'svn'; ++# $cfg['svnlook_path'] = 'svnlook_path'; ++# This is only necessary if svn and svnlook binaries are not set in $PATH ++$cfg['svn_path'] = 'svn'; ++$cfg['svnlook_path'] = 'svnlook'; ++ + return $cfg; +-- +1.5.4.3 + diff --git a/indefero/src/IDF/Tests/TestDiff.php b/indefero/src/IDF/Tests/TestDiff.php new file mode 100644 index 0000000..6f7f0e6 --- /dev/null +++ b/indefero/src/IDF/Tests/TestDiff.php @@ -0,0 +1,73 @@ +parse(); + // $def = $diff->files['src/IDF/templates/idf/issues/view.html']; + // + // $orig_lines = preg_split("/\015\012|\015|\012/", $orig); + // $merged = $diff->mergeChunks($orig_lines, $def, 10); + // $lchunk = end($merged); + // $lline = end($lchunk); + // $this->assertEqual(array('', '166', '{/if}{/block}'), + // $lline); + //} + + public function testDiffWithHeaders() + { + $diff_content = file_get_contents(dirname(__FILE__).'/0001-Some-configuration-variables-have-been-added-in-orde.patch'); + $diff = new IDF_Diff($diff_content); + $diff->parse(); + $this->assertEqual(2, count($diff->files)); + $this->assertEqual(12, count($diff->files['src/IDF/conf/idf.php-dist']['chunks'][0])); + } + + public function testDiffRemoveOneLine() + { + $diff_content = file_get_contents(dirname(__FILE__).'/test-diff-remove-oneline.diff'); + $diff = new IDF_Diff($diff_content); + $diff->parse(); + $this->assertEqual(2, count($diff->files)); + $this->assertEqual(array(280, 288, ''), + $diff->files['src/IDF/Scm/Git.php']['chunks'][1][2]); + $this->assertEqual(7, count($diff->files['src/IDF/Scm/Git.php']['chunks'][1])); + } +} diff --git a/indefero/src/IDF/Tests/TestFileUtil.php b/indefero/src/IDF/Tests/TestFileUtil.php new file mode 100644 index 0000000..97ba8f2 --- /dev/null +++ b/indefero/src/IDF/Tests/TestFileUtil.php @@ -0,0 +1,47 @@ + 'application/x-httpd-php', + 'whatever.pht' => 'application/x-httpd-php', + 'README' => 'text/plain', + ); + foreach ($files as $file => $mime) { + $m = IDF_Views_Source::getMimeType($file); + $this->assertEqual($mime, $m[0]); + } + } +} diff --git a/indefero/src/IDF/Tests/TestGit.php b/indefero/src/IDF/Tests/TestGit.php new file mode 100644 index 0000000..a2e640c --- /dev/null +++ b/indefero/src/IDF/Tests/TestGit.php @@ -0,0 +1,87 @@ +assertEqual('Fixed the middleware to correctly return a 404 error if the project is', $log[0]->title); + + } + + /** + * parse a log encoded in iso 8859-1 + */ + public function testParseIsoLog() + { + $log_lines = preg_split("/\015\012|\015|\012/", file_get_contents(dirname(__FILE__).'/data/git-log-iso-8859-1.txt')); + $log = IDF_Scm_Git::parseLog($log_lines); + $titles = array( + array('Quick Profiler entfernt', 'UTF-8'), + array('Anwendungsmenu Divider eingefügt', 'ISO-8859-1'), + array('Anwendungen aufäumen', 'ISO-8859-1'), + ); + foreach ($log as $change) { + list($title, $senc) = array_shift($titles); + list($conv, $encoding) = IDF_Commit::toUTF8($change->title, true); + $this->assertEqual($title, $conv); + $this->assertEqual($senc, $encoding); + } + } + + /** + * parse a log encoded in iso 8859-2 + */ + public function testParseIsoLog2() + { + $log_lines = preg_split("/\015\012|\015|\012/", file_get_contents(dirname(__FILE__).'/data/git-log-iso-8859-2.txt')); + $log = IDF_Scm_Git::parseLog($log_lines); + $titles = array( + array('Doda³em model','ISO-8859-1'), + array('Doda³em model','ISO-8859-1'), + // The Good result is 'Dodałem model', the + // problem is that in that case, one cannot + // distinguish between latin1 and latin2. We + // will need to add a way for the project + // admin to set the priority between the + // encodings. + ); + foreach ($log as $change) { + list($title, $senc) = array_shift($titles); + list($conv, $encoding) = IDF_Commit::toUTF8($change->title, true); + $this->assertEqual($title, $conv); + $this->assertEqual($senc, $encoding); + } + } +} diff --git a/indefero/src/IDF/Tests/TestIssue.php b/indefero/src/IDF/Tests/TestIssue.php new file mode 100644 index 0000000..e919f23 --- /dev/null +++ b/indefero/src/IDF/Tests/TestIssue.php @@ -0,0 +1,138 @@ +projects = array(); + $this->users = array(); + for ($i=1;$i<3;$i++) { + $project = new IDF_Project(); + $project->name = 'Test project '.$i; + $project->shortname = 'test'.$i; + $project->description = sprintf('This is a test project %d.', $i); + $project->create(); + $this->projects[] = $project; + $user = new Pluf_User(); + $user->last_name = 'user'.$i; + $user->login = 'user'.$i; + $user->email = 'user'.$i.'@example.com'; + $user->create(); + $this->users[] = $user; + } + } + + + public function tearDown() + { + // This will drop cascading issues, comments and tags. + foreach ($this->projects as $proj) { + $proj->delete(); + } + foreach ($this->users as $u) { + $u->delete(); + } + } + + public function testCreate() + { + $issue = new IDF_Issue(); + $issue->project = $this->projects[0]; + $issue->summary = 'This is a test issue'; + $issue->submitter = $this->users[0]; + $issue->create(); + $this->assertEqual(1, $issue->id); + $this->assertIdentical(null, $issue->get_owner()); + $this->assertNotIdentical(null, $issue->get_submitter()); + } + + public function testCreateMultiple() + { + for ($i=1;$i<11;$i++) { + $issue = new IDF_Issue(); + $issue->project = $this->projects[0]; + $issue->summary = 'This is a test issue '.$i; + $issue->submitter = $this->users[0]; + $issue->owner = $this->users[1]; + $issue->create(); + } + for ($i=11;$i<16;$i++) { + $issue = new IDF_Issue(); + $issue->project = $this->projects[1]; + $issue->summary = 'This is a test issue '.$i; + $issue->submitter = $this->users[1]; + $issue->create(); + } + $this->assertEqual(10, + $this->projects[0]->get_issues_list()->count()); + $this->assertEqual(5, + $this->projects[1]->get_issues_list()->count()); + $this->assertEqual(5, + $this->users[1]->get_submitted_issue_list()->count()); + $this->assertEqual(10, + $this->users[0]->get_submitted_issue_list()->count()); + $this->assertEqual(10, + $this->users[1]->get_owned_issue_list()->count()); + $this->assertEqual(0, + $this->users[1]->get_owned_issue_list(array('filter' => 'project='.(int)$this->projects[1]->id))->count()); + $this->assertEqual(10, + $this->users[1]->get_owned_issue_list(array('filter' => 'project='.(int)$this->projects[0]->id))->count()); + } + + public function testAddIssueComment() + { + $issue = new IDF_Issue(); + $issue->project = $this->projects[0]; + $issue->summary = 'This is a test issue'; + $issue->submitter = $this->users[0]; + $issue->create(); + $ic = new IDF_IssueComment(); + $ic->issue = $issue; + $ic->submitter = $this->users[0]; + $ic->content = 'toto'; + $changes = array('s' => 'New summary', + 'st' => 'Active', + 't' => '-OS:Linux OS:Windows'); + $ic->changes = $changes; + $ic->create(); + $comments = $issue->get_comments_list(); + $this->assertEqual($changes, $comments[0]->changes); + } +} \ No newline at end of file diff --git a/indefero/src/IDF/Tests/TestMonotone.php b/indefero/src/IDF/Tests/TestMonotone.php new file mode 100644 index 0000000..ef20c9e --- /dev/null +++ b/indefero/src/IDF/Tests/TestMonotone.php @@ -0,0 +1,239 @@ +tmpdir, + "--db", $this->dbfile, + "--norc", + "--timestamps"); + + $cmdline = array_merge($cmdline, $args); + + $descriptorspec = array( + 0 => array("pipe", "r"), + 1 => array("pipe", "w"), + 2 => array("file", "{$this->tmpdir}/mtn-errors", "a") + ); + + $pipes = array(); + $dir = !empty($dir) ? $dir : $this->tmpdir; + $process = proc_open(implode(" ", $cmdline), + $descriptorspec, + $pipes, + $dir); + + if (!is_resource($process)) { + throw new Exception("could not create process"); + } + + if (!empty($stdin)) { + fwrite($pipes[0], $stdin); + fclose($pipes[0]); + } + + $stdout = stream_get_contents($pipes[1]); + fclose($pipes[1]); + + $ret = proc_close($process); + if ($ret != 0) { + throw new Exception( + "call ended with a non-zero error code (complete cmdline was: ". + implode(" ", $cmdline).")" + ); + } + + return $stdout; + } + + public function __construct() + { + parent::__construct("Test the monotone class."); + + $this->tmpdir = sys_get_temp_dir() . "/mtn-test"; + $this->dbfile = "{$this->tmpdir}/test.mtn"; + + set_include_path(get_include_path() . ":../../../pluf-master/src"); + require_once("Pluf.php"); + + Pluf::start(dirname(__FILE__)."/../conf/idf.php"); + + // Pluf::f() mocking + $GLOBALS['_PX_config']['mtn_repositories'] = "{$this->tmpdir}/%s.mtn"; + } + + private static function deleteRecursive($dirname) + { + if (is_dir($dirname)) + $dir_handle=opendir($dirname); + + while ($file = readdir($dir_handle)) { + if ($file!="." && $file!="..") { + if (!is_dir($dirname."/".$file)) { + unlink ($dirname."/".$file); + continue; + } + self::deleteRecursive($dirname."/".$file); + } + } + + closedir($dir_handle); + rmdir($dirname); + + return true; + } + + public function setUp() + { + if (is_dir($this->tmpdir)) { + self::deleteRecursive($this->tmpdir); + } + + mkdir($this->tmpdir); + + $this->mtnCall(array("db", "init")); + + $this->mtnCall(array("genkey", "test@test.de"), "\n\n"); + + $workspaceRoot = "{$this->tmpdir}/test-workspace"; + mkdir($workspaceRoot); + + $this->mtnCall(array("setup", "-b", "testbranch", "."), null, $workspaceRoot); + + file_put_contents("$workspaceRoot/foo", "blubber"); + $this->mtnCall(array("add", "foo"), null, $workspaceRoot); + + $this->mtnCall(array("commit", "-m", "initial"), null, $workspaceRoot); + + file_put_contents("$workspaceRoot/bar", "blafoo"); + mkdir("$workspaceRoot/subdir"); + file_put_contents("$workspaceRoot/subdir/bla", "blabla"); + $this->mtnCall(array("add", "-R", "--unknown"), null, $workspaceRoot); + + $this->mtnCall(array("commit", "-m", "second"), null, $workspaceRoot); + + $rev = $this->mtnCall(array("au", "get_base_revision_id"), null, $workspaceRoot); + $this->mtnCall(array("tag", rtrim($rev), "release-1.0")); + + $project = new IDF_Project(); + $project->shortname = "test"; + $this->mtnInstance = new IDF_Scm_Monotone($project); + } + + public function testIsAvailable() + { + $this->assertTrue($this->mtnInstance->isAvailable()); + } + + public function testGetBranches() + { + $branches = $this->mtnInstance->getBranches(); + $this->assertEqual(1, count($branches)); + list($key, $value) = each($branches); + $this->assertEqual("h:testbranch", $key); + $this->assertEqual("testbranch", $value); + } + + public function testGetTags() + { + $tags = $this->mtnInstance->getTags(); + $this->assertEqual(1, count($tags)); + list($key, $value) = each($tags); + $this->assertEqual("t:release-1.0", $key); + $this->assertEqual("release-1.0", $value); + } + + public function testInBranches() + { + $revOut = $this->mtnCall(array("au", "select", "b:testbranch")); + $revs = preg_split('/\n/', $revOut, -1, PREG_SPLIT_NO_EMPTY); + + $branches = $this->mtnInstance->inBranches($revs[0], null); + $this->assertEqual(1, count($branches)); + $this->assertEqual("h:testbranch", $branches[0]); + + $branches = $this->mtnInstance->inBranches("t:release-1.0", null); + $this->assertEqual(1, count($branches)); + $this->assertEqual("h:testbranch", $branches[0]); + } + + public function testInTags() + { + $rev = $this->mtnCall(array("au", "select", "t:release-1.0")); + $tags = $this->mtnInstance->inTags(rtrim($rev), null); + $this->assertEqual(1, count($tags)); + $this->assertEqual("t:release-1.0", $tags[0]); + + // pick the first (root) revisions in this database + $rev = $this->mtnCall(array("au", "roots")); + $tags = $this->mtnInstance->inTags(rtrim($rev), null); + $this->assertEqual(0, count($tags)); + } + + public function testGetTree() + { + $files = $this->mtnInstance->getTree("t:release-1.0"); + $this->assertEqual(3, count($files)); + + $this->assertEqual("bar", $files[0]->file); + $this->assertEqual("blob", $files[0]->type); + $this->assertEqual(6, $files[0]->size); // "blafoo" + $this->assertEqual("second\n", $files[0]->log); + + $this->assertEqual("foo", $files[1]->file); + $this->assertEqual("blob", $files[1]->type); + $this->assertEqual(7, $files[1]->size); // "blubber" + $this->assertEqual("initial\n", $files[1]->log); + + $this->assertEqual("subdir", $files[2]->file); + $this->assertEqual("tree", $files[2]->type); + $this->assertEqual(0, $files[2]->size); + + $files = $this->mtnInstance->getTree("t:release-1.0", "subdir"); + $this->assertEqual(1, count($files)); + + $this->assertEqual("bla", $files[0]->file); + $this->assertEqual("subdir/bla", $files[0]->fullpath); + $this->assertEqual("blob", $files[0]->type); + $this->assertEqual(6, $files[0]->size); // "blabla" + $this->assertEqual("second\n", $files[0]->log); + } + + public function testvalidateRevision() + { + $this->assertEquals(IDF_Scm::REVISION_VALID, $this->mtnInstance->validateRevision("t:release-1.0")); + $this->assertEquals(IDF_Scm::REVISION_INVALID, $this->mtnInstance->validateRevision("abcdef12345")); + } +} diff --git a/indefero/src/IDF/Tests/TestProject.php b/indefero/src/IDF/Tests/TestProject.php new file mode 100644 index 0000000..fcf4ea8 --- /dev/null +++ b/indefero/src/IDF/Tests/TestProject.php @@ -0,0 +1,77 @@ +getList() as $proj) { + $proj->delete(); + } + } + + public function testCreate() + { + $gproj = Pluf::factory('IDF_Project')->getList(); + $this->assertEqual(0, $gproj->count()); + $project = new IDF_Project(); + $project->name = 'Test project'; + $project->shortname = 'test'; + $project->description = 'This is a test project.'; + $project->create(); + $id = $project->id; + $p2 = new IDF_Project($id); + $this->assertEqual($p2->shortname, $project->shortname); + } + + public function testMultipleCreate() + { + $project = new IDF_Project(); + $project->name = 'Test project'; + $project->shortname = 'test'; + $project->description = 'This is a test project.'; + $project->create(); + try { + $project = new IDF_Project(); + $project->name = 'Test project'; + $project->shortname = 'test'; + $project->description = 'This is a test project.'; + $project->create(); + // if here it as failed + $this->fail('It should not be possible to create 2 projects with same shortname'); + } catch (Exception $e) { + $this->pass(); + } + } +} \ No newline at end of file diff --git a/indefero/src/IDF/Tests/TestSource.php b/indefero/src/IDF/Tests/TestSource.php new file mode 100644 index 0000000..f1f42dd --- /dev/null +++ b/indefero/src/IDF/Tests/TestSource.php @@ -0,0 +1,51 @@ + + array('test_project', 'default', 'current/sources'), + '/p/test_project/source/tree/3.6/current/sources' => + array('test_project', '3.6', 'current/sources'), + ); + foreach ($tests as $test => $res) { + $m = array(); + $t = preg_match($regex, $test, $m); + $this->assertEqual($res[0], $m[1]); + $this->assertEqual($res[1], $m[2]); + $this->assertEqual($res[2], $m[3]); + } + } +} diff --git a/indefero/src/IDF/Tests/TestSyncGit.php b/indefero/src/IDF/Tests/TestSyncGit.php new file mode 100644 index 0000000..5bc5d98 --- /dev/null +++ b/indefero/src/IDF/Tests/TestSyncGit.php @@ -0,0 +1,44 @@ +preg; + $no_matches = array('foo', "'ev!l'", "'something/../evil'"); + foreach ($no_matches as $test) { + preg_match($regex, $test, $matches); + $this->assertEqual(false, isset($matches['path'])); + } + } +} \ No newline at end of file diff --git a/indefero/src/IDF/Tests/data/git-log-iso-8859-1.txt b/indefero/src/IDF/Tests/data/git-log-iso-8859-1.txt new file mode 100644 index 0000000..c42a5ef --- /dev/null +++ b/indefero/src/IDF/Tests/data/git-log-iso-8859-1.txt @@ -0,0 +1,19 @@ +commit 11531a9dbc64a65150f2f38fbea7cef9d478a123 +Author: unknown +Date: Fri Jul 3 01:44:11 2009 +0200 + + Quick Profiler entfernt + +commit 11531a9dbc64a65150f2f38fbea7cef9d478a123 +Author: unknown +Date: Wed Jul 1 15:51:22 2009 +0200 + + Anwendungsmenu Divider eingefgt + +commit 11531a9dbc64a65150f2f38fbea7cef9d478a123 +Author: unknown +Date: Wed Jul 1 15:05:41 2009 +0200 + + Anwendungen aufumen + + diff --git a/indefero/src/IDF/Tests/data/git-log-iso-8859-2.txt b/indefero/src/IDF/Tests/data/git-log-iso-8859-2.txt new file mode 100644 index 0000000..e98328c --- /dev/null +++ b/indefero/src/IDF/Tests/data/git-log-iso-8859-2.txt @@ -0,0 +1,12 @@ +commit 11531a9dbc64a65150f2f38fbea7cef9d478a123 +Author: unknown +Date: Fri Jul 3 01:44:11 2009 +0200 + + Dodaem model + +commit 11531a9dbc64a65150f2f38fbea7cef9d478a123 +Author: unknown +Date: Fri Jul 3 01:44:11 2009 +0200 + + Dodaem model + diff --git a/indefero/src/IDF/Tests/test-diff-remove-oneline.diff b/indefero/src/IDF/Tests/test-diff-remove-oneline.diff new file mode 100644 index 0000000..3fb279c --- /dev/null +++ b/indefero/src/IDF/Tests/test-diff-remove-oneline.diff @@ -0,0 +1,53 @@ +diff --git a/src/IDF/Scm/Git.php b/src/IDF/Scm/Git.php +index 5f35e0b..ebe0530 100644 +--- a/src/IDF/Scm/Git.php ++++ b/src/IDF/Scm/Git.php +@@ -250,14 +250,22 @@ class IDF_Scm_Git + * Get commit details. + * + * @param string Commit ('HEAD'). ++ * @param bool Get commit diff (false). + * @return array Changes. + */ +- public function getCommit($commit='HEAD') ++ public function getCommit($commit='HEAD', $getdiff=false) + { +- $cmd = sprintf('GIT_DIR=%s git show --date=iso --pretty=format:%s %s', +- escapeshellarg($this->repo), +- "'".$this->mediumtree_fmt."'", +- escapeshellarg($commit)); ++ if ($getdiff) { ++ $cmd = sprintf('GIT_DIR=%s git show --date=iso --pretty=format:%s %s', ++ escapeshellarg($this->repo), ++ "'".$this->mediumtree_fmt."'", ++ escapeshellarg($commit)); ++ } else { ++ $cmd = sprintf('GIT_DIR=%s git log -1 --date=iso --pretty=format:%s %s', ++ escapeshellarg($this->repo), ++ "'".$this->mediumtree_fmt."'", ++ escapeshellarg($commit)); ++ } + $out = array(); + IDF_Scm::exec($cmd, $out); + $log = array(); +@@ -278,7 +286,6 @@ class IDF_Scm_Git + return $out[0]; + } + +- + /** + * Get latest changes. + * +diff --git a/src/IDF/Views/Source.php b/src/IDF/Views/Source.php +index ad24ed6..e5b4f1b 100644 +--- a/src/IDF/Views/Source.php ++++ b/src/IDF/Views/Source.php +@@ -216,7 +216,7 @@ class IDF_Views_Source + } + $title = sprintf(__('%s Commit Details'), (string) $request->project); + $page_title = sprintf(__('%s Commit Details - %s'), (string) $request->project, $commit); +- $cobject = $scm->getCommit($commit); ++ $cobject = $scm->getCommit($commit, true); + $rcommit = IDF_Commit::getOrAdd($cobject, $request->project); + $diff = new IDF_Diff($cobject->changes); + $diff->parse(); diff --git a/indefero/src/IDF/Tests/test-diff-view.html b/indefero/src/IDF/Tests/test-diff-view.html new file mode 100644 index 0000000..cb9e085 --- /dev/null +++ b/indefero/src/IDF/Tests/test-diff-view.html @@ -0,0 +1,125 @@ +{extends "idf/issues/base.html"} +{block titleicon}{if $form}
{/if}{/block} +{block body} +{assign $i = 0} +{assign $nc = $comments.count()} +{foreach $comments as $c} +
{assign $who = $c.get_submitter()}{aurl 'whourl', 'IDF_Views_User::view', array($who.login)} +{if $i == 0} +

{blocktrans}Reported by {$who}, {$c.creation_dtime|date}{/blocktrans}

+{else} +{aurl 'url', 'IDF_Views_Issue::view', array($project.shortname, $issue.id)} +{assign $id = $c.id} +{assign $url = $url~'#ic'~$c.id} +

{blocktrans}Comment {$i} by {$who}, {$c.creation_dtime|date}{/blocktrans}

+{/if} + +
{if strlen($c.content) > 0}{issuetext $c.content, $request}{else}{trans '(No comments were given for this change.)'}{/if}
+{assign $attachments = $c.get_attachment_list()} +{if $attachments.count() > 0} +
+
    +{foreach $attachments as $a}
  • {$a.filename} - {$a.filesize|size}
  • {/foreach} +
{/if} +{if $i> 0 and $c.changedIssue()} +
+{foreach $c.changes as $w => $v} +{if $w == 'su'}{trans 'Summary:'}{/if}{if $w == 'st'}{trans 'Status:'}{/if}{if $w == 'ow'}{trans 'Owner:'}{/if}{if $w == 'lb'}{trans 'Labels:'}{/if} {if $w == 'lb'}{assign $l = implode(', ', $v)}{$l}{else}{$v}{/if}
+{/foreach} +
+{/if} +
{assign $i = $i + 1}{if $i == $nc and false == $form} + +{/if} +{/foreach} + +{if $form} +
+ +{if $form.errors} +
+

{trans 'The form contains some errors. Please correct them to change the issue.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +
+{/if} + +{if $closed and (!$isOwner and !$isMember)} +

 {blocktrans}This issue is marked as closed, add a comment only if you think this issue is still valid and more work is needed to fully fix it.{/blocktrans}

+ +{/if} +
+ + + + + + + + +{if $isOwner or $isMember} + + + + + + + + + + + + + + + +{/if} + + + + +
{$form.f.content.labelTag}:{if $form.f.content.errors}{$form.f.content.fieldErrors}{/if} +{$form.f.content|unsafe} +
{$form.f.attachment.labelTag}:{if $form.f.attachment.errors}{$form.f.attachment.fieldErrors}{/if} +{$form.f.attachment|unsafe} +
{$form.f.summary.labelTag}:{if $form.f.summary.errors}{$form.f.summary.fieldErrors}{/if} +{$form.f.summary|unsafe} +
{$form.f.status.labelTag}:{if $form.f.status.errors}{$form.f.status.fieldErrors}{/if} +{$form.f.status|unsafe} +
{$form.f.owner.labelTag}:{if $form.f.owner.errors}{$form.f.owner.fieldErrors}{/if} +{$form.f.owner|unsafe} +
{$form.f.label1.labelTag}: +{if $form.f.label1.errors}{$form.f.label1.fieldErrors}{/if}{$form.f.label1|unsafe} +{if $form.f.label2.errors}{$form.f.label2.fieldErrors}{/if}{$form.f.label2|unsafe} +{if $form.f.label3.errors}{$form.f.label3.fieldErrors}{/if}{$form.f.label3|unsafe}
+{if $form.f.label4.errors}{$form.f.label4.fieldErrors}{/if}{$form.f.label4|unsafe} +{if $form.f.label5.errors}{$form.f.label5.fieldErrors}{/if}{$form.f.label5|unsafe} +{if $form.f.label6.errors}{$form.f.label6.fieldErrors}{/if}{$form.f.label6|unsafe} +
  | {trans 'Cancel'} +
+
+{/if} +{/block} +{block context} +
+{assign $submitter = $issue.get_submitter()}{aurl 'url', 'IDF_Views_User::view', array($submitter.login)} +

{trans 'Created:'} {$issue.creation_dtime|dateago} {blocktrans}by {$submitter}{/blocktrans}

+{if $issue.modif_dtime != $issue.creation_dtime}

+{trans 'Updated:'} {$issue.modif_dtime|dateago}

{/if} +

+{trans 'Status:'} {$issue.get_status.name}

+{if $issue.get_owner != null}

{aurl 'url', 'IDF_Views_User::view', array($issue.get_owner().login)} +{trans 'Owner:'} {$issue.get_owner} +

{/if}{assign $tags = $issue.get_tags_list()}{if $tags.count()} +

+{trans 'Labels:'}
+{foreach $tags as $tag}{aurl 'url', 'IDF_Views_Issue::listLabel', array($project.shortname, $tag.id, 'open')} +{$tag.class}:{$tag.name}
+{/foreach} +

{/if} +
+{/block} +{block javascript}{if $form}{include 'idf/issues/js-autocomplete.html'}{/if}{/block} diff --git a/indefero/src/IDF/Tests/test-diff.diff b/indefero/src/IDF/Tests/test-diff.diff new file mode 100644 index 0000000..cd16d08 --- /dev/null +++ b/indefero/src/IDF/Tests/test-diff.diff @@ -0,0 +1,515 @@ +diff --git a/src/IDF/Form/IssueCreate.php b/src/IDF/Form/IssueCreate.php +index 0743e72..67afca7 100644 +--- a/src/IDF/Form/IssueCreate.php ++++ b/src/IDF/Form/IssueCreate.php +@@ -72,8 +72,9 @@ class IDF_Form_IssueCreate extends Pluf_Form + // We add .dummy to try to mitigate security issues in the + // case of someone allowing the upload path to be accessible + // to everybody. +- $filename = substr($md5, 0, 2).'/'.substr($md5, 2, 2).'/'.substr($md5, 4).'/%s.dummy'; +- $this->fields['attachment'] = new Pluf_Form_Field_File( ++ for ($i=1;$i<4;$i++) { ++ $filename = substr($md5, 0, 2).'/'.substr($md5, 2, 2).'/'.substr($md5, 4).'/%s.dummy'; ++ $this->fields['attachment'.$i] = new Pluf_Form_Field_File( + array('required' => false, + 'label' => __('Attach a file'), + 'move_function_params' => +@@ -83,6 +84,7 @@ class IDF_Form_IssueCreate extends Pluf_Form + ) + ) + ); ++ } + + if ($this->show_full) { + $this->fields['status'] = new Pluf_Form_Field_Varchar( +@@ -195,6 +197,21 @@ class IDF_Form_IssueCreate extends Pluf_Form + } + + /** ++ * Clean the attachments post failure. ++ */ ++ function failed() ++ { ++ $upload_path = Pluf::f('upload_issue_path', false); ++ if ($upload_path == false) return; ++ for ($i=1;$i<4;$i++) { ++ if (!empty($this->cleaned_data['attachment'.$i]) and ++ file_exists($upload_path.'/'.$this->cleaned_data['attachment'.$i])) { ++ @unlink($upload_path.'/'.$this->cleaned_data['attachment'.$i]); ++ } ++ } ++ } ++ ++ /** + * Save the model in the database. + * + * @param bool Commit in the database or not. If not, the object +@@ -203,61 +220,63 @@ class IDF_Form_IssueCreate extends Pluf_Form + */ + function save($commit=true) + { +- if ($this->isValid()) { +- // Add a tag for each label +- $tags = array(); +- if ($this->show_full) { +- for ($i=1;$i<7;$i++) { +- if (strlen($this->cleaned_data['label'.$i]) > 0) { +- if (strpos($this->cleaned_data['label'.$i], ':') !== false) { +- list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2); +- list($class, $name) = array(trim($class), trim($name)); +- } else { +- $class = 'Other'; +- $name = trim($this->cleaned_data['label'.$i]); +- } +- $tags[] = IDF_Tag::add($name, $this->project, $class); ++ if (!$this->isValid()) { ++ throw new Exception(__('Cannot save the model from an invalid form.')); ++ } ++ // Add a tag for each label ++ $tags = array(); ++ if ($this->show_full) { ++ for ($i=1;$i<7;$i++) { ++ if (strlen($this->cleaned_data['label'.$i]) > 0) { ++ if (strpos($this->cleaned_data['label'.$i], ':') !== false) { ++ list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2); ++ list($class, $name) = array(trim($class), trim($name)); ++ } else { ++ $class = 'Other'; ++ $name = trim($this->cleaned_data['label'.$i]); + } ++ $tags[] = IDF_Tag::add($name, $this->project, $class); + } +- } else { +- $tags[] = IDF_Tag::add('Medium', $this->project, 'Priority'); +- $tags[] = IDF_Tag::add('Defect', $this->project, 'Type'); +- } +- // Create the issue +- $issue = new IDF_Issue(); +- $issue->project = $this->project; +- $issue->submitter = $this->user; +- if ($this->show_full) { +- $issue->status = IDF_Tag::add(trim($this->cleaned_data['status']), $this->project, 'Status'); +- $issue->owner = self::findUser($this->cleaned_data['owner']); +- } else { +- $_t = $this->project->getTagIdsByStatus('open'); +- $issue->status = new IDF_Tag($_t[0]); // first one is the default +- $issue->owner = null; +- } +- $issue->summary = trim($this->cleaned_data['summary']); +- $issue->create(); +- foreach ($tags as $tag) { +- $issue->setAssoc($tag); + } +- // add the first comment +- $comment = new IDF_IssueComment(); +- $comment->issue = $issue; +- $comment->content = $this->cleaned_data['content']; +- $comment->submitter = $this->user; +- $comment->create(); +- // If we have a file, create the IDF_IssueFile and attach +- // it to the comment. +- if ($this->cleaned_data['attachment']) { ++ } else { ++ $tags[] = IDF_Tag::add('Medium', $this->project, 'Priority'); ++ $tags[] = IDF_Tag::add('Defect', $this->project, 'Type'); ++ } ++ // Create the issue ++ $issue = new IDF_Issue(); ++ $issue->project = $this->project; ++ $issue->submitter = $this->user; ++ if ($this->show_full) { ++ $issue->status = IDF_Tag::add(trim($this->cleaned_data['status']), $this->project, 'Status'); ++ $issue->owner = self::findUser($this->cleaned_data['owner']); ++ } else { ++ $_t = $this->project->getTagIdsByStatus('open'); ++ $issue->status = new IDF_Tag($_t[0]); // first one is the default ++ $issue->owner = null; ++ } ++ $issue->summary = trim($this->cleaned_data['summary']); ++ $issue->create(); ++ foreach ($tags as $tag) { ++ $issue->setAssoc($tag); ++ } ++ // add the first comment ++ $comment = new IDF_IssueComment(); ++ $comment->issue = $issue; ++ $comment->content = $this->cleaned_data['content']; ++ $comment->submitter = $this->user; ++ $comment->create(); ++ // If we have a file, create the IDF_IssueFile and attach ++ // it to the comment. ++ for ($i=1;$i<4;$i++) { ++ if ($this->cleaned_data['attachment'.$i]) { + $file = new IDF_IssueFile(); +- $file->attachment = $this->cleaned_data['attachment']; ++ $file->attachment = $this->cleaned_data['attachment'.$i]; + $file->submitter = $this->user; + $file->comment = $comment; + $file->create(); + } +- return $issue; + } +- throw new Exception(__('Cannot save the model from an invalid form.')); ++ return $issue; + } + + /** +diff --git a/src/IDF/Form/IssueUpdate.php b/src/IDF/Form/IssueUpdate.php +index 550889e..0d36e72 100644 +--- a/src/IDF/Form/IssueUpdate.php ++++ b/src/IDF/Form/IssueUpdate.php +@@ -68,8 +68,9 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate + // We add .dummy to try to mitigate security issues in the + // case of someone allowing the upload path to be accessible + // to everybody. +- $filename = substr($md5, 0, 2).'/'.substr($md5, 2, 2).'/'.substr($md5, 4).'/%s.dummy'; +- $this->fields['attachment'] = new Pluf_Form_Field_File( ++ for ($i=1;$i<4;$i++) { ++ $filename = substr($md5, 0, 2).'/'.substr($md5, 2, 2).'/'.substr($md5, 4).'/%s.dummy'; ++ $this->fields['attachment'.$i] = new Pluf_Form_Field_File( + array('required' => false, + 'label' => __('Attach a file'), + 'move_function_params' => +@@ -79,6 +80,7 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate + ) + ) + ); ++ } + + if ($this->show_full) { + $this->fields['status'] = new Pluf_Form_Field_Varchar( +@@ -124,6 +126,21 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate + } + + /** ++ * Clean the attachments post failure. ++ */ ++ function failed() ++ { ++ $upload_path = Pluf::f('upload_issue_path', false); ++ if ($upload_path == false) return; ++ for ($i=1;$i<4;$i++) { ++ if (!empty($this->cleaned_data['attachment'.$i]) and ++ file_exists($upload_path.'/'.$this->cleaned_data['attachment'.$i])) { ++ @unlink($upload_path.'/'.$this->cleaned_data['attachment'.$i]); ++ } ++ } ++ } ++ ++ /** + * We check that something is really changed. + */ + public function clean() +@@ -202,90 +219,92 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate + */ + function save($commit=true) + { +- if ($this->isValid()) { +- if ($this->show_full) { +- // Add a tag for each label +- $tags = array(); +- $tagids = array(); +- for ($i=1;$i<7;$i++) { +- if (strlen($this->cleaned_data['label'.$i]) > 0) { +- if (strpos($this->cleaned_data['label'.$i], ':') !== false) { +- list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2); +- list($class, $name) = array(trim($class), trim($name)); +- } else { +- $class = 'Other'; +- $name = trim($this->cleaned_data['label'.$i]); +- } +- $tag = IDF_Tag::add($name, $this->project, $class); +- $tags[] = $tag; +- $tagids[] = $tag->id; ++ if (!$this->isValid()) { ++ throw new Exception(__('Cannot save the model from an invalid form.')); ++ } ++ if ($this->show_full) { ++ // Add a tag for each label ++ $tags = array(); ++ $tagids = array(); ++ for ($i=1;$i<7;$i++) { ++ if (strlen($this->cleaned_data['label'.$i]) > 0) { ++ if (strpos($this->cleaned_data['label'.$i], ':') !== false) { ++ list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2); ++ list($class, $name) = array(trim($class), trim($name)); ++ } else { ++ $class = 'Other'; ++ $name = trim($this->cleaned_data['label'.$i]); + } ++ $tag = IDF_Tag::add($name, $this->project, $class); ++ $tags[] = $tag; ++ $tagids[] = $tag->id; + } +- // Compare between the old and the new data +- $changes = array(); +- $oldtags = $this->issue->get_tags_list(); +- foreach ($tags as $tag) { +- if (!Pluf_Model_InArray($tag, $oldtags)) { +- if (!isset($changes['lb'])) $changes['lb'] = array(); +- if ($tag->class != 'Other') { +- $changes['lb'][] = (string) $tag; //new tag +- } else { +- $changes['lb'][] = (string) $tag->name; +- } ++ } ++ // Compare between the old and the new data ++ $changes = array(); ++ $oldtags = $this->issue->get_tags_list(); ++ foreach ($tags as $tag) { ++ if (!Pluf_Model_InArray($tag, $oldtags)) { ++ if (!isset($changes['lb'])) $changes['lb'] = array(); ++ if ($tag->class != 'Other') { ++ $changes['lb'][] = (string) $tag; //new tag ++ } else { ++ $changes['lb'][] = (string) $tag->name; + } + } +- foreach ($oldtags as $tag) { +- if (!Pluf_Model_InArray($tag, $tags)) { +- if (!isset($changes['lb'])) $changes['lb'] = array(); +- if ($tag->class != 'Other') { +- $changes['lb'][] = '-'.(string) $tag; //new tag +- } else { +- $changes['lb'][] = '-'.(string) $tag->name; +- } ++ } ++ foreach ($oldtags as $tag) { ++ if (!Pluf_Model_InArray($tag, $tags)) { ++ if (!isset($changes['lb'])) $changes['lb'] = array(); ++ if ($tag->class != 'Other') { ++ $changes['lb'][] = '-'.(string) $tag; //new tag ++ } else { ++ $changes['lb'][] = '-'.(string) $tag->name; + } + } +- // Status, summary and owner +- $status = IDF_Tag::add(trim($this->cleaned_data['status']), $this->project, 'Status'); +- if ($status->id != $this->issue->status) { +- $changes['st'] = $status->name; +- } +- if (trim($this->issue->summary) != trim($this->cleaned_data['summary'])) { +- $changes['su'] = trim($this->cleaned_data['summary']); +- } +- $owner = self::findUser($this->cleaned_data['owner']); +- if ((is_null($owner) and !is_null($this->issue->get_owner())) +- or (!is_null($owner) and is_null($this->issue->get_owner())) +- or ((!is_null($owner) and !is_null($this->issue->get_owner())) and $owner->id != $this->issue->get_owner()->id)) { +- $changes['ow'] = (is_null($owner)) ? '---' : $owner->login; +- } +- // Update the issue +- $this->issue->batchAssoc('IDF_Tag', $tagids); +- $this->issue->summary = trim($this->cleaned_data['summary']); +- $this->issue->status = $status; +- $this->issue->owner = $owner; + } +- // Create the comment +- $comment = new IDF_IssueComment(); +- $comment->issue = $this->issue; +- $comment->content = $this->cleaned_data['content']; +- $comment->submitter = $this->user; +- if (!$this->show_full) $changes = array(); +- $comment->changes = $changes; +- $comment->create(); +- $this->issue->update(); +- if ($this->issue->owner != $this->user->id and +- $this->issue->submitter != $this->user->id) { +- $this->issue->setAssoc($this->user); // interested user. ++ // Status, summary and owner ++ $status = IDF_Tag::add(trim($this->cleaned_data['status']), $this->project, 'Status'); ++ if ($status->id != $this->issue->status) { ++ $changes['st'] = $status->name; + } +- if ($this->cleaned_data['attachment']) { ++ if (trim($this->issue->summary) != trim($this->cleaned_data['summary'])) { ++ $changes['su'] = trim($this->cleaned_data['summary']); ++ } ++ $owner = self::findUser($this->cleaned_data['owner']); ++ if ((is_null($owner) and !is_null($this->issue->get_owner())) ++ or (!is_null($owner) and is_null($this->issue->get_owner())) ++ or ((!is_null($owner) and !is_null($this->issue->get_owner())) and $owner->id != $this->issue->get_owner()->id)) { ++ $changes['ow'] = (is_null($owner)) ? '---' : $owner->login; ++ } ++ // Update the issue ++ $this->issue->batchAssoc('IDF_Tag', $tagids); ++ $this->issue->summary = trim($this->cleaned_data['summary']); ++ $this->issue->status = $status; ++ $this->issue->owner = $owner; ++ } ++ // Create the comment ++ $comment = new IDF_IssueComment(); ++ $comment->issue = $this->issue; ++ $comment->content = $this->cleaned_data['content']; ++ $comment->submitter = $this->user; ++ if (!$this->show_full) $changes = array(); ++ $comment->changes = $changes; ++ $comment->create(); ++ $this->issue->update(); ++ if ($this->issue->owner != $this->user->id and ++ $this->issue->submitter != $this->user->id) { ++ $this->issue->setAssoc($this->user); // interested user. ++ } ++ for ($i=1;$i<4;$i++) { ++ if ($this->cleaned_data['attachment'.$i]) { + $file = new IDF_IssueFile(); +- $file->attachment = $this->cleaned_data['attachment']; ++ $file->attachment = $this->cleaned_data['attachment'.$i]; + $file->submitter = $this->user; + $file->comment = $comment; + $file->create(); + } +- return $this->issue; + } +- throw new Exception(__('Cannot save the model from an invalid form.')); ++ return $this->issue; + } + } +diff --git a/src/IDF/IssueFile.php b/src/IDF/IssueFile.php +index f4367dd..f0745e8 100644 +--- a/src/IDF/IssueFile.php ++++ b/src/IDF/IssueFile.php +@@ -114,6 +114,7 @@ class IDF_IssueFile extends Pluf_Model + $this->filename = substr(basename($file), 0, -6); + $img_extensions = array('jpeg', 'jpg', 'png', 'gif'); + $info = pathinfo($this->filename); ++ if (!isset($info['extension'])) $info['extension'] = ''; + if (in_array(strtolower($info['extension']), $img_extensions)) { + $this->type = 'img'; + } else { +diff --git a/src/IDF/templates/idf/issues/create.html b/src/IDF/templates/idf/issues/create.html +index e8f4a5b..faaa743 100644 +--- a/src/IDF/templates/idf/issues/create.html ++++ b/src/IDF/templates/idf/issues/create.html +@@ -24,10 +24,22 @@ + {$form.f.content|unsafe} + + +- +-{$form.f.attachment.labelTag}: +-{if $form.f.attachment.errors}{$form.f.attachment.fieldErrors}{/if} +-{$form.f.attachment|unsafe} ++ ++{$form.f.attachment1.labelTag}: ++{if $form.f.attachment1.errors}{$form.f.attachment1.fieldErrors}{/if} ++{$form.f.attachment1|unsafe} ++ ++ ++ ++{$form.f.attachment2.labelTag}: ++{if $form.f.attachment2.errors}{$form.f.attachment2.fieldErrors}{/if} ++{$form.f.attachment2|unsafe} ++ ++ ++ ++{$form.f.attachment3.labelTag}: ++{if $form.f.attachment3.errors}{$form.f.attachment3.fieldErrors}{/if} ++{$form.f.attachment3|unsafe} + + {if $isOwner or $isMember} + +@@ -74,7 +86,34 @@ + {/block} + {block javascript} + ++{/literal}{/block} ++ + {include 'idf/issues/js-autocomplete.html'}{/block} + +diff --git a/src/IDF/templates/idf/issues/view.html b/src/IDF/templates/idf/issues/view.html +index cb9e085..ad56d05 100644 +--- a/src/IDF/templates/idf/issues/view.html ++++ b/src/IDF/templates/idf/issues/view.html +@@ -59,10 +59,22 @@ + {$form.f.content|unsafe} + + +- +-{$form.f.attachment.labelTag}: +-{if $form.f.attachment.errors}{$form.f.attachment.fieldErrors}{/if} +-{$form.f.attachment|unsafe} ++ ++{$form.f.attachment1.labelTag}: ++{if $form.f.attachment1.errors}{$form.f.attachment1.fieldErrors}{/if} ++{$form.f.attachment1|unsafe} ++ ++ ++ ++{$form.f.attachment2.labelTag}: ++{if $form.f.attachment2.errors}{$form.f.attachment2.fieldErrors}{/if} ++{$form.f.attachment2|unsafe} ++ ++ ++ ++{$form.f.attachment3.labelTag}: ++{if $form.f.attachment3.errors}{$form.f.attachment3.fieldErrors}{/if} ++{$form.f.attachment3|unsafe} + + {if $isOwner or $isMember} + +@@ -122,4 +134,33 @@ +

{/if} + + {/block} +-{block javascript}{if $form}{include 'idf/issues/js-autocomplete.html'}{/if}{/block} ++{block javascript}{if $form}{include 'idf/issues/js-autocomplete.html'} ++ ++{/if}{/block} +diff --git a/www/media/idf/img/attachment.png b/www/media/idf/img/attachment.png +new file mode 100644 +index 0000000..529bb7f +Binary files /dev/null and b/www/media/idf/img/attachment.png differ \ No newline at end of file diff --git a/indefero/src/IDF/Tests/test-log.txt b/indefero/src/IDF/Tests/test-log.txt new file mode 100644 index 0000000..07e0362 --- /dev/null +++ b/indefero/src/IDF/Tests/test-log.txt @@ -0,0 +1,210 @@ +commit cf9360a1a87f8a98dc506a316055537b95ec245f +Author: Loic d'Anterroches +Date: Sat Aug 2 09:48:55 2008 +0200 + + Fixed the middleware to correctly return a 404 error if the project is + not found. + +commit 953d7c4ecd37e2c89058b656ee586ae73bfe1e8f +Author: Loic d'Anterroches +Date: Sat Aug 2 09:48:35 2008 +0200 + + Added the name of the login view. + +commit f4f8f9615ab460b9966509bd60b740c84ec9ecc9 +Author: Loic d'Anterroches +Date: Sat Aug 2 09:42:05 2008 +0200 + + Added the link to commit and issues in the changelog. + +commit 4c5bd8d2be673c9d86d8b6b5108d551982491d5c +Author: Loic d'Anterroches +Date: Sat Aug 2 09:38:06 2008 +0200 + + Fixed bug when looking at a commit which is a merge. + + When you merge you do not get always a diff of files. This fix correct + that for the case of commit 9a2b8e249acad9f844. + +commit fd6031d7f50085b2e42bb539a886fc9175f6fe27 +Author: Loic d'Anterroches +Date: Fri Aug 1 22:18:58 2008 +0200 + + Fixed SQL to follow the standards. + +commit 83658ac860328568d8570cbbadde565de8348be9 +Author: Loic d'Anterroches +Date: Fri Aug 1 22:15:49 2008 +0200 + + Fixed to have standard SQL. + +commit 593afd9b8b18efde2a7817d57e8f101112aaa6fe +Author: Loic d'Anterroches +Date: Fri Aug 1 22:13:25 2008 +0200 + + Fix for PostgreSQL. + +commit a831c749d849f903f84698c36666affd391aa04d +Author: Loic d'Anterroches +Date: Fri Aug 1 22:03:56 2008 +0200 + + Fixed boolean for PostgreSQL. + +commit 7d806325579547facd27a0c44b54872fe9d7fb2d +Author: Loic d'Anterroches +Date: Fri Aug 1 00:50:44 2008 +0200 + + Added code indentation. + +commit 80ce87009e0249b7faf1143075bb4006bd2f8e35 +Author: Loic d'Anterroches +Date: Fri Aug 1 00:38:29 2008 +0200 + + Added a better commit diff. + +commit cb15f036fe91edb9c07ff07f13bc592a8877f3c2 +Author: Loic d'Anterroches +Date: Thu Jul 31 22:54:02 2008 +0200 + + Fixed some typos. + +commit 1b3a42940d30abb342d9c4b8ff166a586701b784 +Author: Loic d'Anterroches +Date: Thu Jul 31 22:50:21 2008 +0200 + + Added the registration procedure. + +commit 416d13e249da7d8717ebb15966b9dbbd5c0188ba +Author: Loic d'Anterroches +Date: Tue Jul 29 22:33:13 2008 +0200 + + Added the registration form. + + Still need a lot :) + +commit c50e218704dcc81eb346cc757e4c1bdbd0808d8b +Author: Loic d'Anterroches +Date: Tue Jul 29 21:18:02 2008 +0200 + + Added a project home. + +commit ccf24df13120ae1e64225ec27db1ee647c9df4d4 +Author: Loic d'Anterroches +Date: Tue Jul 29 15:13:40 2008 +0200 + + Link to the corresponding tree in the commit view. + +commit a6716c77160c9bbb4829eff5c6e11c7b9a4f6d50 +Author: Loic d'Anterroches +Date: Mon Jul 28 22:09:17 2008 +0200 + + Added the visualisation of a commit. + +commit 3fb47562ce0453af4481b1b470581f5bcbbc6b3b +Author: Loic d'Anterroches +Date: Mon Jul 28 20:31:23 2008 +0200 + + Automatically create links in the issue description and comments. + + Link to issues but also commits. + +commit 3dbae6272a9f239499038f069f6472dfceb5e73e +Author: Loic d'Anterroches +Date: Sun Jul 27 21:38:49 2008 +0200 + + Added smooth handling of bad files and commits. + + Now simply redirect to the root of the first available branch. + +commit 8a0a35726cd82e3003675d8ba432efe68f7c4f74 +Author: Loic d'Anterroches +Date: Sun Jul 27 17:46:04 2008 +0200 + + Fixed typo. + +commit b6084cbf070bf9e78101b1088d5d6c0d852ed6dc +Author: Loic d'Anterroches +Date: Sun Jul 27 17:43:51 2008 +0200 + + Improved the support of the git browser. + + Now the reference is always a commit as from a commit it is always possible to travel back to the corresponding tree and blobs. + +commit 9a2b8e249acad9f84401846cf87bf040ffd585b3 +Merge: 789c7ed... 24e8c80... +Author: Loic d'Anterroches +Date: Sun Jul 27 01:51:55 2008 +0200 + + Merge branch 'gitbrowser' + +commit 789c7ed43d2b551ba9de97dc8af87cb8d6fa208c +Author: Loic d'Anterroches +Date: Sun Jul 27 01:51:08 2008 +0200 + + Take into account if in one branch but listing another. + + Need to check how this is working on a bar repository. + +commit 24e8c80dfbd358710464cda0e5570655d5f200c6 +Author: Loic d'Anterroches +Date: Sun Jul 27 01:37:43 2008 +0200 + + Updated the docstring. + +commit c915f8fccfc20a1a491bb88dd7848005dc1641ff +Author: Loic d'Anterroches +Date: Sun Jul 27 01:31:10 2008 +0200 + + Added the changelog and fixed the source browser. + + The source browser is normally a little bit more robust. + +commit f57a0ec08bfbaa830f4f7fb39f1f7e39d400ecb3 +Author: Loic d'Anterroches +Date: Sat Jul 26 20:17:18 2008 +0200 + + Cosmetic improvements. + +commit 876e206742179ba640667430b5cad6b45c651250 +Author: Loic d'Anterroches +Date: Sat Jul 26 18:42:41 2008 +0200 + + First work on the git browser. + +commit 2e711bee8d2b7c6680d6d44cb796f2cc67c9ed68 +Author: Loic d'Anterroches +Date: Fri Jul 25 14:25:50 2008 +0200 + + Added a nice formatting of the issue comments. + +commit 4eea3797b26cb3ab34c5b4e1b7ff5098f2284deb +Author: Loic d'Anterroches +Date: Fri Jul 25 14:15:58 2008 +0200 + + Added the autocompletion of the owner and cosmetic changes. + +commit e5d296d8638db9bd59a85360d80e126b901befeb +Author: Loic d'Anterroches +Date: Fri Jul 25 11:17:56 2008 +0200 + + Added the Shift+w hotkey to get the working list of the user. + +commit d19dbb441c86740d6a2df2501cb5875a5fc34e19 +Author: Loic d'Anterroches +Date: Fri Jul 25 11:16:18 2008 +0200 + + Added a hotkey tag to easily add them. + + Added a new Shift+m hotkey to access the list of submitted issues. + +commit cc5ec30e6a06a3c855848b907512e4b796950981 +Author: Loic d'Anterroches +Date: Fri Jul 25 10:28:35 2008 +0200 + + Correctly set the copyrights. + +commit efbd82fccb20b0b4c9ac82777b8bdf7d83be0e40 +Author: Loic d'Anterroches +Date: Fri Jul 25 10:26:05 2008 +0200 + + Initial commit. diff --git a/indefero/src/IDF/Timeline.php b/indefero/src/IDF/Timeline.php new file mode 100644 index 0000000..a053121 --- /dev/null +++ b/indefero/src/IDF/Timeline.php @@ -0,0 +1,159 @@ +_a['table'] = 'idf_timeline'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + 'blank' => true, + ), + 'project' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_Project', + 'blank' => false, + 'relate_name' => 'thumbroll', + ), + 'author' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'Pluf_User', + 'is_null' => true, + 'help_text' => 'This will allow us to list the latest commits of a user in its profile.', + ), + 'model_class' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 150, + ), + 'model_id' => + array( + 'type' => 'Pluf_DB_Field_Integer', + 'blank' => false, + ), + 'creation_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'index' => true, + ), + 'public_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'index' => true, + ), + ); + } + + function __toString() + { + return $this->summary.' - ('.$this->scm_id.')'; + } + + function _toIndex() + { + $str = str_repeat($this->summary.' ', 4).' '.$this->fullmessage; + return Pluf_Text::cleanString(html_entity_decode($str, ENT_QUOTES, 'UTF-8')); + } + + function preSave($create=false) + { + if ($this->id == '') { + $this->public_dtime = gmdate('Y-m-d H:i:s'); + } + if ($this->creation_dtime == '') { + $this->creation_dtime = gmdate('Y-m-d H:i:s'); + } + } + + /** + * Easily insert an item in the timeline. + * + * @param mixed Item to be inserted + * @param IDF_Project Project of the item + * @param Pluf_User Author of the item (null) + * @param string GMT creation date time (null) + * @return bool Success + */ + public static function insert($item, $project, $author=null, $creation=null) + { + $t = new IDF_Timeline(); + $t->project = $project; + $t->author = $author; + $t->creation_dtime = (is_null($creation)) ? '' : $creation; + $t->model_id = $item->id; + $t->model_class = $item->_model; + $t->create(); + return $t; + } + + /** + * Remove an item from the timeline. + * + * You must call this function when you delete items wich are + * tracked in the timeline. Just add the call: + * + * IDF_Timeline::remove($this); + * + * in the preDelete() method of your object. + * + * @param mixed Item to be removed + * @return bool Success + */ + public static function remove($item) + { + if ($item->id > 0) { + $sql = new Pluf_SQL('model_id=%s AND model_class=%s', + array($item->id, $item->_model)); + $items = Pluf::factory('IDF_Timeline')->getList(array('filter'=>$sql->gen())); + foreach ($items as $tl) { + $tl->delete(); + } + } + return true; + } +} diff --git a/indefero/src/IDF/Timeline/Paginator.php b/indefero/src/IDF/Timeline/Paginator.php new file mode 100644 index 0000000..7d3ff72 --- /dev/null +++ b/indefero/src/IDF/Timeline/Paginator.php @@ -0,0 +1,56 @@ +model_class, $item->model_id); + $doc->public_dtime = $item->public_dtime; + $item_day = Pluf_Template_dateFormat($item->creation_dtime, + '%y-%m-%d'); + $out = ''; + if ($this->current_day == null or + Pluf_Date::dayCompare($this->current_day, $item_day) != 0) { + $day = Pluf_Template_dateFormat($item->creation_dtime); + if ($item_day == Pluf_Template_timeFormat(time(), 'y-m-d')) { + $day = __('Today'); + } + $out = ''.$day.''."\n"; + $this->current_day = $item_day; + } + return $out.$doc->timelineFragment($item->request); + } +} diff --git a/indefero/src/IDF/Upload.php b/indefero/src/IDF/Upload.php new file mode 100644 index 0000000..2fa7aec --- /dev/null +++ b/indefero/src/IDF/Upload.php @@ -0,0 +1,324 @@ +_a['table'] = 'idf_uploads'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + 'blank' => true, + ), + 'project' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_Project', + 'blank' => false, + 'verbose' => __('project'), + 'relate_name' => 'downloads', + ), + 'summary' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 250, + 'verbose' => __('summary'), + ), + 'changelog' => + array( + 'type' => 'Pluf_DB_Field_Text', + 'blank' => true, + 'verbose' => __('changes'), + ), + 'file' => + array( + 'type' => 'Pluf_DB_Field_File', + 'blank' => false, + 'default' => 0, + 'verbose' => __('file'), + 'help_text' => __('The path is relative to the upload path.'), + ), + 'filesize' => + array( + 'type' => 'Pluf_DB_Field_Integer', + 'blank' => false, + 'default' => 0, + 'verbose' => __('file size in bytes'), + ), + 'md5' => + array( + 'type' => 'Pluf_DB_Field_Text', + 'blank' => true, + 'verbose' => __('MD5'), + ), + 'submitter' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'Pluf_User', + 'blank' => false, + 'verbose' => __('submitter'), + 'relate_name' => 'submitted_downloads', + ), + 'tags' => + array( + 'type' => 'Pluf_DB_Field_Manytomany', + 'blank' => true, + 'model' => 'IDF_Tag', + 'verbose' => __('labels'), + ), + 'downloads' => + array( + 'type' => 'Pluf_DB_Field_Integer', + 'blank' => false, + 'default' => 0, + 'verbose' => __('number of downloads'), + ), + 'creation_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('creation date'), + ), + 'modif_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('modification date'), + ), + ); + $this->_a['idx'] = array( + 'modif_dtime_idx' => + array( + 'col' => 'modif_dtime', + 'type' => 'normal', + ), + ); + $table = $this->_con->pfx.'idf_tag_idf_upload_assoc'; + $this->_a['views'] = array( + 'join_tags' => + array( + 'join' => 'LEFT JOIN '.$table + .' ON idf_upload_id=id', + ), + ); + } + + function __toString() + { + return $this->file; + } + + function _toIndex() + { + return ''; + } + + function preSave($create=false) + { + if ($this->id == '') { + $this->creation_dtime = gmdate('Y-m-d H:i:s'); + $this->modif_dtime = gmdate('Y-m-d H:i:s'); + $this->md5 = md5_file ($this->getFullPath()); + } + } + + function postSave($create=false) + { + if ($create) { + IDF_Timeline::insert($this, $this->get_project(), + $this->get_submitter(), $this->creation_dtime); + } + } + + function getAbsoluteUrl($project) + { + return Pluf::f('url_upload').'/'.$project->shortname.'/files/'.$this->file; + } + + function getFullPath() + { + return(Pluf::f('upload_path').'/'.$this->get_project()->shortname.'/files/'.$this->file); + } + + /** + * We drop the information from the timeline. + */ + function preDelete() + { + IDF_Timeline::remove($this); + @unlink(Pluf::f('upload_path').'/'.$this->project->shortname.'/files/'.$this->file); + } + + /** + * Returns the timeline fragment for the file. + * + * + * @param Pluf_HTTP_Request + * @return Pluf_Template_SafeString + */ + public function timelineFragment($request) + { + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Download::view', + array($request->project->shortname, + $this->id)); + $out = ''. + Pluf_esc(Pluf_Template_dateAgo($this->creation_dtime, 'without')). + ''; + $stag = new IDF_Template_ShowUser(); + $user = $stag->start($this->get_submitter(), $request, '', false); + $out .= sprintf(__('Download %2$d, %3$s'), $url, $this->id, Pluf_esc($this->summary)).''; + $out .= ''; + $out .= "\n".' +
'.sprintf(__('Addition of download %2$d, by %3$s'), $url, $this->id, $user).'
'; + return Pluf_Template::markSafe($out); + } + + public function feedFragment($request) + { + $url = Pluf::f('url_base') + .Pluf_HTTP_URL_urlForView('IDF_Views_Download::view', + array($request->project->shortname, + $this->id)); + $title = sprintf(__('%1$s: Download %2$d added - %3$s'), + $request->project->name, + $this->id, $this->summary); + $date = Pluf_Date::gmDateToGmString($this->creation_dtime); + $context = new Pluf_Template_Context_Request( + $request, + array('url' => $url, + 'title' => $title, + 'file' => $this, + 'date' => $date) + ); + $tmpl = new Pluf_Template('idf/downloads/feedfragment.xml'); + return $tmpl->render($context); + } + + /** + * Notification of change of the object. + * + * @param IDF_Conf Current configuration + * @param bool Creation (true) + */ + public function notify($conf, $create=true) + { + $project = $this->get_project(); + $url = str_replace(array('%p', '%d'), + array($project->shortname, $this->id), + $conf->getVal('upload_webhook_url', '')); + + $tags = array(); + foreach ($this->get_tags_list() as $tag) { + $tags[] = $tag->class.':'.$tag->name; + } + + $submitter = $this->get_submitter(); + $payload = array( + 'to_send' => array( + 'project' => $project->shortname, + 'id' => $this->id, + 'summary' => $this->summary, + 'changelog' => $this->changelog, + 'filename' => $this->file, + 'filesize' => $this->filesize, + 'md5sum' => $this->md5, + 'submitter_login' => $submitter->login, + 'submitter_email' => $submitter->email, + 'tags' => $tags, + ), + 'project_id' => $project->id, + 'authkey' => $project->getWebHookKey(), + 'url' => $url, + ); + + if ($create === true) { + $payload['method'] = 'PUT'; + $payload['to_send']['creation_date'] = $this->creation_dtime; + } else { + $payload['method'] = 'POST'; + $payload['to_send']['update_date'] = $this->modif_dtime; + } + + $item = new IDF_Queue(); + $item->type = 'upload'; + $item->payload = $payload; + $item->create(); + + $current_locale = Pluf_Translation::getLocale(); + + $from_email = Pluf::f('from_email'); + $messageId = '<'.md5('upload'.$this->id.md5(Pluf::f('secret_key'))).'@'.Pluf::f('mail_host', 'localhost').'>'; + $recipients = $project->getNotificationRecipientsForTab('downloads'); + + foreach ($recipients as $address => $language) { + + if ($this->get_submitter()->email === $address) { + continue; + } + + Pluf_Translation::loadSetLocale($language); + + $context = new Pluf_Template_Context(array( + 'file' => $this, + 'urlfile' => $this->getAbsoluteUrl($project), + 'project' => $project, + 'tags' => $this->get_tags_list(), + )); + + $tplfile = 'idf/downloads/download-created-email.txt'; + $subject = __('New download - %1$s (%2$s)'); + $headers = array('Message-ID' => $messageId); + if (!$create) { + $tplfile = 'idf/downloads/download-updated-email.txt'; + $subject = __('Updated download - %1$s (%2$s)'); + $headers = array('References' => $messageId); + } + + $tmpl = new Pluf_Template($tplfile); + $text_email = $tmpl->render($context); + + $email = new Pluf_Mail($from_email, + $address, + sprintf($subject, + $this->summary, + $project->shortname)); + $email->addTextMessage($text_email); + $email->addHeaders($headers); + $email->sendMail(); + } + + Pluf_Translation::loadSetLocale($current_locale); + } +} diff --git a/indefero/src/IDF/UserData.php b/indefero/src/IDF/UserData.php new file mode 100644 index 0000000..7862661 --- /dev/null +++ b/indefero/src/IDF/UserData.php @@ -0,0 +1,59 @@ +setVal($key, $value); + } + + function __get($key) + { + if (in_array($key, self::$protectedVars)) + return parent::__get($key); + return $this->getVal($key, null); + } + + public static function factory($user) + { + $conf = new IDF_UserData(); + $conf->setModel((object) array('_model'=>'IDF_UserData', 'id' => $user->id)); + $conf->initCache(); + return $conf; + } +} diff --git a/indefero/src/IDF/Views.php b/indefero/src/IDF/Views.php new file mode 100644 index 0000000..1e1b22f --- /dev/null +++ b/indefero/src/IDF/Views.php @@ -0,0 +1,540 @@ +isCustomForgePageEnabled()) { + $url = Pluf_HTTP_URL_urlForView('IDF_Views::listProjects'); + return new Pluf_HTTP_Response_Redirect($url); + } + + return Pluf_Shortcuts_RenderToResponse('idf/index.html', + array('page_title' => __('Welcome'), + 'content' => $forge->getCustomForgePageContent(), + ), + $request); + } + + /** + * List all projects unfiltered + * + * @param unknown_type $request + * @param unknown_type $match + * @return Pluf_HTTP_Response + */ + public function listProjects($request, $match) + { + $match = array('', 'all', 'name'); + return $this->listProjectsByLabel($request, $match); + } + + /** + * List projects, optionally filtered by label + * + * @param unknown_type $request + * @param unknown_type $match + * @return Pluf_HTTP_Response + */ + public function listProjectsByLabel($request, $match) + { + list(, $tagId, $order) = $match; + + $tag = false; + if ($tagId !== 'all') { + $tag = Pluf::factory('IDF_Tag')->get($match[1]); + // ignore non-global tags + if ($tag !== false && $tag->project > 0) { + $tag = false; + } + } + $order = in_array($order, array('name', 'activity')) ? $order : 'name'; + + $projects = self::getProjects($request->user, $tag, $order); + $stats = self::getProjectsStatistics($projects); + $projectLabels = self::getProjectLabelsWithCounts($request->user); + + return Pluf_Shortcuts_RenderToResponse('idf/listProjects.html', + array('page_title' => __('Projects'), + 'projects' => $projects, + 'projectLabels' => $projectLabels, + 'tag' => $tag, + 'order' => $order, + 'stats' => new Pluf_Template_ContextVars($stats)), + $request); + } + + /** + * Login view. + */ + public function login($request, $match) + { + if (isset($request->POST['action']) + and $request->POST['action'] == 'new-user') { + $login = (isset($request->POST['login'])) ? $request->POST['login'] : ''; + $url = Pluf_HTTP_URL_urlForView('IDF_Views::register', array(), + array('login' => $login)); + return new Pluf_HTTP_Response_Redirect($url); + } + $v = new Pluf_Views(); + $request->POST['login'] = (isset($request->POST['login'])) ? mb_strtolower($request->POST['login']) : ''; + return $v->login($request, $match, Pluf::f('login_success_url'), + array(), 'idf/login_form.html'); + } + + /** + * Logout view. + */ + function logout($request, $match) + { + $views = new Pluf_Views(); + return $views->logout($request, $match, Pluf::f('after_logout_page')); + } + + /** + * Registration. + * + * We just ask for login, email and to agree with the terms. Then, + * we go ahead and send a confirmation email. The confirmation + * email will allow to set the password, first name and last name + * of the user. + */ + function register($request, $match) + { + $title = __('Create Your Account'); + $params = array('request'=>$request); + if ($request->method == 'POST') { + $form = new IDF_Form_Register(array_merge( + (array)$request->POST, + (array)$request->FILES + ), $params); + if ($form->isValid()) { + $user = $form->save(); // It is sending the confirmation email + $url = Pluf_HTTP_URL_urlForView('IDF_Views::registerInputKey'); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + if (isset($request->GET['login'])) { + $params['initial'] = array('login' => $request->GET['login']); + } + $form = new IDF_Form_Register(null, $params); + } + $context = new Pluf_Template_Context(array()); + $tmpl = new Pluf_Template('idf/terms.html'); + $terms = Pluf_Template::markSafe($tmpl->render($context)); + return Pluf_Shortcuts_RenderToResponse('idf/register/index.html', + array('page_title' => $title, + 'form' => $form, + 'terms' => $terms), + $request); + } + + /** + * Input the registration confirmation key. + * + * Very simple view just to redirect to the register confirmation + * views to input the password. + */ + function registerInputKey($request, $match) + { + $title = __('Confirm Your Account Creation'); + if ($request->method == 'POST') { + $form = new IDF_Form_RegisterInputKey($request->POST); + if ($form->isValid()) { + $url = $form->save(); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $form = new IDF_Form_RegisterInputKey(); + } + return Pluf_Shortcuts_RenderToResponse('idf/register/inputkey.html', + array('page_title' => $title, + 'form' => $form), + $request); + } + + /** + * Registration confirmation. + * + * Input first/last name, password and sign in the user. + * + * Maybe in the future send the user to its personal page for + * customization. + */ + function registerConfirmation($request, $match) + { + $title = __('Confirm Your Account Creation'); + $key = $match[1]; + // first "check", full check is done in the form. + $email_id = IDF_Form_RegisterInputKey::checkKeyHash($key); + if (false == $email_id) { + $url = Pluf_HTTP_URL_urlForView('IDF_Views::registerInputKey'); + return new Pluf_HTTP_Response_Redirect($url); + } + $user = new Pluf_User($email_id[1]); + $extra = array('key' => $key, + 'user' => $user); + if ($request->method == 'POST') { + $form = new IDF_Form_RegisterConfirmation($request->POST, $extra); + if ($form->isValid()) { + $user = $form->save(); + $request->user = $user; + $request->session->clear(); + $request->session->setData('login_time', gmdate('Y-m-d H:i:s')); + $user->last_login = gmdate('Y-m-d H:i:s'); + $user->update(); + $request->user->setMessage(__('Welcome! You can now participate in the life of your project of choice.')); + $url = Pluf_HTTP_URL_urlForView('IDF_Views::index'); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $form = new IDF_Form_RegisterConfirmation(null, $extra); + } + return Pluf_Shortcuts_RenderToResponse('idf/register/confirmation.html', + array('page_title' => $title, + 'new_user' => $user, + 'form' => $form), + $request); + } + + /** + * Password recovery. + * + * Request the login or the email of the user and if the login or + * email is available in the database, send an email with a key to + * reset the password. + * + * If the user is not yet confirmed, send the confirmation key one + * more time. + */ + function passwordRecoveryAsk($request, $match) + { + $title = __('Password Recovery'); + if ($request->method == 'POST') { + $form = new IDF_Form_Password($request->POST); + if ($form->isValid()) { + $url = $form->save(); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $form = new IDF_Form_Password(); + } + return Pluf_Shortcuts_RenderToResponse('idf/user/passrecovery-ask.html', + array('page_title' => $title, + 'form' => $form), + $request); + } + + /** + * If the key is valid, provide a nice form to reset the password + * and automatically login the user. + * + * This is also firing the password change event for the plugins. + */ + public function passwordRecovery($request, $match) + { + $title = __('Password Recovery'); + $key = $match[1]; + // first "check", full check is done in the form. + $email_id = IDF_Form_PasswordInputKey::checkKeyHash($key); + if (false == $email_id) { + $url = Pluf_HTTP_URL_urlForView('IDF_Views::passwordRecoveryInputKey'); + return new Pluf_HTTP_Response_Redirect($url); + } + $user = new Pluf_User($email_id[1]); + $extra = array('key' => $key, + 'user' => $user); + if ($request->method == 'POST') { + $form = new IDF_Form_PasswordReset($request->POST, $extra); + if ($form->isValid()) { + $user = $form->save(); + $request->user = $user; + $request->session->clear(); + $request->session->setData('login_time', gmdate('Y-m-d H:i:s')); + $user->last_login = gmdate('Y-m-d H:i:s'); + $user->update(); + $request->user->setMessage(__('Welcome back! Next time, you can use your broswer options to remember the password.')); + $url = Pluf_HTTP_URL_urlForView('IDF_Views::index'); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $form = new IDF_Form_PasswordReset(null, $extra); + } + return Pluf_Shortcuts_RenderToResponse('idf/user/passrecovery.html', + array('page_title' => $title, + 'new_user' => $user, + 'form' => $form), + $request); + + } + + /** + * Just a simple input box to provide the code and redirect to + * passwordRecovery + */ + public function passwordRecoveryInputCode($request, $match) + { + $title = __('Password Recovery'); + if ($request->method == 'POST') { + $form = new IDF_Form_PasswordInputKey($request->POST); + if ($form->isValid()) { + $url = $form->save(); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $form = new IDF_Form_PasswordInputKey(); + } + return Pluf_Shortcuts_RenderToResponse('idf/user/passrecovery-inputkey.html', + array('page_title' => $title, + 'form' => $form), + $request); + } + + /** + * FAQ. + */ + public function faq($request, $match) + { + $title = __('Here to Help You!'); + $projects = self::getProjects($request->user); + return Pluf_Shortcuts_RenderToResponse('idf/faq.html', + array( + 'page_title' => $title, + 'projects' => $projects, + ), + $request); + + } + + /** + * Download archive FAQ. + */ + public function faqArchiveFormat($request, $match) + { + $title = __('InDefero Upload Archive Format'); + $projects = self::getProjects($request->user); + return Pluf_Shortcuts_RenderToResponse('idf/faq-archive-format.html', + array( + 'page_title' => $title, + 'projects' => $projects, + ), + $request); + + } + + /** + * API FAQ. + */ + public function faqApi($request, $match) + { + $title = __('InDefero API (Application Programming Interface)'); + $projects = self::getProjects($request->user); + return Pluf_Shortcuts_RenderToResponse('idf/faq-api.html', + array( + 'page_title' => $title, + 'projects' => $projects, + ), + $request); + + } + + /** + * Returns a list of ids of projects that are visible for the given user + * + * @param Pluf_User $user + */ + private static function getUserVisibleProjectIds($user) + { + $db =& Pluf::db(); + // the administrator can see all projects + if ($user->administrator) { + $ids = array(); + $sql_results = $db->select( + 'SELECT id FROM '.Pluf::f('db_table_prefix', '').'idf_projects' + ); + foreach ($sql_results as $id) { + $ids[] = $id['id']; + } + return $ids; + } + + // anonymous users can only see non-private projects + $false = Pluf_DB_BooleanToDb(false, $db); + $sql_results = $db->select( + 'SELECT id FROM '.$db->pfx.'idf_projects '. + 'WHERE '.$db->qn('private').'='.$false + ); + + $ids = array(); + foreach ($sql_results as $id) { + $ids[] = $id['id']; + } + + // registered users may additionally see private projects with which + // they're somehow affiliated + if (!$user->isAnonymous()) { + $perms = array( + Pluf_Permission::getFromString('IDF.project-member'), + Pluf_Permission::getFromString('IDF.project-owner'), + Pluf_Permission::getFromString('IDF.project-authorized-user') + ); + $permSql = new Pluf_SQL( + "model_class='IDF_Project' AND owner_class='Pluf_User' ". + "AND owner_id=%s AND negative=".$false, $user->id + ); + $rows = Pluf::factory('Pluf_RowPermission')->getList(array('filter' => $permSql->gen())); + if ($rows->count() > 0) { + foreach ($rows as $row) { + if (in_array($row->model_id, $ids)) + continue; + $ids[] = $row->model_id; + } + } + } + return $ids; + } + + /** + * Returns a list of projects accessible for the user and optionally filtered by tag. + * + * @param Pluf_User + * @param IDF_Tag + * @return ArrayObject IDF_Project + */ + public static function getProjects($user, $tag = false, $order = 'name') + { + $db =& Pluf::db(); + $sql = new Pluf_SQL('1=1'); + if ($tag !== false) { + $sql->SAnd(new Pluf_SQL('idf_tag_id=%s', $tag->id)); + } + + $projectIds = self::getUserVisibleProjectIds($user); + if (count($projectIds) == 0) { + return new ArrayObject(); + } + + $sql->SAnd(new Pluf_SQL(sprintf($db->pfx.'idf_projects.id IN (%s)', implode(', ', $projectIds)))); + + $orderTypes = array( + 'name' => 'name ASC', + 'activity' => 'value DESC, name ASC', + ); + return Pluf::factory('IDF_Project')->getList(array( + 'filter'=> $sql->gen(), + 'view' => 'join_activities_and_tags', + 'order' => $orderTypes[$order], + )); + } + + /** + * Returns a list of global tags each carrying the number of projects that have the + * particular tag set + * + * @param Pluf_User $user + * @return array + */ + public static function getProjectLabelsWithCounts($user) { + + $sql = new Pluf_SQL('project IS NULL'); + + $projectIds = self::getUserVisibleProjectIds($user); + if (count($projectIds) == 0) { + return new ArrayObject(); + } + + $sql->SAnd(new Pluf_SQL(sprintf('idf_project_id IN (%s)', implode(', ', $projectIds)))); + + $tagList = Pluf::factory('IDF_Tag')->getList(array( + 'filter' => $sql->gen(), + 'view' => 'join_projects', + 'order' => 'class ASC, lcname ASC' + )); + + $maxProjectCount = 0; + foreach ($tagList as $tag) { + $maxProjectCount = max($maxProjectCount, $tag->project_count); + } + + $tags = array(); + foreach ($tagList as $tag) { + // group by class + if (!array_key_exists($tag->class, $tags)) { + $tags[$tag->class] = array(); + } + $tag->rel_project_count = $tag->project_count / (double) $maxProjectCount; + $tags[$tag->class][] = $tag; + } + return $tags; + } + + + /** + * Returns statistics on a list of projects. + * + * @param ArrayObject IDF_Project + * @return Associative array of statistics + */ + public static function getProjectsStatistics($projects) + { + $projectIds = array(0); + foreach ($projects as $project) { + $projectIds[] = $project->id; + } + + $forgestats = array(); + + // count overall project stats + $forgestats['total'] = 0; + $what = array( + 'downloads' => 'IDF_Upload', + 'reviews' => 'IDF_Review', + 'issues' => 'IDF_Issue', + 'docpages' => 'IDF_Wiki_Page', + 'commits' => 'IDF_Commit', + ); + + foreach ($what as $key => $model) { + $count = Pluf::factory($model)->getCount(array( + 'filter' => sprintf('project IN (%s)', implode(', ', $projectIds)) + )); + $forgestats[$key] = $count; + $forgestats['total'] += $count; + } + $forgestats['proj_count'] = count($projects); + return $forgestats; + } +} diff --git a/indefero/src/IDF/Views/Admin.php b/indefero/src/IDF/Views/Admin.php new file mode 100644 index 0000000..9b68e7b --- /dev/null +++ b/indefero/src/IDF/Views/Admin.php @@ -0,0 +1,649 @@ +method == 'POST') { + $form = new IDF_Form_Admin_ForgeConf($request->POST); + if ($form->isValid()) { + $forge->setCustomForgePageEnabled($form->cleaned_data['enabled']); + $forge->setCustomForgePageContent($form->cleaned_data['content']); + $request->user->setMessage(__('The forge configuration has been saved.')); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Admin::forge'); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $params = array(); + $params['enabled'] = $forge->isCustomForgePageEnabled(); + if (($content = $forge->getCustomForgePageContent(false)) !== false) { + $params['content'] = $content; + } + if (count($params) == 0) { + $params = null; //Nothing in the db, so new form. + } + $form = new IDF_Form_Admin_ForgeConf($params); + } + return Pluf_Shortcuts_RenderToResponse('idf/gadmin/forge/index.html', + array( + 'page_title' => $title, + 'form' => $form, + ), + $request); + } + + /** + * Projects overview. + * + */ + public $projects_precond = array('Pluf_Precondition::staffRequired'); + public function projects($request, $match) + { + $title = __('Projects'); + $pag = new Pluf_Paginator(new IDF_Project()); + $pag->class = 'recent-issues'; + $pag->summary = __('This table shows the projects in the forge.'); + $pag->action = 'IDF_Views_Admin::projects'; + $pag->edit_action = array('IDF_Views_Admin::projectUpdate', 'id'); + $pag->sort_order = array('shortname', 'ASC'); + $list_display = array( + 'shortname' => __('Short Name'), + 'name' => __('Name'), + array('id', 'IDF_Views_Admin_projectSize', __('Repository Size')), + ); + $pag->configure($list_display, array(), + array('shortname' )); + $pag->extra_classes = array('', '', 'right'); + $pag->items_per_page = 25; + $pag->no_results_text = __('No projects were found.'); + $pag->setFromRequest($request); + + return Pluf_Shortcuts_RenderToResponse('idf/gadmin/projects/index.html', + array( + 'page_title' => $title, + 'projects' => $pag, + 'size' => IDF_Views_Admin_getForgeSize(), + ), + $request); + } + + /** + * Administrate the labels of a project. + */ + public $projectLabels_precond = array('Pluf_Precondition::staffRequired'); + public function projectLabels($request, $match) + { + $title = __('Project Labels'); + $forge = IDF_Forge::instance(); + if ($request->method == 'POST') { + $form = new IDF_Form_Admin_LabelConf($request->POST); + if ($form->isValid()) { + $forge->setProjectLabels($form->cleaned_data['project_labels']); + $request->user->setMessage(__('The label configuration has been saved.')); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Admin::projectLabels'); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $params = array(); + if (($labels = $forge->getProjectLabels(false)) !== false) { + $params['project_labels'] = $labels; + } + if (count($params) == 0) { + $params = null; //Nothing in the db, so new form. + } + $form = new IDF_Form_Admin_LabelConf($params); + } + return Pluf_Shortcuts_RenderToResponse('idf/gadmin/projects/labels.html', + array( + 'page_title' => $title, + 'form' => $form, + ), + $request); + } + + /** + * Edition of a project. + * + * One cannot switch from one source backend to another. + */ + public $projectUpdate_precond = array('Pluf_Precondition::staffRequired'); + public function projectUpdate($request, $match) + { + $project = Pluf_Shortcuts_GetObjectOr404('IDF_Project', $match[1]); + $title = sprintf(__('Update %s'), $project->name); + $params = array( + 'project' => $project, + ); + if ($request->method == 'POST') { + $form = new IDF_Form_Admin_ProjectUpdate($request->POST, $params); + if ($form->isValid()) { + $form->save(); + $request->user->setMessage(__('The project has been updated.')); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Admin::projectUpdate', + array($project->id)); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $form = new IDF_Form_Admin_ProjectUpdate(null, $params); + } + $arrays = IDF_Views_Project::autoCompleteArrays(); + return Pluf_Shortcuts_RenderToResponse('idf/gadmin/projects/update.html', + array_merge( + array( + 'page_title' => $title, + 'project' => $project, + 'form' => $form, + ), + $arrays + ), + $request); + } + + /** + * Creation of a project. + * + * A project can use another project as template. In that case, + * everything but the data in the input at creation time is + * reused, including the wiki pages. + */ + public $projectCreate_precond = array('Pluf_Precondition::staffRequired'); + public function projectCreate($request, $match) + { + $title = __('Create Project'); + $extra = array('user' => $request->user); + if ($request->method == 'POST') { + $form = new IDF_Form_Admin_ProjectCreate($request->POST, $extra); + if ($form->isValid()) { + $project = $form->save(); + $request->user->setMessage(__('The project has been created.')); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Admin::projects'); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $form = new IDF_Form_Admin_ProjectCreate(null, $extra); + } + $base = Pluf::f('url_base').Pluf::f('idf_base').'/p/'; + + $arrays = IDF_Views_Project::autoCompleteArrays(); + return Pluf_Shortcuts_RenderToResponse('idf/gadmin/projects/create.html', + array_merge( + array( + 'page_title' => $title, + 'form' => $form, + 'base_url' => $base, + ), + $arrays + ), + $request); + } + + /** + * Deletion of a project. + * + * Only the forge administrator can perform this operation. + */ + public $projectDelete_precond = array('Pluf_Precondition::adminRequired'); + public function projectDelete($request, $match) + { + $project = Pluf_Shortcuts_GetObjectOr404('IDF_Project', $match[1]); + $title = sprintf(__('Delete %s Project'), $project); + $extra = array('project' => $project, + 'user' => $request->user); + if ($request->method == 'POST') { + $form = new IDF_Form_Admin_ProjectDelete($request->POST, $extra); + if ($form->isValid()) { + $project = $form->save(); + $request->user->setMessage(__('The project has been deleted.')); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Admin::projects'); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $form = new IDF_Form_Admin_ProjectDelete(null, $extra); + } + return Pluf_Shortcuts_RenderToResponse('idf/gadmin/projects/delete.html', + array( + 'project' => $project, + 'page_title' => $title, + 'form' => $form, + 'stats' => $project->getStats(), + 'code' => $form->getCode(), + ), + $request); + } + + /** + * Users overview. + * + */ + public $users_precond = array('Pluf_Precondition::staffRequired'); + public function users($request, $match, $not_validated=false) + { + $pag = new Pluf_Paginator(new Pluf_User()); + $db =& Pluf::db(); + $true = Pluf_DB_BooleanToDb(true, $db); + if ($not_validated) { + $pag->forced_where = new Pluf_SQL('first_name = \'---\' AND active!='.$true); + $title = __('Not Validated User List'); + $pag->action = 'IDF_Views_Admin::usersNotValidated'; + } else { + $pag->forced_where = new Pluf_SQL('first_name != \'---\''); + $title = __('User List'); + $pag->action = 'IDF_Views_Admin::users'; + } + $pag->class = 'recent-issues'; + $pag->summary = __('This table shows the users in the forge.'); + $pag->edit_action = array('IDF_Views_Admin::userUpdate', 'id'); + $pag->sort_order = array('login', 'ASC'); + $list_display = array( + 'login' => __('login'), + array('last_name', 'Pluf_Paginator_ToString', __('Name')), + array('staff', 'IDF_Views_Admin_bool', __('Staff')), + array('administrator', 'IDF_Views_Admin_bool', __('Admin')), + array('active', 'IDF_Views_Admin_bool', __('Active')), + array('last_login', 'Pluf_Paginator_DateYMDHM', __('Last Login')), + ); + $pag->extra_classes = array('', '', 'a-c', 'a-c', 'a-c', 'a-c'); + $pag->configure($list_display, + array('login', 'last_name', 'email'), + array('login', 'last_login')); + $pag->items_per_page = 50; + $pag->no_results_text = __('No users were found.'); + $pag->setFromRequest($request); + return Pluf_Shortcuts_RenderToResponse('idf/gadmin/users/index.html', + array( + 'page_title' => $title, + 'users' => $pag, + 'not_validated' => $not_validated, + ), + $request); + } + + /** + * Not validated users. + */ + public $usersNotValidated_precond = array('Pluf_Precondition::staffRequired'); + public function usersNotValidated($request, $match) + { + return $this->users($request, $match, true); + } + + /** + * Edition of a user. + * + * Staff cannot edit other staff people and only admin can edit + * staff. + */ + public $userUpdate_precond = array('Pluf_Precondition::staffRequired'); + public function userUpdate($request, $match) + { + $user = Pluf_Shortcuts_GetObjectOr404('Pluf_User', $match[1]); + $title = sprintf(__('Update %s'), $user->__toString()); + $params = array( + 'user' => $user, + 'request' => $request, + ); + // Check the rights. + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Admin::users'); + $error = __('You do not have the rights to update this user.'); + if ($user->administrator and $request->user->id != $user->id) { + $request->user->setMessage($error); + return new Pluf_HTTP_Response_Redirect($url); + } + if ($user->staff) { + if (!$request->user->administrator and $request->user->id != $user->id) { + $request->user->setMessage($error); + return new Pluf_HTTP_Response_Redirect($url); + } + } + + if ($request->method == 'POST') { + $form = new IDF_Form_Admin_UserUpdate(array_merge($request->POST, + $request->FILES), + $params); + if ($form->isValid()) { + $form->save(); + $request->user->setMessage(__('The user has been updated.')); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $form = new IDF_Form_Admin_UserUpdate(null, $params); + } + return Pluf_Shortcuts_RenderToResponse('idf/gadmin/users/update.html', + array( + 'page_title' => $title, + 'cuser' => $user, + 'form' => $form, + ), + $request); + } + + /** + * Create a new user. + * + * Only staff can add a user. The user can be added together with + * a public ssh key. + */ + public $userCreate_precond = array('Pluf_Precondition::staffRequired'); + public function userCreate($request, $match) + { + $params = array( + 'request' => $request, + ); + if ($request->method == 'POST') { + $form = new IDF_Form_Admin_UserCreate(array_merge($request->POST, + $request->FILES), + $params); + if ($form->isValid()) { + $cuser = $form->save(); + $request->user->setMessage(sprintf(__('The user %s has been created.'), (string) $cuser)); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Admin::users'); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $form = new IDF_Form_Admin_UserCreate(null, $params); + } + $title = __('Add User'); + return Pluf_Shortcuts_RenderToResponse('idf/gadmin/users/create.html', + array( + 'page_title' => $title, + 'form' => $form, + ), + $request); + } + + /** + * Usher servers overview + * + */ + public $usher_precond = array('Pluf_Precondition::staffRequired'); + public function usher($request, $match) + { + $title = __('Usher management'); + $servers = array(); + foreach (IDF_Scm_Monotone_Usher::getServerList() as $server) { + $servers[] = (object)array( + "name" => $server, + "status" => IDF_Scm_Monotone_Usher::getStatus($server), + ); + } + + return Pluf_Shortcuts_RenderToResponse( + 'idf/gadmin/usher/index.html', + array( + 'page_title' => $title, + 'servers' => $servers, + ), + $request + ); + } + + /** + * Usher control + * + */ + public $usherControl_precond = array('Pluf_Precondition::staffRequired'); + public function usherControl($request, $match) + { + $title = __('Usher control'); + $action = $match[1]; + + if (!empty($action)) { + if (!in_array($action, array('reload', 'shutdown', 'startup'))) { + throw new Pluf_HTTP_Error404(); + } + + $msg = null; + if ($action == 'reload') { + IDF_Scm_Monotone_Usher::reload(); + $msg = __('Usher configuration has been reloaded'); + } + else if ($action == 'shutdown') { + IDF_Scm_Monotone_Usher::shutDown(); + $msg = __('Usher has been shut down'); + } + else + { + IDF_Scm_Monotone_Usher::startUp(); + $msg = __('Usher has been started up'); + } + + $request->user->setMessage($msg); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Admin::usherControl', array('')); + return new Pluf_HTTP_Response_Redirect($url); + } + + return Pluf_Shortcuts_RenderToResponse( + 'idf/gadmin/usher/control.html', + array( + 'page_title' => $title, + 'status' => IDF_Scm_Monotone_Usher::getStatus(), + ), + $request + ); + } + + /** + * Usher control + * + */ + public $usherServerControl_precond = array('Pluf_Precondition::staffRequired'); + public function usherServerControl($request, $match) + { + $server = $match[1]; + if (!in_array($server, IDF_Scm_Monotone_Usher::getServerList())) { + throw new Pluf_HTTP_Error404(); + } + + $action = $match[2]; + if (!in_array($action, array('start', 'stop', 'kill'))) { + throw new Pluf_HTTP_Error404(); + } + + $msg = null; + if ($action == 'start') { + IDF_Scm_Monotone_Usher::startServer($server); + $msg = sprintf(__('The server "%s" has been started'), $server); + } + else if ($action == 'stop') { + IDF_Scm_Monotone_Usher::stopServer($server); + $msg = sprintf(__('The server "%s" has been stopped'), $server); + } + else + { + IDF_Scm_Monotone_Usher::killServer($server); + $msg = sprintf(__('The server "%s" has been killed'), $server); + } + + $request->user->setMessage($msg); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Admin::usher'); + return new Pluf_HTTP_Response_Redirect($url); + } + + /** + * Open connections for a configured server + * + */ + public $usherServerConnections_precond = array('Pluf_Precondition::staffRequired'); + public function usherServerConnections($request, $match) + { + $server = $match[1]; + if (!in_array($server, IDF_Scm_Monotone_Usher::getServerList())) { + throw new Pluf_HTTP_Error404(); + } + + $title = sprintf(__('Open connections for "%s"'), $server); + + $connections = IDF_Scm_Monotone_Usher::getConnectionList($server); + if (count($connections) == 0) { + $request->user->setMessage(sprintf( + __('no connections for server "%s"'), $server + )); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Admin::usher'); + return new Pluf_HTTP_Response_Redirect($url); + } + + return Pluf_Shortcuts_RenderToResponse( + 'idf/gadmin/usher/connections.html', + array( + 'page_title' => $title, + 'server' => $server, + 'connections' => $connections, + ), + $request + ); + } +} + +function IDF_Views_Admin_bool($field, $item) +{ + $img = ($item->$field) ? 'day' : 'night'; + $text = ($item->$field) ? __('Yes') : __('No'); + return sprintf('%s ', $img, $text); +} + +/** + * Display the size of the project. + * + * @param string Field + * @param IDF_Project + * @return string + */ +function IDF_Views_Admin_projectSize($field, $project) +{ + $size = $project->getRepositorySize(); + if ($size == -1) { + return ''; + } + return Pluf_Utils::prettySize($size); +} + +/** + * Get a forge size. + * + * @return array Associative array with the size of each element + */ +function IDF_Views_Admin_getForgeSize($force=false) +{ + $conf = new IDF_Gconf(); + $conf->setModel((object) array('_model'=>'IDF_Forge', 'id'=> 1)); + $res = array(); + $res['repositories'] = 0; + foreach (Pluf::factory('IDF_Project')->getList() as $prj) { + $size = $prj->getRepositorySize($force); + if ($size != -1) { + $res['repositories'] += $size; + } + } + $last_eval = $conf->getVal('downloads_size_check_date', 0); + if (Pluf::f('idf_no_size_check', false) or + (!$force and $last_eval > time()-172800)) { + $res['downloads'] = $conf->getVal('downloads_size', 0); + } else { + $conf->setVal('downloads_size_check_date', time()); + $cmd = Pluf::f('idf_exec_cmd_prefix', '').'du -sk ' + .escapeshellarg(Pluf::f('upload_path')); + $out = explode(' ', shell_exec($cmd), 2); + $res['downloads'] = $out[0]*1024; + $conf->setVal('downloads_size', $res['downloads']); + } + $last_eval = $conf->getVal('attachments_size_check_date', 0); + if (Pluf::f('idf_no_size_check', false) or + (!$force and $last_eval > time()-172800)) { + $res['attachments'] = $conf->getVal('attachments_size', 0); + } else { + $conf->setVal('attachments_size_check_date', time()); + $cmd = Pluf::f('idf_exec_cmd_prefix', '').'du -sk ' + .escapeshellarg(Pluf::f('upload_path')); + $out = explode(' ', shell_exec($cmd), 2); + $res['attachments'] = $out[0]*1024; + $conf->setVal('attachments_size', $res['attachments']); + } + $last_eval = $conf->getVal('database_size_check_date', 0); + if (Pluf::f('idf_no_size_check', false) or + (!$force and $last_eval > time()-172800)) { + $res['database'] = $conf->getVal('database_size', 0); + } else { + $conf->setVal('database_size_check_date', time()); + $res['database'] = IDF_Views_Admin_getForgeDbSize(); + $conf->setVal('database_size', $res['database']); + } + $res['total'] = $res['repositories'] + $res['downloads'] + $res['attachments'] + $res['database']; + return $res; +} + +/** + * Get the database size as given by the database. + * + * @return int Database size + */ +function IDF_Views_Admin_getForgeDbSize() +{ + $db = Pluf::db(); + if (Pluf::f('db_engine') == 'SQLite') { + return filesize(Pluf::f('db_database')); + } + switch (Pluf::f('db_engine')) { + case 'PostgreSQL': + $sql = 'SELECT relname, pg_total_relation_size(CAST(relname AS +TEXT)) AS size FROM pg_class AS pgc, pg_namespace AS pgn + WHERE pg_table_is_visible(pgc.oid) IS TRUE AND relkind = \'r\' + AND pgc.relnamespace = pgn.oid + AND pgn.nspname NOT IN (\'information_schema\', \'pg_catalog\')'; + break; + case 'MySQL': + default: + $sql = 'SHOW TABLE STATUS FROM `'.Pluf::f('db_database').'`'; + break; + } + $rs = $db->select($sql); + $total = 0; + switch (Pluf::f('db_engine')) { + case 'PostgreSQL': + foreach ($rs as $table) { + $total += $table['size']; + } + break; + case 'MySQL': + default: + foreach ($rs as $table) { + $total += $table['Data_length'] + $table['Index_length']; + } + break; + } + return $total; +} diff --git a/indefero/src/IDF/Views/Api.php b/indefero/src/IDF/Views/Api.php new file mode 100644 index 0000000..c0e488d --- /dev/null +++ b/indefero/src/IDF/Views/Api.php @@ -0,0 +1,131 @@ +user from the + * _login, _hash and _salt parameters. + */ +class IDF_Views_Api +{ + /** + * View list of issues for a given project. + */ + public $issuesIndex_precond = array('IDF_Precondition::apiSetUser', + 'IDF_Precondition::accessIssues'); + public function issuesIndex($request, $match) + { + $views = new IDF_Views_Issue(); + $p = $views->index($request, $match, true); + $out = array( + 'project' => $request->project->shortname, + 'open' => $p['open'], + 'closed' => $p['closed'], + 'issues' => $p['issues']->render_array(), + ); + return new Pluf_HTTP_Response_Json($out); + } + + /** + * Create a new issue. + */ + public $issueCreate_precond = array('IDF_Precondition::apiSetUser', + 'Pluf_Precondition::loginRequired', + 'IDF_Precondition::accessIssues'); + public function issueCreate($request, $match) + { + $views = new IDF_Views_Issue(); + $p = $views->create($request, $match, true); + $out = array(); + if ($request->method == 'GET') { + // We give the details of the form + $out['help'] = 'A POST request against this url will allow you to create a new issue.'; + if ($request->user->hasPerm('IDF.project-owner', $request->project) + or $request->user->hasPerm('IDF.project-member', $request->project)) { + $out['status'] = array(); + foreach (self::getTags($request->project) as $tag) { + $out['status'][] = $tag->name; + } + } + + } else { + // We need to give back the results of the creation + if (is_object($p) and 'IDF_Issue' == get_class($p)) { + $out['message'] = 'success'; + $out['issue'] = $p->id; + } else { + $out['message'] = 'error'; + $out['errors'] = $p['form']->errors; + } + } + return new Pluf_HTTP_Response_Json($out); + } + + /** + * List all the projects + */ + public $projectIndex_precond = array('IDF_Precondition::apiSetUser'); + + public function projectIndex($request, $match) + { + $projects = IDF_Views::getProjects($request->user); + + $data = array(); + foreach ($projects as $p) { + $data[] = array("shortname" => $p->shortname, "name" => $p->name, "shortdesc" => $p->shortdesc, "private" => $p->private); + } + + $out = array(); + $out['message'] = 'success'; + $out['projects'] = $data; + return new Pluf_HTTP_Response_Json($out); + } + + /** + * Get the list of tags to give them to the end users when doing a + * GET request against a form. That way it is possible for them to + * know which tags/labels are available. + * + * @param IDF_Project Current project + * @param string Which tags to get ('issue-open') + * @return ArrayObject Tags + */ + + public static function getTags($project, $what='issue-open') + { + switch ($what) { + case 'issue-open': + $key = 'labels_issue_open'; + $default = IDF_Form_IssueTrackingConf::init_open; + return $project->getTagsFromConfig($key, $default); + case 'issue-closed': + return $project->getTagIdsByStatus('closed'); + } + return array(); + } +} \ No newline at end of file diff --git a/indefero/src/IDF/Views/Download.php b/indefero/src/IDF/Views/Download.php new file mode 100644 index 0000000..20247be --- /dev/null +++ b/indefero/src/IDF/Views/Download.php @@ -0,0 +1,425 @@ +project; + $title = sprintf(__('%s Downloads'), (string) $prj); + // Paginator to paginate the files to download. + $pag = new Pluf_Paginator(new IDF_Upload()); + //$pag->class = 'recent-issues'; + $pag->class = 'uploads'; + $pag->item_extra_props = array('project_m' => $prj, + 'shortname' => $prj->shortname); + $pag->summary = __('This table shows the files to download.'); + $pag->action = array('IDF_Views_Download::index', array($prj->shortname)); + $pag->edit_action = array('IDF_Views_Download::view', 'shortname', 'id'); + $sql = 'project=%s'; + $ptags = self::getDownloadTags($prj); + $dtag = array_pop($ptags); // The last tag is the deprecated tag. + $ids = self::getDeprecatedFilesIds($prj); + if (count($ids)) { + $sql .= ' AND id NOT IN ('.implode(',', $ids).')'; + } + $pag->forced_where = new Pluf_SQL($sql, array($prj->id)); + + $list_display = array( + 'file' => __('File'), + array('summary', 'IDF_Views_Download_SummaryAndLabels', __('Summary')), + array('filesize', 'IDF_Views_Download_Size', __('Size')), + array('creation_dtime', 'Pluf_Paginator_DateYMD', __('Uploaded')), + array('downloads', 'Pluf_Paginator_DisplayVal', __('Downlaods')), + ); + $pag->configure($list_display, array(), array('file', 'filesize', 'creation_dtime')); + $pag->items_per_page = 10; + $pag->no_results_text = __('No downloads were found.'); + $pag->sort_order = array('creation_dtime', 'DESC'); + $pag->setFromRequest($request); + return Pluf_Shortcuts_RenderToResponse('idf/downloads/index.html', + array( + 'page_title' => $title, + 'downloads' => $pag, + 'deprecated' => count($ids), + 'dlabel' => $dtag, + ), + $request); + + } + + /** + * View details of a file. + */ + public $view_precond = array('IDF_Precondition::accessDownloads'); + public function view($request, $match) + { + $prj = $request->project; + $upload = Pluf_Shortcuts_GetObjectOr404('IDF_Upload', $match[2]); + $prj->inOr404($upload); + $title = sprintf(__('Download %s'), $upload->summary); + $form = false; + $ptags = self::getDownloadTags($prj); + $dtag = array_pop($ptags); // The last tag is the deprecated tag. + $tags = $upload->get_tags_list(); + $deprecated = Pluf_Model_InArray($dtag, $tags); + if ($request->method == 'POST' and + true === IDF_Precondition::projectMemberOrOwner($request)) { + + $form = new IDF_Form_UpdateUpload($request->POST, + array('project' => $prj, + 'upload' => $upload, + 'user' => $request->user)); + if ($form->isValid()) { + $upload = $form->save(); + $urlfile = Pluf_HTTP_URL_urlForView('IDF_Views_Download::view', + array($prj->shortname, $upload->id)); + $request->user->setMessage(sprintf(__('The file %2$s has been updated.'), $urlfile, Pluf_esc($upload->file))); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Download::index', + array($prj->shortname)); + return new Pluf_HTTP_Response_Redirect($url); + } + } elseif (true === IDF_Precondition::projectMemberOrOwner($request)) { + $form = new IDF_Form_UpdateUpload(null, + array('upload' => $upload, + 'project' => $prj, + 'user' => $request->user)); + } + return Pluf_Shortcuts_RenderToResponse('idf/downloads/view.html', + array( + 'file' => $upload, + 'deprecated' => $deprecated, + 'tags' => $tags, + 'auto_labels' => self::autoCompleteArrays($prj), + 'page_title' => $title, + 'form' => $form, + ), + $request); + } + + /** + * Delete a file. + */ + public $delete_precond = array('IDF_Precondition::accessDownloads', + 'IDF_Precondition::projectMemberOrOwner'); + public function delete($request, $match) + { + $prj = $request->project; + $upload = Pluf_Shortcuts_GetObjectOr404('IDF_Upload', $match[2]); + $prj->inOr404($upload); + $title = sprintf(__('Delete Download %s'), $upload->summary); + $form = false; + $ptags = self::getDownloadTags($prj); + $dtag = array_pop($ptags); // The last tag is the deprecated tag. + $tags = $upload->get_tags_list(); + $deprecated = Pluf_Model_InArray($dtag, $tags); + if ($request->method == 'POST') { + $fname = $upload->file; + @unlink(Pluf::f('upload_path').'/'.$prj->shortname.'/files/'.$fname); + /** + * [signal] + * + * IDF_Upload::delete + * + * [sender] + * + * IDF_Form_UpdateUpload + * + * [description] + * + * This signal allows an application to perform a set of tasks + * just before the deletion of the corresponding object in the + * database but just after the deletion from the storage. + * + * [parameters] + * + * array('upload' => $upload); + * + */ + $params = array('upload' => $upload); + Pluf_Signal::send('IDF_Upload::delete', + 'IDF_Views_Download', $params); + $upload->delete(); + $request->user->setMessage(__('The file has been deleted.')); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Download::index', + array($prj->shortname)); + return new Pluf_HTTP_Response_Redirect($url); + } + return Pluf_Shortcuts_RenderToResponse('idf/downloads/delete.html', + array( + 'file' => $upload, + 'deprecated' => $deprecated, + 'tags' => $tags, + 'page_title' => $title, + ), + $request); + } + + /** + * Download the file with the given name. + */ + public $download_precond = array('IDF_Precondition::accessDownloads'); + public function download($request, $match) + { + $prj = $request->project; + $sql = new Pluf_SQL('file=%s', array($match[2])); + $upload = Pluf::factory('IDF_Upload')->getOne(array('filter' => $sql->gen())); + if (!$upload) throw new Pluf_HTTP_Error404(); + $prj->inOr404($upload); + $upload->downloads += 1; + $upload->update(); + $path = $upload->getFullPath(); + $mime = IDF_FileUtil::getMimeType($path); + $render = new Pluf_HTTP_Response_File($path, $mime[0]); + $render->headers['Content-MD5'] = $upload->md5; + $render->headers['Content-Disposition'] = 'attachment; filename="'.$upload->file.'"'; + return $render; + } + + /** + * Download the file with the given ID (for legacy links). + */ + public $downloadById_precond = array('IDF_Precondition::accessDownloads'); + public function downloadById($request, $match) + { + $upload = Pluf_Shortcuts_GetObjectOr404('IDF_Upload', $match[2]); + return new Pluf_HTTP_Response_Redirect( + Pluf_HTTP_URL_urlForView('IDF_Views_Download::download', array( + $match[1], $upload->file + )), 301 + ); + } + + /** + * Create a new file for download. + */ + public $create_precond = array('IDF_Precondition::accessDownloads', + 'IDF_Precondition::projectMemberOrOwner'); + public function create($request, $match) + { + $prj = $request->project; + $title = __('New Download'); + if ($request->method == 'POST') { + $form = new IDF_Form_Upload(array_merge($request->POST, $request->FILES), + array('project' => $prj, + 'user' => $request->user)); + if ($form->isValid()) { + $upload = $form->save(); + $urlfile = Pluf_HTTP_URL_urlForView('IDF_Views_Download::view', + array($prj->shortname, $upload->id)); + $request->user->setMessage(sprintf(__('The file has been uploaded.'), $urlfile)); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Download::index', + array($prj->shortname)); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $form = new IDF_Form_Upload(null, + array('project' => $prj, + 'user' => $request->user)); + } + return Pluf_Shortcuts_RenderToResponse('idf/downloads/create.html', + array( + 'auto_labels' => self::autoCompleteArrays($prj), + 'page_title' => $title, + 'form' => $form, + ), + $request); + } + + /** + * Create new downloads from an uploaded archive. + */ + public $createFromArchive_precond = array('IDF_Precondition::accessDownloads', + 'IDF_Precondition::projectMemberOrOwner'); + public function createFromArchive($request, $match) + { + $prj = $request->project; + $title = __('New Downloads from Archive'); + if ($request->method == 'POST') { + $form = new IDF_Form_UploadArchive(array_merge($request->POST, $request->FILES), + array('project' => $prj, + 'user' => $request->user)); + if ($form->isValid()) { + $upload = $form->save(); + $request->user->setMessage(__('The archive has been uploaded and processed.')); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Download::index', + array($prj->shortname)); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $form = new IDF_Form_UploadArchive(null, + array('project' => $prj, + 'user' => $request->user)); + } + return Pluf_Shortcuts_RenderToResponse('idf/downloads/createFromArchive.html', + array( + 'page_title' => $title, + 'form' => $form, + ), + $request); + } + + /** + * Create the autocomplete arrays for the little AJAX stuff. + */ + public static function autoCompleteArrays($project) + { + $conf = new IDF_Conf(); + $conf->setProject($project); + $st = preg_split("/\015\012|\015|\012/", + $conf->getVal('labels_download_predefined', IDF_Form_UploadConf::init_predefined), -1, PREG_SPLIT_NO_EMPTY); + $auto = ''; + foreach ($st as $s) { + $v = ''; + $d = ''; + $_s = explode('=', $s, 2); + if (count($_s) > 1) { + $v = trim($_s[0]); + $d = trim($_s[1]); + } else { + $v = trim($_s[0]); + } + $auto .= sprintf('{ name: "%s", to: "%s" }, ', + Pluf_esc($d), Pluf_esc($v)); + } + return substr($auto, 0, -2); + } + + /** + * View list of downloads with a given label. + */ + public $listLabel_precond = array('IDF_Precondition::accessDownloads'); + public function listLabel($request, $match) + { + $prj = $request->project; + $tag = Pluf_Shortcuts_GetObjectOr404('IDF_Tag', $match[2]); + $prj->inOr404($tag); + $title = sprintf(__('%1$s Downloads with Label %2$s'), (string) $prj, + (string) $tag); + // Paginator to paginate the downloads + $ptags = self::getDownloadTags($prj); + $dtag = array_pop($ptags); // The last tag is the deprecated tag. + $pag = new Pluf_Paginator(new IDF_Upload()); + $pag->model_view = 'join_tags'; + $pag->class = 'recent-issues'; + $pag->item_extra_props = array('project_m' => $prj, + 'shortname' => $prj->shortname); + $pag->summary = sprintf(__('This table shows the downloads with label %s.'), (string) $tag); + $pag->forced_where = new Pluf_SQL('project=%s AND idf_tag_id=%s', array($prj->id, $tag->id)); + $pag->action = array('IDF_Views_Download::listLabel', array($prj->shortname, $tag->id)); + $pag->edit_action = array('IDF_Views_Download::view', 'shortname', 'id'); + $list_display = array( + 'file' => __('File'), + array('summary', 'IDF_Views_Download_SummaryAndLabels', __('Summary')), + array('filesize', 'IDF_Views_Download_Size', __('Size')), + array('creation_dtime', 'Pluf_Paginator_DateYMD', __('Uploaded')), + ); + $pag->configure($list_display, array(), array('file', 'filesize', 'creation_dtime')); + $pag->items_per_page = 10; + $pag->no_results_text = __('No downloads were found.'); + $pag->sort_order = array('creation_dtime', 'DESC'); + $pag->setFromRequest($request); + return Pluf_Shortcuts_RenderToResponse('idf/downloads/index.html', + array( + 'page_title' => $title, + 'label' => $tag, + 'downloads' => $pag, + 'dlabel' => $dtag, + ), + $request); + } + + /** + * Get the download tags. + * + * @param IDF_Project + * @return ArrayObject The tags + */ + public static function getDownloadTags($project) + { + return $project->getTagsFromConfig('labels_download_predefined', + IDF_Form_UploadConf::init_predefined); + + } + + /** + * Get deprecated file ids. + * + * @return array Ids of the deprecated files. + */ + public static function getDeprecatedFilesIds($project) + { + $ptags = self::getDownloadTags($project); + $dtag = array_pop($ptags); // The last tag is the deprecated tag. + $sql = new Pluf_SQL('project=%s AND idf_tag_id=%s', array($project->id, + $dtag->id)); + $ids = array(); + foreach (Pluf::factory('IDF_Upload')->getList(array('filter' => $sql->gen(), 'view' => 'join_tags')) + as $file) { + $ids[] = (int) $file->id; + } + return $ids; + } +} + +/** + * Display the summary of a download, then on a new line, display the + * list of labels. + * + * The summary of the download is linking to the download. + */ +function IDF_Views_Download_SummaryAndLabels($field, $down, $extra='') +{ + $tags = array(); + foreach ($down->get_tags_list() as $tag) { + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Download::listLabel', + array($down->shortname, $tag->id)); + $tags[] = sprintf('%s', $url, Pluf_esc((string) $tag)); + } + $out = ''; + if (count($tags)) { + $out = '
'.implode(', ', $tags).''; + } + return Pluf_esc($down->summary).$out; +} + +function IDF_Views_Download_Size($field, $down) +{ + return Pluf_Utils::prettySize($down->$field); +} diff --git a/indefero/src/IDF/Views/Issue.php b/indefero/src/IDF/Views/Issue.php new file mode 100644 index 0000000..f1f0100 --- /dev/null +++ b/indefero/src/IDF/Views/Issue.php @@ -0,0 +1,1055 @@ +project; + $title = sprintf(__('%s Open Issues'), (string) $prj); + // Get stats about the issues + $open = $prj->getIssueCountByStatus('open'); + $closed = $prj->getIssueCountByStatus('closed'); + // Paginator to paginate the issues + $pag = new Pluf_Paginator(new IDF_Issue()); + $pag->class = 'recent-issues'; + $pag->item_extra_props = array('project_m' => $prj, + 'shortname' => $prj->shortname, + 'current_user' => $request->user); + $pag->summary = __('This table shows the open issues.'); + $otags = $prj->getTagIdsByStatus('open'); + if (count($otags) == 0) $otags[] = 0; + $pag->forced_where = new Pluf_SQL('project=%s AND status IN ('.implode(', ', $otags).')', array($prj->id)); + $pag->action = array('IDF_Views_Issue::index', array($prj->shortname)); + $pag->sort_order = array('modif_dtime', 'ASC'); // will be reverted + $pag->sort_reverse_order = array('modif_dtime'); + $pag->sort_link_title = true; + $pag->extra_classes = array('a-c', '', 'a-c', ''); + $list_display = array( + 'id' => __('Id'), + array('summary', 'IDF_Views_Issue_SummaryAndLabels', __('Summary')), + array('status', 'IDF_Views_Issue_ShowStatus', __('Status')), + array('modif_dtime', 'Pluf_Paginator_DateAgo', __('Last Updated')), + ); + $pag->configure($list_display, array(), array('id', 'status', 'modif_dtime')); + $pag->items_per_page = 10; + $pag->no_results_text = __('No issues were found.'); + $pag->setFromRequest($request); + $params = array('project' => $prj, + 'page_title' => $title, + 'open' => $open, + 'closed' => $closed, + 'issues' => $pag, + 'cloud' => 'issues', + ); + if ($api) return $params; + return Pluf_Shortcuts_RenderToResponse('idf/issues/index.html', + $params, $request); + } + + /** + * View the issue summary. + * TODO Add thoses data in cache, and process it only after an issue update + */ + public $summary_precond = array('IDF_Precondition::accessIssues'); + public function summary($request, $match) + { + $tagStatistics = array(); + $ownerStatistics = array(); + $status = array(); + $isTrackerEmpty = false; + + $prj = $request->project; + $opened = $prj->getIssueCountByStatus('open'); + $closed = $prj->getIssueCountByStatus('closed'); + + // Check if the tracker is empty + if ($opened === 0 && $closed === 0) { + $isTrackerEmpty = true; + } else { + if ($opened > 0 || $closed > 0) { + // Issue status statistics + $status['Open'] = array($opened, (int)(100 * $opened / ($opened + $closed))); + $status['Closed'] = array($closed, (int)(100 * $closed / ($opened + $closed))); + } + + if ($opened > 0) { + // Issue owner statistics + $owners = $prj->getIssueCountByOwner('open'); + foreach ($owners as $user => $nb) { + if ($user === '') { + $key = __('Not assigned'); + $login = null; + } else { + $obj = Pluf::factory('Pluf_User')->getOne(array('filter'=>'id='.$user)); + $key = $obj->first_name . ' ' . $obj->last_name; + $login = $obj->login; + } + $ownerStatistics[$key] = array($nb, (int)(100 * $nb / $opened), $login); + } + arsort($ownerStatistics); + + // Issue class tag statistics + $grouped_tags = $prj->getTagCloud(); + foreach ($grouped_tags as $class => $tags) { + foreach ($tags as $tag) { + $tagStatistics[$class][$tag->name] = array($tag->nb_use, $tag->id); + } + uasort($tagStatistics[$class], function ($a, $b) { + if ($a[0] === $b[0]) + return 0; + + return ($a[0] > $b[0]) ? -1 : 1; + }); + } + foreach($tagStatistics as $k => $v) { + $nbIssueInClass = 0; + foreach ($v as $val) { + $nbIssueInClass += $val[0]; + } + foreach ($v as $kk => $vv) { + $tagStatistics[$k][$kk] = array($vv[0], (int)(100 * $vv[0] / $nbIssueInClass), $vv[1]); + } + } + } + } + + $title = sprintf(__('Summary of tracked issues in %s.'), (string) $prj); + + return Pluf_Shortcuts_RenderToResponse('idf/issues/summary.html', + array('page_title' => $title, + 'trackerEmpty' => $isTrackerEmpty, + 'project' => $prj, + 'tagStatistics' => $tagStatistics, + 'ownerStatistics' => $ownerStatistics, + 'status' => $status, + ), + $request); + } + + /** + * View the issues watch list of a given user. + * Limited to a specified project + */ + public $watchList_precond = array('IDF_Precondition::accessIssues', + 'Pluf_Precondition::loginRequired'); + public function watchList($request, $match) + { + $prj = $request->project; + $otags = $prj->getTagIdsByStatus('open'); + $ctags = $prj->getTagIdsByStatus('closed'); + if (count($otags) == 0) $otags[] = 0; + if (count($ctags) == 0) $ctags[] = 0; + + // Get the id list of issue in the user watch list (for all projects !) + $db =& Pluf::db(); + $sql_results = $db->select('SELECT idf_issue_id as id FROM '.Pluf::f('db_table_prefix', '').'idf_issue_pluf_user_assoc WHERE pluf_user_id='.$request->user->id); + $issue_ids = array(0); + foreach ($sql_results as $id) { + $issue_ids[] = $id['id']; + } + $issue_ids = implode (',', $issue_ids); + + // Count open and close issues + $sql = new Pluf_SQL('project=%s AND id IN ('.$issue_ids.') AND status IN ('.implode(', ', $otags).')', array($prj->id)); + $nb_open = Pluf::factory('IDF_Issue')->getCount(array('filter'=>$sql->gen())); + $sql = new Pluf_SQL('project=%s AND id IN ('.$issue_ids.') AND status IN ('.implode(', ', $ctags).')', array($prj->id)); + $nb_closed = Pluf::factory('IDF_Issue')->getCount(array('filter'=>$sql->gen())); + + // Generate a filter for the paginator + switch ($match[2]) { + case 'closed': + $title = sprintf(__('Watch List: Closed Issues for %s'), (string) $prj); + $summary = __('This table shows the closed issues in your watch list for %s project.', (string) $prj); + $f_sql = new Pluf_SQL('project=%s AND id IN ('.$issue_ids.') AND status IN ('.implode(', ', $ctags).')', array($prj->id)); + break; + case 'open': + default: + $title = sprintf(__('Watch List: Open Issues for %s'), (string) $prj); + $summary = __('This table shows the open issues in your watch list for %s project.', (string) $prj); + $f_sql = new Pluf_SQL('project=%s AND id IN ('.$issue_ids.') AND status IN ('.implode(', ', $otags).')', array($prj->id)); + break; + } + + // Paginator to paginate the issues + $pag = new Pluf_Paginator(new IDF_Issue()); + $pag->class = 'recent-issues'; + $pag->item_extra_props = array('project_m' => $prj, + 'shortname' => $prj->shortname, + 'current_user' => $request->user); + $pag->summary = $summary; + $pag->forced_where = $f_sql; + $pag->action = array('IDF_Views_Issue::watchList', array($prj->shortname, $match[1])); + $pag->sort_order = array('modif_dtime', 'ASC'); // will be reverted + $pag->sort_reverse_order = array('modif_dtime'); + $pag->sort_link_title = true; + $pag->extra_classes = array('a-c', '', 'a-c', ''); + $list_display = array( + 'id' => __('Id'), + array('summary', 'IDF_Views_Issue_SummaryAndLabels', __('Summary')), + array('status', 'IDF_Views_Issue_ShowStatus', __('Status')), + array('modif_dtime', 'Pluf_Paginator_DateAgo', __('Last Updated')), + ); + $pag->configure($list_display, array(), array('id', 'status', 'modif_dtime')); + $pag->items_per_page = 10; + $pag->no_results_text = __('No issues were found.'); + $pag->setFromRequest($request); + return Pluf_Shortcuts_RenderToResponse('idf/issues/project-watchlist.html', + array('project' => $prj, + 'page_title' => $title, + 'open' => $nb_open, + 'closed' => $nb_closed, + 'issues' => $pag, + ), + $request); + } + + /** + * View the issues watch list of a given user. + * For all projects + */ + public $forgeWatchList_precond = array('Pluf_Precondition::loginRequired'); + public function forgeWatchList($request, $match) + { + $otags = array(); + $ctags = array(); + // Note that this approach does not scale, we will need to add + // a table to cache the meaning of the tags for large forges. + foreach (IDF_Views::getProjects($request->user) as $project) { + $otags = array_merge($otags, $project->getTagIdsByStatus('open')); + } + foreach (IDF_Views::getProjects($request->user) as $project) { + $ctags = array_merge($ctags, $project->getTagIdsByStatus('closed')); + } + if (count($otags) == 0) $otags[] = 0; + if (count($ctags) == 0) $ctags[] = 0; + + // Get the id list of issue in the user watch list (for all projects !) + $db =& Pluf::db(); + $sql_results = $db->select('SELECT idf_issue_id as id FROM '.Pluf::f('db_table_prefix', '').'idf_issue_pluf_user_assoc WHERE pluf_user_id='.$request->user->id); + $issue_ids = array(0); + foreach ($sql_results as $id) { + $issue_ids[] = $id['id']; + } + $issue_ids = implode (',', $issue_ids); + + // Count open and close issues + $sql = new Pluf_SQL('id IN ('.$issue_ids.') AND status IN ('.implode(', ', $otags).')', array()); + $nb_open = Pluf::factory('IDF_Issue')->getCount(array('filter'=>$sql->gen())); + $sql = new Pluf_SQL('id IN ('.$issue_ids.') AND status IN ('.implode(', ', $ctags).')', array()); + $nb_closed = Pluf::factory('IDF_Issue')->getCount(array('filter'=>$sql->gen())); + + // Generate a filter for the paginator + switch ($match[1]) { + case 'closed': + $title = sprintf(__('Watch List: Closed Issues')); + $summary = __('This table shows the closed issues in your watch list.'); + $f_sql = new Pluf_SQL('id IN ('.$issue_ids.') AND status IN ('.implode(', ', $ctags).')', array()); + break; + case 'open': + default: + $title = sprintf(__('Watch List: Open Issues')); + $summary = __('This table shows the open issues in your watch list.'); + $f_sql = new Pluf_SQL('id IN ('.$issue_ids.') AND status IN ('.implode(', ', $otags).')', array()); + break; + } + + // Paginator to paginate the issues + $pag = new Pluf_Paginator(new IDF_Issue()); + $pag->class = 'recent-issues'; + $pag->item_extra_props = array('current_user' => $request->user); + $pag->summary = $summary; + $pag->forced_where = $f_sql; + $pag->action = array('IDF_Views_Issue::forgeWatchList', array($match[1])); + $pag->sort_order = array('modif_dtime', 'ASC'); // will be reverted + $pag->sort_reverse_order = array('modif_dtime'); + $pag->sort_link_title = true; + $pag->extra_classes = array('a-c', '', 'a-c', 'a-c', 'a-c'); + $list_display = array( + 'id' => __('Id'), + array('summary', 'IDF_Views_Issue_SummaryAndLabelsUnknownProject', __('Summary')), + array('project', 'Pluf_Paginator_FkToString', __('Project')), + array('status', 'IDF_Views_Issue_ShowStatus', __('Status')), + array('modif_dtime', 'Pluf_Paginator_DateAgo', __('Last Updated')), + ); + $pag->configure($list_display, array(), array('id', 'project', 'status', 'modif_dtime')); + $pag->items_per_page = 10; + $pag->no_results_text = __('No issues were found.'); + $pag->setFromRequest($request); + return Pluf_Shortcuts_RenderToResponse('idf/issues/forge-watchlist.html', + array('page_title' => $title, + 'open' => $nb_open, + 'closed' => $nb_closed, + 'issues' => $pag, + ), + $request); + } + + /** + * View the issues of a given user. + * + * Only open issues are shown. + */ + public $userIssues_precond = array('IDF_Precondition::accessIssues'); + public function userIssues($request, $match) + { + $prj = $request->project; + + $sql = new Pluf_SQL('login=%s', array($match[2])); + $user = Pluf::factory('Pluf_User')->getOne(array('filter' => $sql->gen())); + if ($user === null) { + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::index', + array($prj->shortname)); + return new Pluf_HTTP_Response_Redirect($url); + } + + $otags = $prj->getTagIdsByStatus('open'); + $ctags = $prj->getTagIdsByStatus('closed'); + if (count($otags) == 0) $otags[] = 0; + if (count($ctags) == 0) $ctags[] = 0; + switch ($match[3]) { + case 'submit': + $titleFormat = __('%1$s %2$s Submitted %3$s Issues'); + $f_sql = new Pluf_SQL('project=%s AND submitter=%s AND status IN ('.implode(', ', $otags).')', array($prj->id, $user->id)); + break; + case 'submitclosed': + $titleFormat = __('%1$s %2$s Closed Submitted %3$s Issues'); + $f_sql = new Pluf_SQL('project=%s AND submitter=%s AND status IN ('.implode(', ', $ctags).')', array($prj->id, $user->id)); + break; + case 'ownerclosed': + $titleFormat = __('%1$s %2$s Closed Working %3$s Issues'); + $f_sql = new Pluf_SQL('project=%s AND owner=%s AND status IN ('.implode(', ', $ctags).')', array($prj->id, $user->id)); + break; + default: + $titleFormat = __('%1$s %2$s Working %3$s Issues'); + $f_sql = new Pluf_SQL('project=%s AND owner=%s AND status IN ('.implode(', ', $otags).')', array($prj->id, $user->id)); + break; + } + $title = sprintf($titleFormat, + $user->first_name, + $user->last_name, + (string) $prj); + + // Get stats about the issues + $sql = new Pluf_SQL('project=%s AND submitter=%s AND status IN ('.implode(', ', $otags).')', array($prj->id, $user->id)); + $nb_submit = Pluf::factory('IDF_Issue')->getCount(array('filter'=>$sql->gen())); + $sql = new Pluf_SQL('project=%s AND owner=%s AND status IN ('.implode(', ', $otags).')', array($prj->id, $user->id)); + $nb_owner = Pluf::factory('IDF_Issue')->getCount(array('filter'=>$sql->gen())); + // Closed issues + $sql = new Pluf_SQL('project=%s AND submitter=%s AND status IN ('.implode(', ', $ctags).')', array($prj->id, $user->id)); + $nb_submit_closed = Pluf::factory('IDF_Issue')->getCount(array('filter'=>$sql->gen())); + $sql = new Pluf_SQL('project=%s AND owner=%s AND status IN ('.implode(', ', $ctags).')', array($prj->id, $user->id)); + $nb_owner_closed = Pluf::factory('IDF_Issue')->getCount(array('filter'=>$sql->gen())); + + // Paginator to paginate the issues + $pag = new Pluf_Paginator(new IDF_Issue()); + $pag->class = 'recent-issues'; + $pag->item_extra_props = array('project_m' => $prj, + 'shortname' => $prj->shortname, + 'current_user' => $request->user); + $pag->summary = __('This table shows the open issues.'); + $pag->forced_where = $f_sql; + $pag->action = array('IDF_Views_Issue::userIssues', array($prj->shortname, $match[2])); + $pag->sort_order = array('modif_dtime', 'ASC'); // will be reverted + $pag->sort_reverse_order = array('modif_dtime'); + $pag->sort_link_title = true; + $pag->extra_classes = array('a-c', '', 'a-c', ''); + $list_display = array( + 'id' => __('Id'), + array('summary', 'IDF_Views_Issue_SummaryAndLabels', __('Summary')), + array('status', 'IDF_Views_Issue_ShowStatus', __('Status')), + array('modif_dtime', 'Pluf_Paginator_DateAgo', __('Last Updated')), + ); + $pag->configure($list_display, array(), array('id', 'status', 'modif_dtime')); + $pag->items_per_page = 10; + $pag->no_results_text = __('No issues were found.'); + $pag->setFromRequest($request); + return Pluf_Shortcuts_RenderToResponse('idf/issues/userIssues.html', + array('project' => $prj, + 'page_title' => $title, + 'login' => $user->login, + 'nb_submit' => $nb_submit, + 'nb_owner' => $nb_owner, + 'nb_submit_closed' => $nb_submit_closed, + 'nb_owner_closed' => $nb_owner_closed, + 'issues' => $pag, + ), + $request); + } + + public $create_precond = array('IDF_Precondition::accessIssues', + 'Pluf_Precondition::loginRequired'); + public function create($request, $match, $api=false) + { + $prj = $request->project; + $title = __('Submit a new issue'); + $params = array( + 'project' => $prj, + 'user' => $request->user); + $preview = (isset($request->POST['preview'])) ? + $request->POST['content'] : false; + if ($request->method == 'POST') { + $form = new IDF_Form_IssueCreate(array_merge($request->POST, + $request->FILES), + $params); + if (!isset($request->POST['preview']) and $form->isValid()) { + $issue = $form->save(); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view', + array($prj->shortname, $issue->id)); + $issue->notify($request->conf); + if ($api) return $issue; + $request->user->setMessage(sprintf(__('Issue %2$d has been created.'), $url, $issue->id)); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $form = new IDF_Form_IssueCreate(null, $params); + } + $params = array_merge( + array('project' => $prj, + 'form' => $form, + 'page_title' => $title, + 'preview' => $preview, + 'issue' => new IDF_Issue(), + ), + self::autoCompleteArrays($prj) + ); + if ($api == true) return $params; + return Pluf_Shortcuts_RenderToResponse('idf/issues/create.html', + $params, $request); + } + + public $search_precond = array('IDF_Precondition::accessIssues'); + public function search($request, $match) + { + $query = !isset($request->REQUEST['q']) ? '' : $request->REQUEST['q']; + return $this->doSearch($request, $query, 'open'); + } + + public $searchStatus_precond = array('IDF_Precondition::accessIssues'); + public function searchStatus($request, $match) + { + $query = !isset($request->REQUEST['q']) ? '' : $request->REQUEST['q']; + $status = in_array($match[2], array('open', 'closed')) ? $match[2] : 'open'; + return $this->doSearch($request, $query, $status); + } + + public $searchLabel_precond = array('IDF_Precondition::accessIssues'); + public function searchLabel($request, $match) + { + $query = !isset($request->REQUEST['q']) ? '' : $request->REQUEST['q']; + $tag_id = intval($match[2]); + $status = in_array($match[3], array('open', 'closed')) ? $match[3] : 'open'; + return $this->doSearch($request, $query, $status, $tag_id); + } + + private function doSearch($request, $query, $status, $tag_id=null) + { + $prj = $request->project; + if (trim($query) == '') { + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::index', array($prj->shortname)); + return new Pluf_HTTP_Response_Redirect($url); + } + + $tag = null; + if ($tag_id !== null) { + $tag = Pluf_Shortcuts_GetObjectOr404('IDF_Tag', $tag_id); + } + + $title = sprintf(__('Search issues - %s'), $query); + if ($status === 'closed') { + $title = sprintf(__('Search closed issues - %s'), $query); + } + + // using Plufs ResultSet implementation here is inefficient, because + // it makes a SELECT for each item and does not allow for further + // filtering neither, so we just return the ids and filter by them + // and other things in the next round + $results = IDF_Search::mySearch($query, $prj, 'IDF_Issue'); + + $issue_ids = array(0); + foreach ($results as $result) { + $issue_ids[] = $result['model_id']; + } + + $otags = $prj->getTagIdsByStatus($status); + if (count($otags) == 0) $otags[] = 0; + $sql = new Pluf_SQL( + 'id IN ('.implode(',', $issue_ids).') '. + 'AND status IN ('.implode(', ', $otags).') '. + ($tag_id !== null ? 'AND idf_tag_id='.$tag_id.' ' : '') + ); + $model = new IDF_Issue(); + $issues = $model->getList(array('filter' => $sql->gen(), 'view' => 'join_tags')); + + // we unfortunately loose the original sort order, + // so we manually have to apply it here again + $sorted_issues = new ArrayObject(); + $filtered_issue_ids = array(0); + foreach ($issue_ids as $issue_id) { + foreach ($issues as $issue) { + if ($issue->id != $issue_id) + continue; + if (array_key_exists($issue_id, $sorted_issues)) + continue; + $sorted_issues[$issue_id] = $issue; + $filtered_issue_ids[] = $issue_id; + } + } + + $pag = new Pluf_Paginator(); + $pag->class = 'recent-issues'; + $pag->items = $sorted_issues; + $pag->item_extra_props = array( + 'project_m' => $prj, + 'shortname' => $prj->shortname, + 'current_user' => $request->user + ); + $pag->summary = __('This table shows the found issues.'); + $pag->extra_classes = array('a-c', '', 'a-c', ''); + $pag->configure(array( + 'id' => __('Id'), + array('summary', 'IDF_Views_Issue_SummaryAndLabels', __('Summary')), + array('status', 'IDF_Views_Issue_ShowStatus', __('Status')), + array('modif_dtime', 'Pluf_Paginator_DateAgo', __('Last Updated')), + )); + // disable paginating + $pag->items_per_page = PHP_INT_MAX; + $pag->no_results_text = __('No issues were found.'); + $pag->setFromRequest($request); + + if ($tag_id === null) { + $pag->action = array('IDF_Views_Issue::searchStatus', + array($prj->shortname, $status), + array('q'=> $query), + ); + } else { + $pag->action = array('IDF_Views_Issue::searchLabel', + array($prj->shortname, $tag_id, $status), + array('q'=> $query), + ); + } + + // get stats about the issues + $open = $prj->getIssueCountByStatus('open', $tag, $issue_ids); + $closed = $prj->getIssueCountByStatus('closed', $tag, $issue_ids); + + // query the available tags for this search result + $all_tags = $prj->getTagsByIssues($filtered_issue_ids); + $grouped_tags = array(); + foreach ($all_tags as $atag) { + // group by class + if (!array_key_exists($atag->class, $grouped_tags)) { + $grouped_tags[$atag->class] = array(); + } + $grouped_tags[$atag->class][] = $atag; + } + + $params = array( + 'page_title' => $title, + 'issues' => $pag, + 'query' => $query, + 'status' => $status, + 'open' => $open, + 'closed' => $closed, + 'tag' => $tag, + 'all_tags' => $grouped_tags, + ); + + return Pluf_Shortcuts_RenderToResponse('idf/issues/search.html', $params, $request); + } + + public $view_precond = array('IDF_Precondition::accessIssues'); + public function view($request, $match) + { + $prj = $request->project; + $issue = Pluf_Shortcuts_GetObjectOr404('IDF_Issue', $match[2]); + $prj->inOr404($issue); + $comments = $issue->get_comments_list(array('order' => 'id ASC')); + $related_issues = $issue->getGroupedRelatedIssues(array('order' => 'other_issue ASC')); + + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view', + array($prj->shortname, $issue->id)); + $title = Pluf_Template::markSafe(sprintf(__('Issue %2$d: %3$s'), $url, $issue->id, Pluf_esc($issue->summary))); + $form = false; // The form is available only if logged in. + $starred = false; + $closed = in_array($issue->status, $prj->getTagIdsByStatus('closed')); + $interested = $issue->get_interested_list(); + $preview = (isset($request->POST['preview'])) ? + $request->POST['content'] : false; + if (!$request->user->isAnonymous()) { + $starred = Pluf_Model_InArray($request->user, $issue->get_interested_list()); + $params = array( + 'project' => $prj, + 'user' => $request->user, + 'issue' => $issue, + ); + if ($request->method == 'POST') { + $form = new IDF_Form_IssueUpdate(array_merge($request->POST, + $request->FILES), + $params); + if (!isset($request->POST['preview']) && $form->isValid()) { + $issue = $form->save(); // Note, should return the + // last comment + $issue->notify($request->conf, false); + $comments = $issue->get_comments_list(array('order' => 'id DESC')); + $url .= '#ic' . $comments[0]->id; + $request->user->setMessage(sprintf(__('Issue %2$d has been updated.'), $url, $issue->id)); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $form = new IDF_Form_IssueUpdate(null, $params); + } + } + + // Search previous and next issue id + $octags = $prj->getTagIdsByStatus(($closed) ? 'closed' : 'open'); + if (count($octags) == 0) $octags[] = 0; + $sql_previous = new Pluf_SQL('project=%s AND status IN ('.implode(', ', $octags).') AND id<%s', + array($prj->id, $match[2]) + ); + $sql_next = new Pluf_SQL('project=%s AND status IN ('.implode(', ', $octags).') AND id>%s', + array($prj->id, $match[2]) + ); + $previous_issue = Pluf::factory('IDF_Issue')->getList(array('filter' => $sql_previous->gen(), + 'order' => 'id DESC', + 'nb' => 1 + )); + $next_issue = Pluf::factory('IDF_Issue')->getList(array('filter' => $sql_next->gen(), + 'order' => 'id ASC', + 'nb' => 1 + )); + $previous_issue_id = (isset($previous_issue[0])) ? $previous_issue[0]->id : 0; + $next_issue_id = (isset($next_issue[0])) ? $next_issue[0]->id : 0; + + $arrays = self::autoCompleteArrays($prj); + return Pluf_Shortcuts_RenderToResponse('idf/issues/view.html', + array_merge( + array( + 'issue' => $issue, + 'comments' => $comments, + 'form' => $form, + 'starred' => $starred, + 'page_title' => $title, + 'closed' => $closed, + 'preview' => $preview, + 'interested' => $interested->count(), + 'previous_issue_id' => $previous_issue_id, + 'next_issue_id' => $next_issue_id, + 'related_issues' => $related_issues, + ), + $arrays), + $request); + } + + + /** + * Download a given attachment. + */ + public $getAttachment_precond = array('IDF_Precondition::accessIssues'); + public function getAttachment($request, $match) + { + $prj = $request->project; + $attach = Pluf_Shortcuts_GetObjectOr404('IDF_IssueFile', $match[2]); + $prj->inOr404($attach->get_comment()->get_issue()); + $info = IDF_FileUtil::getMimeType($attach->filename); + $mime = 'application/octet-stream'; + if (strpos($info[0], 'image/') === 0) { + $mime = $info[0]; + } + $res = new Pluf_HTTP_Response_File(Pluf::f('upload_issue_path').'/'.$attach->attachment, + $mime); + if ($mime == 'application/octet-stream') { + $res->headers['Content-Disposition'] = 'attachment; filename="'.$attach->filename.'"'; + } + return $res; + } + + /** + * View a given attachment. + */ + public $viewAttachment_precond = array('IDF_Precondition::accessIssues'); + public function viewAttachment($request, $match) + { + $prj = $request->project; + $attach = Pluf_Shortcuts_GetObjectOr404('IDF_IssueFile', $match[2]); + $prj->inOr404($attach->get_comment()->get_issue()); + // If one cannot see the attachement, redirect to the + // getAttachment view. + $info = IDF_FileUtil::getMimeType($attach->filename); + if (!IDF_FileUtil::isText($info)) { + return $this->getAttachment($request, $match); + } + // Now we want to look at the file but with links back to the + // issue. + $file = IDF_FileUtil::highLight($info, + file_get_contents(Pluf::f('upload_issue_path').'/'.$attach->attachment)); + $title = sprintf(__('View %s'), $attach->filename); + return Pluf_Shortcuts_RenderToResponse('idf/issues/attachment.html', + array( + 'attachment' => $attach, + 'page_title' => $title, + 'comment' => $attach->get_comment(), + 'issue' => $attach->get_comment()->get_issue(), + 'file' => $file, + ), + $request); + } + + /** + * View list of issues for a given project with a given status. + */ + public $listStatus_precond = array('IDF_Precondition::accessIssues'); + public function listStatus($request, $match) + { + $prj = $request->project; + $status = $match[2]; + + if (mb_strtolower($status) == 'open') { + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::index', + array($prj->shortname)); + return new Pluf_HTTP_Response_Redirect($url); + } + + $title = sprintf(__('%s Closed Issues'), (string) $prj); + // Get stats about the issues + $open = $prj->getIssueCountByStatus('open'); + $closed = $prj->getIssueCountByStatus('closed'); + // Paginator to paginate the issues + $pag = new Pluf_Paginator(new IDF_Issue()); + $pag->class = 'recent-issues'; + $pag->item_extra_props = array('project_m' => $prj, + 'shortname' => $prj->shortname, + 'current_user' => $request->user); + $pag->summary = __('This table shows the closed issues.'); + $otags = $prj->getTagIdsByStatus('closed'); + if (count($otags) == 0) $otags[] = 0; + $pag->forced_where = new Pluf_SQL('project=%s AND status IN ('.implode(', ', $otags).')', array($prj->id)); + $pag->action = array('IDF_Views_Issue::listStatus', array($prj->shortname, $status)); + $pag->sort_order = array('modif_dtime', 'ASC'); // will be reverted + $pag->sort_reverse_order = array('modif_dtime'); + $pag->sort_link_title = true; + $pag->extra_classes = array('a-c', '', 'a-c', ''); + $list_display = array( + 'id' => __('Id'), + array('summary', 'IDF_Views_Issue_SummaryAndLabels', __('Summary')), + array('status', 'IDF_Views_Issue_ShowStatus', __('Status')), + array('modif_dtime', 'Pluf_Paginator_DateAgo', __('Last Updated')), + ); + $pag->configure($list_display, array(), array('id', 'status', 'modif_dtime')); + $pag->items_per_page = 10; + $pag->no_results_text = __('No issues were found.'); + $pag->setFromRequest($request); + return Pluf_Shortcuts_RenderToResponse('idf/issues/index.html', + array('project' => $prj, + 'page_title' => $title, + 'open' => $open, + 'closed' => $closed, + 'issues' => $pag, + 'cloud' => 'closed_issues', + ), + $request); + } + + /** + * View list of issues for a given project with a given label. + */ + public $listLabel_precond = array('IDF_Precondition::accessIssues'); + public function listLabel($request, $match) + { + $prj = $request->project; + $tag = Pluf_Shortcuts_GetObjectOr404('IDF_Tag', $match[2]); + $status = $match[3]; + if ($tag->project != $prj->id or !in_array($status, array('open', 'closed'))) { + throw new Pluf_HTTP_Error404(); + } + if ($status == 'open') { + $title = sprintf(__('%1$s Issues with Label %2$s'), (string) $prj, + (string) $tag); + } else { + $title = sprintf(__('%1$s Closed Issues with Label %2$s'), + (string) $prj, (string) $tag); + } + // Get stats about the open/closed issues having this tag. + $open = $prj->getIssueCountByStatus('open', $tag); + $closed = $prj->getIssueCountByStatus('closed', $tag); + // Paginator to paginate the issues + $pag = new Pluf_Paginator(new IDF_Issue()); + $pag->model_view = 'join_tags'; + $pag->class = 'recent-issues'; + $pag->item_extra_props = array('project_m' => $prj, + 'shortname' => $prj->shortname, + 'current_user' => $request->user); + $pag->summary = sprintf(__('This table shows the issues with label %s.'), (string) $tag); + $otags = $prj->getTagIdsByStatus($status); + if (count($otags) == 0) $otags[] = 0; + $pag->forced_where = new Pluf_SQL('project=%s AND idf_tag_id=%s AND status IN ('.implode(', ', $otags).')', array($prj->id, $tag->id)); + $pag->action = array('IDF_Views_Issue::listLabel', array($prj->shortname, $tag->id, $status)); + $pag->sort_order = array('modif_dtime', 'ASC'); // will be reverted + $pag->sort_reverse_order = array('modif_dtime'); + $pag->sort_link_title = true; + $pag->extra_classes = array('a-c', '', 'a-c', ''); + $list_display = array( + 'id' => __('Id'), + array('summary', 'IDF_Views_Issue_SummaryAndLabels', __('Summary')), + array('status', 'IDF_Views_Issue_ShowStatus', __('Status')), + array('modif_dtime', 'Pluf_Paginator_DateAgo', __('Last Updated')), + ); + $pag->configure($list_display, array(), array('id', 'status', 'modif_dtime')); + $pag->items_per_page = 10; + $pag->no_results_text = __('No issues were found.'); + $pag->setFromRequest($request); + if (($open+$closed) > 0) { + $completion = sprintf('%01.0f%%', (100*$closed)/((float) $open+$closed)); + } else { + $completion = false; + } + return Pluf_Shortcuts_RenderToResponse('idf/issues/by-label.html', + array('project' => $prj, + 'completion' => $completion, + 'page_title' => $title, + 'open' => $open, + 'label' => $tag, + 'closed' => $closed, + 'issues' => $pag, + ), + $request); + } + + /** + * Renders a JSON string containing completed issue information + * based on the queried / partial string + */ + public $autoCompleteIssueList_precond = array('IDF_Precondition::accessIssues'); + public function autoCompleteIssueList($request, $match) + { + $prj = $request->project; + $issue_id = !empty($match[2]) ? intval($match[2]) : 0; + $query = trim($request->REQUEST['q']); + $limit = !empty($request->REQUEST['limit']) ? intval($request->REQUEST['limit']) : 0; + $limit = max(10, $limit); + + $issues = array(); + + // empty search, return the most recently updated issues + if (empty($query)) { + $sql = new Pluf_SQL('project=%s', array($prj->id)); + $tmp = Pluf::factory('IDF_Issue')->getList(array( + 'filter' => $sql->gen(), + 'order' => 'modif_dtime DESC' + )); + $issues += $tmp->getArrayCopy(); + } + else { + // ID-based search + if (is_numeric($query)) { + $sql = 'project=%s AND CAST(id AS VARCHAR) LIKE %s'; + // MySQL can't cast to VARCHAR and a CAST to CHAR converts + // the whole number, not just the first digit + if (strtolower(Pluf::f('db_engine')) == 'mysql') { + $sql = 'project=%s AND CAST(id AS CHAR) LIKE %s'; + } + $sql = new Pluf_SQL($sql, array($prj->id, $query.'%')); + $tmp = Pluf::factory('IDF_Issue')->getList(array( + 'filter' => $sql->gen(), + 'order' => 'id ASC' + )); + $issues += $tmp->getArrayCopy(); + } + + // text-based search + $res = new Pluf_Search_ResultSet( + IDF_Search::mySearch($query, $prj, 'IDF_Issue') + ); + foreach ($res as $issue) + $issues[] = $issue; + } + + // Autocomplete from jQuery UI works with JSON, this old one still + // expects a parsable string; since we'd need to bump jQuery beyond + // 1.2.6 for this to use as well, we're trying to cope with the old format. + // see http://www.learningjquery.com/2010/06/autocomplete-migration-guide + $out = ''; + $ids = array(); + foreach ($issues as $issue) + { + if ($issue->id == $issue_id) + continue; + + if (in_array($issue->id, $ids)) + continue; + + if (--$limit < 0) + break; + + $out .= str_replace('|', '|', $issue->summary) .'|'.$issue->id."\n"; + $ids[] = $issue->id; + } + + return new Pluf_HTTP_Response($out); + } + + /** + * Star/Unstar an issue. + */ + public $star_precond = array('IDF_Precondition::accessIssues', + 'Pluf_Precondition::loginRequired'); + public function star($request, $match) + { + $prj = $request->project; + $issue = Pluf_Shortcuts_GetObjectOr404('IDF_Issue', $match[2]); + $prj->inOr404($issue); + if ($request->method == 'POST') { + $starred = Pluf_Model_InArray($request->user, $issue->get_interested_list()); + if ($starred) { + $issue->delAssoc($request->user); + $request->user->setMessage(__('The issue has been removed from your watch list.')); + } else { + $issue->setAssoc($request->user); + $request->user->setMessage(__('The issue has been added to your watch list.')); + } + } + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view', + array($prj->shortname, $issue->id)); + return new Pluf_HTTP_Response_Redirect($url); + } + + /** + * Create the autocomplete arrays for the little AJAX stuff. + */ + public static function autoCompleteArrays($project) + { + $conf = new IDF_Conf(); + $conf->setProject($project); + $auto = array('auto_status' => '', 'auto_labels' => ''); + $auto_raw = array('auto_status' => '', 'auto_labels' => ''); + $st = $conf->getVal('labels_issue_open', IDF_Form_IssueTrackingConf::init_open); + $st .= "\n".$conf->getVal('labels_issue_closed', IDF_Form_IssueTrackingConf::init_closed); + $auto_raw['auto_status'] = $st; + $auto_raw['auto_labels'] = $conf->getVal('labels_issue_predefined', IDF_Form_IssueTrackingConf::init_predefined); + foreach ($auto_raw as $key => $st) { + $st = preg_split("/\015\012|\015|\012/", $st, -1, PREG_SPLIT_NO_EMPTY); + foreach ($st as $s) { + $v = ''; + $d = ''; + $_s = explode('=', $s, 2); + if (count($_s) > 1) { + $v = trim($_s[0]); + $d = trim($_s[1]); + } else { + $v = trim($_s[0]); + } + $auto[$key] .= sprintf('{ name: "%s", to: "%s" }, ', + Pluf_esc($d), + Pluf_esc($v)); + } + $auto[$key] = substr($auto[$key], 0, -2); + } + // Get the members/owners + $m = $project->getMembershipData(); + $auto['_auto_owner'] = $m['members']; + $auto['auto_owner'] = ''; + foreach ($m['owners'] as $owner) { + if (!Pluf_Model_InArray($owner, $auto['_auto_owner'])) { + $auto['_auto_owner'][] = $owner; + } + } + foreach ($auto['_auto_owner'] as $owner) { + $auto['auto_owner'] .= sprintf('{ name: "%s", to: "%s" }, ', + Pluf_esc($owner), + Pluf_esc($owner->login)); + } + $auto['auto_owner'] = substr($auto['auto_owner'], 0, -2); + unset($auto['_auto_owner']); + // Get issue relations + $r = $project->getRelationsFromConfig(); + $auto['auto_relation_types'] = ''; + foreach ($r as $rt) { + $auto['auto_relation_types'] .= sprintf('{ name: "%s", to: "%s" }, ', + Pluf_esc(__($rt)), Pluf_esc($rt)); + } + $auto['auto_relation_types'] = substr($auto['auto_relation_types'], 0, -2); + return $auto; + } +} + +/** + * When you access to your forge watch list, issue don't known + * the project shortname. + */ +function IDF_Views_Issue_SummaryAndLabelsUnknownProject($field, $issue, $extra='') +{ + $shortname = $issue->get_project()->shortname; + $issue->__set('shortname', $shortname); + return IDF_Views_Issue_SummaryAndLabels ($field, $issue, $extra); +} + +/** + * Display the summary of an issue, then on a new line, display the + * list of labels with a link to a view "by label only". + * + * The summary of the issue is linking to the issue. + */ +function IDF_Views_Issue_SummaryAndLabels($field, $issue, $extra='') +{ + $edit = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view', + array($issue->shortname, $issue->id)); + $tags = array(); + foreach ($issue->get_tags_list() as $tag) { + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::listLabel', + array($issue->shortname, $tag->id, 'open')); + $tags[] = sprintf('%s', $url, Pluf_esc((string) $tag)); + } + $s = ''; + if (!$issue->current_user->isAnonymous() and + Pluf_Model_InArray($issue->current_user, $issue->get_interested_list())) { + $s = ''.__('On your watch list.').' '; + } + $out = ''; + if (count($tags)) { + $out = '
'.implode(', ', $tags).''; + } + return $s.sprintf('%s', $edit, Pluf_esc($issue->summary)).$out; +} + +/** + * Display the status in the issue listings. + * + */ +function IDF_Views_Issue_ShowStatus($field, $issue, $extra='') +{ + return Pluf_esc($issue->get_status()->name); +} + + diff --git a/indefero/src/IDF/Views/Project.php b/indefero/src/IDF/Views/Project.php new file mode 100644 index 0000000..8029839 --- /dev/null +++ b/indefero/src/IDF/Views/Project.php @@ -0,0 +1,655 @@ +project; + + $logo = $prj->getConf()->getVal('logo'); + if (empty($logo)) { + $url = Pluf::f('url_media') . '/idf/img/no_logo.png'; + return new Pluf_HTTP_Response_Redirect($url); + } + + $info = IDF_FileUtil::getMimeType($logo); + return new Pluf_HTTP_Response_File(Pluf::f('upload_path') . '/' . $prj->shortname . $logo, + $info[0]); + } + + /** + * Home page of a project. + */ + public $home_precond = array('IDF_Precondition::baseAccess'); + public function home($request, $match) + { + $prj = $request->project; + $team = $prj->getMembershipData(); + $title = (string) $prj; + $downloads = array(); + if ($request->rights['hasDownloadsAccess']) { + $tags = IDF_Views_Download::getDownloadTags($prj); + // the first tag is the featured, the last is the deprecated. + $downloads = $tags[0]->get_idf_upload_list(); + } + $pages = array(); + if ($request->rights['hasWikiAccess']) { + $tags = IDF_Views_Wiki::getWikiTags($prj); + $pages = $tags[0]->get_idf_wiki_page_list(); + } + return Pluf_Shortcuts_RenderToResponse('idf/project/home.html', + array( + 'page_title' => $title, + 'team' => $team, + 'downloads' => $downloads, + 'pages' => $pages, + ), + $request); + } + + /** + * Returns an associative array with all accessible model filters + * + * @return array + */ + private static function getAccessibleModelFilters($request) + { + $filters = array('all' => __('All Updates')); + + if (true === IDF_Precondition::accessSource($request)) + $filters['commits'] = __('Commits'); + if (true === IDF_Precondition::accessIssues($request)) + $filters['issues'] = __('Issues and Comments'); + if (true === IDF_Precondition::accessDownloads($request)) + $filters['downloads'] = __('Downloads'); + if (true === IDF_Precondition::accessWiki($request)) + $filters['documents'] = __('Documents'); + if (true === IDF_Precondition::accessReview($request)) + $filters['reviews'] = __('Reviews and Patches'); + + return $filters; + } + + /** + * Returns an array of model classes for which the current user + * has rights and which should be used according to his filter + * + * @param object $request + * @param string $model_filter + * @return array + */ + private static function determineModelClasses($request, $model_filter = 'all') + { + $classes = array(); + if (true === IDF_Precondition::accessSource($request) && + ($model_filter == 'all' || $model_filter == 'commits')) { + $classes[] = '\'IDF_Commit\''; + // FIXME: this looks like a hack... + IDF_Scm::syncTimeline($request->project); + } + if (true === IDF_Precondition::accessIssues($request) && + ($model_filter == 'all' || $model_filter == 'issues')) { + $classes[] = '\'IDF_Issue\''; + $classes[] = '\'IDF_IssueComment\''; + } + if (true === IDF_Precondition::accessDownloads($request) && + ($model_filter == 'all' || $model_filter == 'downloads')) { + $classes[] = '\'IDF_Upload\''; + } + if (true === IDF_Precondition::accessWiki($request) && + ($model_filter == 'all' || $model_filter == 'documents')) { + $classes[] = '\'IDF_Wiki_Page\''; + $classes[] = '\'IDF_Wiki_PageRevision\''; + $classes[] = '\'IDF_Wiki_Resource\''; + $classes[] = '\'IDF_Wiki_ResourceRevision\''; + } + if (true === IDF_Precondition::accessReview($request) && + ($model_filter == 'all' || $model_filter == 'reviews')) { + $classes[] = '\'IDF_Review_Comment\''; + $classes[] = '\'IDF_Review_Patch\''; + } + if (count($classes) == 0) { + $classes[] = '\'IDF_Dummy\''; + } + + return $classes; + } + + /** + * This action serves as URI compatibility layer for v1.0. + * + * @deprecated + */ + public function timelineCompat($request, $match) + { + $match[2] = 'all'; + return $this->timeline($request, $match); + } + + /** + * Timeline of the project. + */ + public $timeline_precond = array('IDF_Precondition::baseAccess'); + public function timeline($request, $match) + { + $prj = $request->project; + + $model_filter = @$match[2]; + $accessible_model_filters = self::getAccessibleModelFilters($request); + if (!array_key_exists($model_filter, $accessible_model_filters)) { + $model_filter = 'all'; + } + $title = (string)$prj . ' ' . $accessible_model_filters[$model_filter]; + + $pag = new IDF_Timeline_Paginator(new IDF_Timeline()); + $pag->class = 'recent-issues'; + $pag->item_extra_props = array('request' => $request); + $pag->summary = __('This table shows the project updates.'); + + $classes = self::determineModelClasses($request, $model_filter); + $sql = sprintf('model_class IN (%s)', implode(', ', $classes)); + $pag->forced_where = new Pluf_SQL('project=%s AND '.$sql, + array($prj->id)); + $pag->sort_order = array('creation_dtime', 'ASC'); + $pag->sort_reverse_order = array('creation_dtime'); + $pag->action = array('IDF_Views_Project::timeline', array($prj->shortname, $model_filter)); + $list_display = array( + 'creation_dtime' => __('Age'), + 'id' => __('Change'), + ); + $pag->configure($list_display, array(), array('creation_dtime')); + $pag->items_per_page = 20; + $pag->no_results_text = __('No changes were found.'); + $pag->setFromRequest($request); + + if (!$request->user->isAnonymous() and $prj->isRestricted()) { + $feedurl = Pluf_HTTP_URL_urlForView('idf_project_timeline_feed_auth', + array($prj->shortname, + $model_filter, + IDF_Precondition::genFeedToken($prj, $request->user))); + } else { + $feedurl = Pluf_HTTP_URL_urlForView('idf_project_timeline_feed', + array($prj->shortname, $model_filter)); + } + return Pluf_Shortcuts_RenderToResponse('idf/project/timeline.html', + array( + 'page_title' => $title, + 'feedurl' => $feedurl, + 'timeline' => $pag, + 'model_filter' => $model_filter, + 'accessible_model_filters' => $accessible_model_filters, + ), + $request); + + } + + /** + * This action serves as URI compatibility layer for v1.0. + * + * @deprecated + */ + public function timelineFeedCompat($request, $match) + { + $match[2] = 'all'; + return $this->timelineFeed($request, $match); + } + + /** + * Timeline feed. + * + * A custom view to have a bit more control on the way to handle + * it and optimize the output. + * + */ + public $timelineFeed_precond = array('IDF_Precondition::feedSetUser', + 'IDF_Precondition::baseAccess'); + public function timelineFeed($request, $match) + { + $prj = $request->project; + $model_filter = @$match[2]; + + $accessible_model_filters = self::getAccessibleModelFilters($request); + if (!array_key_exists($model_filter, $accessible_model_filters)) { + $model_filter = 'all'; + } + $title = $accessible_model_filters[$model_filter]; + + $classes = self::determineModelClasses($request, $model_filter); + $sqls = sprintf('model_class IN (%s)', implode(', ', $classes)); + $sql = new Pluf_SQL('project=%s AND '.$sqls, array($prj->id)); + $params = array( + 'filter' => $sql->gen(), + 'order' => 'creation_dtime DESC', + 'nb' => 20, + ); + $items = Pluf::factory('IDF_Timeline')->getList($params); + $set = new Pluf_Model_Set($items, + array('public_dtime' => 'public_dtime')); + $out = array(); + foreach ($set as $item) { + if ($item->id) { + $out[] = $item->feedFragment($request); + } + } + if ($items->count() > 0) { + $date = Pluf_Date::gmDateToGmString($items[0]->creation_dtime); + } else { + $date = gmdate('c'); + } + $out = Pluf_Template::markSafe(implode("\n", $out)); + $tmpl = new Pluf_Template('idf/index.atom'); + $feedurl = Pluf::f('url_base').Pluf::f('idf_base').$request->query; + $viewurl = Pluf_HTTP_URL_urlForView('IDF_Views_Project::timeline', + array($prj->shortname, $model_filter)); + $context = new Pluf_Template_Context_Request($request, + array('body' => $out, + 'date' => $date, + 'title' => $title, + 'feedurl' => $feedurl, + 'viewurl' => $viewurl)); + return new Pluf_HTTP_Response('' + ."\n".$tmpl->render($context), + 'application/atom+xml; charset=utf-8'); + } + + + /** + * Administrate the summary of a project. + */ + public $admin_precond = array('IDF_Precondition::projectOwner'); + public function admin($request, $match) + { + $prj = $request->project; + $title = sprintf(__('%s Project Summary'), (string) $prj); + $extra = array('project' => $prj, 'user' => $request->user); + if ($request->method == 'POST') { + $form = new IDF_Form_ProjectConf(array_merge($request->POST, + $request->FILES), + $extra); + if ($form->isValid()) { + $form->save(); + $request->user->setMessage(__('The project has been updated.')); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Project::admin', + array($prj->shortname)); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $form = new IDF_Form_ProjectConf(null, $extra); + } + + $logo = $prj->getConf()->getVal('logo'); + $arrays = self::autoCompleteArrays(); + return Pluf_Shortcuts_RenderToResponse('idf/admin/summary.html', + array_merge( + array( + 'page_title' => $title, + 'form' => $form, + 'project' => $prj, + 'logo' => $logo, + ), + $arrays + ), + $request); + } + + /** + * Administrate the issue tracking of a project. + */ + public $adminIssues_precond = array('IDF_Precondition::projectOwner'); + public function adminIssues($request, $match) + { + $prj = $request->project; + $title = sprintf(__('%s Issue Tracking Configuration'), (string) $prj); + $conf = new IDF_Conf(); + $conf->setProject($prj); + if ($request->method == 'POST') { + $form = new IDF_Form_IssueTrackingConf($request->POST); + if ($form->isValid()) { + foreach ($form->cleaned_data as $key=>$val) { + $conf->setVal($key, $val); + } + $request->user->setMessage(__('The issue tracking configuration has been saved.')); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Project::adminIssues', + array($prj->shortname)); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $params = array(); + $keys = array('labels_issue_template', + 'labels_issue_open', 'labels_issue_closed', + 'labels_issue_predefined', 'labels_issue_one_max', + 'issue_relations'); + foreach ($keys as $key) { + $_val = $conf->getVal($key, false); + if ($_val !== false) { + $params[$key] = $_val; + } + } + if (count($params) == 0) { + $params = null; //Nothing in the db, so new form. + } + $form = new IDF_Form_IssueTrackingConf($params); + } + return Pluf_Shortcuts_RenderToResponse('idf/admin/issue-tracking.html', + array( + 'page_title' => $title, + 'form' => $form, + ), + $request); + } + + /** + * Administrate the downloads of a project. + */ + public $adminDownloads_precond = array('IDF_Precondition::projectOwner'); + public function adminDownloads($request, $match) + { + $prj = $request->project; + $title = sprintf(__('%s Downloads Configuration'), (string) $prj); + $conf = new IDF_Conf(); + $conf->setProject($prj); + $extra = array( + 'conf' => $conf, + ); + if ($request->method == 'POST') { + $form = new IDF_Form_UploadConf($request->POST, $extra); + if ($form->isValid()) { + foreach ($form->cleaned_data as $key=>$val) { + $conf->setVal($key, $val); + } + $request->user->setMessage(__('The downloads configuration has been saved.')); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Project::adminDownloads', + array($prj->shortname)); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $params = array(); + $keys = array('labels_download_predefined', 'labels_download_one_max', 'upload_webhook_url'); + foreach ($keys as $key) { + $_val = $conf->getVal($key, false); + if ($_val !== false) { + $params[$key] = $_val; + } + } + if (count($params) == 0) { + $params = null; //Nothing in the db, so new form. + } + $form = new IDF_Form_UploadConf($params, $extra); + } + return Pluf_Shortcuts_RenderToResponse('idf/admin/downloads.html', + array( + 'page_title' => $title, + 'form' => $form, + 'hookkey' => $prj->getWebHookKey(), + ), + $request); + } + + /** + * Administrate the information pages of a project. + */ + public $adminWiki_precond = array('IDF_Precondition::projectOwner'); + public function adminWiki($request, $match) + { + $prj = $request->project; + $title = sprintf(__('%s Documentation Configuration'), (string) $prj); + $conf = new IDF_Conf(); + $conf->setProject($prj); + if ($request->method == 'POST') { + $form = new IDF_Form_WikiConf($request->POST); + if ($form->isValid()) { + foreach ($form->cleaned_data as $key=>$val) { + $conf->setVal($key, $val); + } + $request->user->setMessage(__('The documentation configuration has been saved.')); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Project::adminWiki', + array($prj->shortname)); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $params = array(); + $keys = array('labels_wiki_predefined', 'labels_wiki_one_max'); + foreach ($keys as $key) { + $_val = $conf->getVal($key, false); + if ($_val !== false) { + $params[$key] = $_val; + } + } + if (count($params) == 0) { + $params = null; //Nothing in the db, so new form. + } + $form = new IDF_Form_WikiConf($params); + } + return Pluf_Shortcuts_RenderToResponse('idf/admin/wiki.html', + array( + 'page_title' => $title, + 'form' => $form, + ), + $request); + } + + /** + * Administrate the members of a project. + */ + public $adminMembers_precond = array('IDF_Precondition::projectOwner'); + public function adminMembers($request, $match) + { + $prj = $request->project; + $title = sprintf(__('%s Project Members'), (string) $prj); + $params = array( + 'project' => $prj, + 'user' => $request->user, + ); + if ($request->method == 'POST') { + $form = new IDF_Form_MembersConf($request->POST, $params); + if ($form->isValid()) { + $form->save(); + $request->user->setMessage(__('The project membership has been saved.')); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Project::adminMembers', + array($prj->shortname)); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $form = new IDF_Form_MembersConf($prj->getMembershipData('string'), $params); + } + return Pluf_Shortcuts_RenderToResponse('idf/admin/members.html', + array( + 'page_title' => $title, + 'form' => $form, + ), + $request); + } + + /** + * Administrate the access rights to the tabs. + */ + public $adminTabs_precond = array('IDF_Precondition::projectOwner'); + public function adminTabs($request, $match) + { + $prj = $request->project; + $title = sprintf(__('%s Tabs Access Rights'), (string) $prj); + $extra = array( + 'project' => $prj, + 'conf' => $request->conf, + ); + if ($request->method == 'POST') { + $form = new IDF_Form_TabsConf($request->POST, $extra); + if ($form->isValid()) { + foreach ($form->cleaned_data as $key=>$val) { + if (!in_array($key, array('private_project', 'authorized_users'))) { + $request->conf->setVal($key, $val); + } + } + $form->save(); // Save the authorized users. + $request->user->setMessage(__('The project tabs access rights and notification settings have been saved.')); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Project::adminTabs', + array($prj->shortname)); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $params = array(); + $sections = array('downloads', 'wiki', 'source', 'issues', 'review'); + $keys = array(); + + foreach ($sections as $section) { + $keys[] = $section.'_access_rights'; + $keys[] = $section.'_notification_owners_enabled'; + $keys[] = $section.'_notification_members_enabled'; + $keys[] = $section.'_notification_email_enabled'; + $keys[] = $section.'_notification_email'; + } + + foreach ($keys as $key) { + $_val = $request->conf->getVal($key, false); + if ($_val !== false) { + $params[$key] = $_val; + } + } + // Add the authorized users. + $md = $prj->getMembershipData('string'); + $params['authorized_users'] = $md['authorized']; + $params['private_project'] = $prj->private; + $form = new IDF_Form_TabsConf($params, $extra); + } + return Pluf_Shortcuts_RenderToResponse('idf/admin/tabs.html', + array( + 'page_title' => $title, + 'form' => $form, + 'from_email' => Pluf::f('from_email'), + ), + $request); + } + + /** + * Administrate the source control. + * + * There, the login/password of the subversion remote repo can be + * change together with the webhook url. + */ + public $adminSource_precond = array('IDF_Precondition::projectOwner'); + public function adminSource($request, $match) + { + $prj = $request->project; + $title = sprintf(__('%s Source'), (string) $prj); + + $remote_svn = ($request->conf->getVal('scm') == 'svn' and + strlen($request->conf->getVal('svn_remote_url')) > 0); + $extra = array( + 'conf' => $request->conf, + 'remote_svn' => $remote_svn, + ); + if ($request->method == 'POST') { + $form = new IDF_Form_SourceConf($request->POST, $extra); + if ($form->isValid()) { + foreach ($form->cleaned_data as $key=>$val) { + $request->conf->setVal($key, $val); + } + $request->user->setMessage(__('The project source configuration has been saved.')); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Project::adminSource', + array($prj->shortname)); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $params = array(); + foreach (array('svn_username', 'svn_password', 'webhook_url') as $key) { + $_val = $request->conf->getVal($key, false); + if ($_val !== false) { + $params[$key] = $_val; + } + } + if (count($params) == 0) { + $params = null; //Nothing in the db, so new form. + } + $form = new IDF_Form_SourceConf($params, $extra); + } + $scm = $request->conf->getVal('scm', 'git'); + $options = array( + 'git' => __('git'), + 'svn' => __('Subversion'), + 'mercurial' => __('mercurial'), + 'mtn' => __('monotone'), + ); + $repository_type = $options[$scm]; + $hook_request_method = 'PUT'; + if (Pluf::f('webhook_processing','') === 'compat') { + $hook_request_method = 'POST'; + } + return Pluf_Shortcuts_RenderToResponse('idf/admin/source.html', + array( + 'remote_svn' => $remote_svn, + 'repository_access' => $prj->getRemoteAccessUrl(), + 'repository_type' => $repository_type, + 'repository_size' => $prj->getRepositorySize(), + 'page_title' => $title, + 'form' => $form, + 'hookkey' => $prj->getWebHookKey(), + 'hook_request_method' => $hook_request_method, + ), + $request); + } + + /** + * Create the autocomplete arrays for the little AJAX stuff. + */ + public static function autoCompleteArrays() + { + $forge = IDF_Forge::instance(); + $labels = $forge->getProjectLabels(IDF_Form_Admin_LabelConf::init_project_labels); + + $auto = array('auto_labels' => ''); + $auto_raw = array('auto_labels' => $labels); + foreach ($auto_raw as $key => $st) { + $st = preg_split("/\015\012|\015|\012/", $st, -1, PREG_SPLIT_NO_EMPTY); + foreach ($st as $s) { + $v = ''; + $d = ''; + $_s = explode('=', $s, 2); + if (count($_s) > 1) { + $v = trim($_s[0]); + $d = trim($_s[1]); + } else { + $v = trim($_s[0]); + } + $auto[$key] .= sprintf('{ name: "%s", to: "%s" }, ', + Pluf_esc($d), + Pluf_esc($v)); + } + $auto[$key] = substr($auto[$key], 0, -2); + } + + return $auto; + } +} diff --git a/indefero/src/IDF/Views/Review.php b/indefero/src/IDF/Views/Review.php new file mode 100644 index 0000000..5882ba3 --- /dev/null +++ b/indefero/src/IDF/Views/Review.php @@ -0,0 +1,235 @@ +project; + $title = sprintf(__('%s Code Reviews'), (string) $prj); + // Paginator to paginate the pages + $pag = new Pluf_Paginator(new IDF_Review()); + $pag->class = 'recent-issues'; + $pag->item_extra_props = array('project_m' => $prj, + 'shortname' => $prj->shortname, + 'current_user' => $request->user); + $pag->summary = __('This table shows the latest reviews.'); + $pag->action = array('IDF_Views_Review::index', array($prj->shortname)); + $otags = $prj->getTagIdsByStatus('open'); + if (count($otags) == 0) $otags[] = 0; + $pag->forced_where = new Pluf_SQL('project=%s AND status IN ('.implode(', ', $otags).')', array($prj->id)); + $pag->action = array('IDF_Views_Issue::index', array($prj->shortname)); + $pag->sort_order = array('modif_dtime', 'ASC'); // will be reverted + $pag->sort_reverse_order = array('modif_dtime'); + $list_display = array( + 'id' => __('Id'), + array('summary', 'IDF_Views_Review_SummaryAndLabels', __('Summary')), + array('status', 'IDF_Views_Issue_ShowStatus', __('Status')), + array('modif_dtime', 'Pluf_Paginator_DateAgo', __('Last Updated')), + ); + $pag->configure($list_display, array(), array('title', 'modif_dtime')); + $pag->items_per_page = 25; + $pag->no_results_text = __('No reviews were found.'); + $pag->sort_order = array('modif_dtime', 'ASC'); + $pag->setFromRequest($request); + return Pluf_Shortcuts_RenderToResponse('idf/review/index.html', + array( + 'page_title' => $title, + 'reviews' => $pag, + ), + $request); + } + + /** + * Create a new code review. + */ + public $create_precond = array('IDF_Precondition::accessReview', + 'Pluf_Precondition::loginRequired'); + public function create($request, $match) + { + $prj = $request->project; + $title = __('Start Code Review'); + if ($request->method == 'POST') { + $form = new IDF_Form_ReviewCreate(array_merge($request->POST, + $request->FILES), + array('project' => $prj, + 'user' => $request->user + )); + if ($form->isValid()) { + $review = $form->save(); + $urlr = Pluf_HTTP_URL_urlForView('IDF_Views_Review::view', + array($prj->shortname, $review->id)); + $request->user->setMessage(sprintf(__('The code review %2$d has been created.'), $urlr, $review->id)); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Review::index', + array($prj->shortname)); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $form = new IDF_Form_ReviewCreate(null, + array('project' => $prj, + 'user' => $request->user)); + } + return Pluf_Shortcuts_RenderToResponse('idf/review/create.html', + array( + 'page_title' => $title, + 'form' => $form, + ), + $request); + } + + /** + * Download the patch of a review. + */ + public $getPatch_precond = array('IDF_Precondition::accessReview'); + public function getPatch($request, $match) + { + $prj = $request->project; + $patch = Pluf_Shortcuts_GetObjectOr404('IDF_Review_Patch', $match[2]); + $prj->inOr404($patch->get_review()); + $file = Pluf::f('upload_issue_path').'/'.$patch->patch; + + $rep = new Pluf_HTTP_Response_File($file, 'text/plain'); + $rep->headers['Content-Disposition'] = 'attachment; filename="'.$patch->id.'.diff"'; + return $rep; + + } + + /** + * View a code review. + */ + public $view_precond = array('IDF_Precondition::accessReview'); + public function view($request, $match) + { + $prj = $request->project; + $review = Pluf_Shortcuts_GetObjectOr404('IDF_Review', $match[2]); + $prj->inOr404($review); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Review::view', + array($prj->shortname, $review->id)); + $title = Pluf_Template::markSafe(sprintf(__('Review %2$d: %3$s'), $url, $review->id, Pluf_esc($review->summary))); + + $patches = $review->get_patches_list(); + $patch = $patches[0]; + $diff = new IDF_Diff(file_get_contents(Pluf::f('upload_issue_path').'/'.$patch->patch)); + $diff->parse(); + // The form to submit comments is based on the files in the + // diff + if ($request->method == 'POST' and !$request->user->isAnonymous()) { + $form = new IDF_Form_ReviewFileComment($request->POST, + array('files' => $diff->files, + 'user' => $request->user, + 'patch' => $patch, + 'project' => $prj, + )); + if ($form->isValid()) { + $review_comment = $form->save(); + $review = $patch->get_review(); + $urlr = Pluf_HTTP_URL_urlForView('IDF_Views_Review::view', + array($prj->shortname, $review->id)); + $request->user->setMessage(sprintf(__('Your code review %2$d has been published.'), $urlr, $review->id)); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Review::index', + array($prj->shortname)); + $review_comment->notify($request->conf); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $form = new IDF_Form_ReviewFileComment(null, + array('files' => $diff->files, + 'user' => $request->user, + 'project' => $prj, + 'patch' => $patch,)); + } + $scm = IDF_Scm::get($request->project); + $files = array(); + $reviewers = array(); + foreach ($diff->files as $filename => $def) { + $fileinfo = $scm->getPathInfo($filename, $patch->get_commit()->scm_id); + $sql = new Pluf_SQL('cfile=%s', array($filename)); + $cts = $patch->getFileComments(array('filter'=>$sql->gen(), + 'order'=>'creation_dtime ASC')); + foreach ($cts as $ct) { + $reviewers[] = $ct->get_comment()->get_submitter(); + } + if (count($def['chunks'])) { + $orig_file = ($fileinfo) ? $scm->getFile($fileinfo) : ''; + $files[$filename] = array( + $diff->fileCompare($orig_file, $def, $filename), + $form->f->{md5($filename)}, + $cts, + ); + } else { + $files[$filename] = array('', $form->f->{md5($filename)}, $cts); + } + } + + $reviewers = Pluf_Model_RemoveDuplicates($reviewers); + return Pluf_Shortcuts_RenderToResponse('idf/review/view.html', + array_merge( + array( + 'page_title' => $title, + 'review' => $review, + 'files' => $files, + 'diff' => $diff, + 'patch' => $patch, + 'comments' => $patch->get_comments_list(array('sort' => 'id ASC')), + 'form' => $form, + 'reviewers' => $reviewers, + ), + IDF_Views_Issue::autoCompleteArrays($prj) + ), + $request); + } +} + +/** + * Display the summary of an review, then on a new line, display the + * list of labels with a link to a view "by label only". + * + * The summary of the review is linking to the review. + */ +function IDF_Views_Review_SummaryAndLabels($field, $review, $extra='') +{ + $edit = Pluf_HTTP_URL_urlForView('IDF_Views_Review::view', + array($review->shortname, $review->id)); + $tags = array(); + foreach ($review->get_tags_list() as $tag) { + $tags[] = Pluf_esc($tag); + } + $out = ''; + if (count($tags)) { + $out = '
'.implode(', ', $tags).''; + } + return sprintf('%s', $edit, Pluf_esc($review->summary)).$out; +} + diff --git a/indefero/src/IDF/Views/Source.php b/indefero/src/IDF/Views/Source.php new file mode 100644 index 0000000..225d74a --- /dev/null +++ b/indefero/src/IDF/Views/Source.php @@ -0,0 +1,523 @@ +project); + $scm = IDF_Scm::get($request->project); + $scmConf = $request->conf->getVal('scm', 'git'); + $params = array( + 'page_title' => $title, + 'title' => $title, + 'scm' => $scmConf, + ); + return Pluf_Shortcuts_RenderToResponse('idf/source/'.$scmConf.'/help.html', + $params, $request); + } + + /** + * Is displayed in case an invalid revision is requested + */ + public $invalidRevision_precond = array('IDF_Precondition::accessSource'); + public function invalidRevision($request, $match) + { + $title = sprintf(__('%s Invalid Revision'), (string) $request->project); + $scm = IDF_Scm::get($request->project); + $branches = $scm->getBranches(); + + $commit = $match[2]; + $params = array( + 'page_title' => $title, + 'title' => $title, + 'commit' => $commit, + 'branches' => $branches, + ); + $scmConf = $request->conf->getVal('scm', 'git'); + return Pluf_Shortcuts_RenderToResponse('idf/source/'.$scmConf.'/invalid_revision.html', + $params, $request); + } + + /** + * Is displayed in case a revision identifier cannot be uniquely resolved + * to one single revision + */ + public $disambiguateRevision_precond = array('IDF_Precondition::accessSource', + 'IDF_Views_Source_Precondition::scmAvailable'); + public function disambiguateRevision($request, $match) + { + $title = sprintf(__('%s Ambiguous Revision'), (string) $request->project); + $commit = $match[2]; + $redirect = $match[3]; + $scm = IDF_Scm::get($request->project); + $revisions = $scm->disambiguateRevision($commit); + $params = array( + 'page_title' => $title, + 'title' => $title, + 'commit' => $commit, + 'revisions' => $revisions, + 'redirect' => $redirect, + ); + return Pluf_Shortcuts_RenderToResponse('idf/source/disambiguate_revision.html', + $params, $request); + } + + public $changeLog_precond = array('IDF_Precondition::accessSource', + 'IDF_Views_Source_Precondition::scmAvailable', + 'IDF_Views_Source_Precondition::revisionValid'); + public function changeLog($request, $match) + { + $scm = IDF_Scm::get($request->project); + $branches = $scm->getBranches(); + $commit = $match[2]; + + $title = sprintf(__('%1$s %2$s Change Log'), (string) $request->project, + $this->getScmType($request)); + $changes = $scm->getChangeLog($commit, 25); + $rchanges = array(); + // Sync with the database + foreach ($changes as $change) { + $rchanges[] = IDF_Commit::getOrAdd($change, $request->project); + } + $rchanges = new Pluf_Template_ContextVars($rchanges); + $scmConf = $request->conf->getVal('scm', 'git'); + $in_branches = $scm->inBranches($commit, ''); + $tags = $scm->getTags(); + $in_tags = $scm->inTags($commit, ''); + return Pluf_Shortcuts_RenderToResponse('idf/source/'.$scmConf.'/changelog.html', + array( + 'page_title' => $title, + 'title' => $title, + 'changes' => $rchanges, + 'commit' => $commit, + 'branches' => $branches, + 'tree_in' => $in_branches, + 'tags' => $tags, + 'tags_in' => $in_tags, + 'scm' => $scmConf, + ), + $request); + } + + public function repository($request, $match) + { + $scm = IDF_Scm::get($request->project); + return $scm->repository($request, $match); + } + + public $treeBase_precond = array('IDF_Precondition::accessSource', + 'IDF_Views_Source_Precondition::scmAvailable', + 'IDF_Views_Source_Precondition::revisionValid'); + public function treeBase($request, $match) + { + $scm = IDF_Scm::get($request->project); + $commit = $match[2]; + + $cobject = $scm->getCommit($commit); + if (!$cobject) { + throw new Exception('could not retrieve commit object for '. $commit); + } + $title = sprintf(__('%1$s %2$s Source Tree'), + $request->project, $this->getScmType($request)); + $branches = $scm->getBranches(); + $in_branches = $scm->inBranches($commit, ''); + $tags = $scm->getTags(); + $in_tags = $scm->inTags($commit, ''); + $cache = Pluf_Cache::factory(); + $key = sprintf('Project:%s::IDF_Views_Source::treeBase:%s::', + $request->project->id, $commit); + if (null === ($res=$cache->get($key))) { + $res = new Pluf_Template_ContextVars($scm->getTree($commit)); + $cache->set($key, $res); + } + $scmConf = $request->conf->getVal('scm', 'git'); + $props = $scm->getProperties($commit); + $res->uasort(array('IDF_Views_Source', 'treeSort')); + return Pluf_Shortcuts_RenderToResponse('idf/source/'.$scmConf.'/tree.html', + array( + 'page_title' => $title, + 'title' => $title, + 'files' => $res, + 'cobject' => $cobject, + 'commit' => $commit, + 'tree_in' => $in_branches, + 'branches' => $branches, + 'tags' => $tags, + 'tags_in' => $in_tags, + 'props' => $props, + ), + $request); + } + + public $tree_precond = array('IDF_Precondition::accessSource', + 'IDF_Views_Source_Precondition::scmAvailable', + 'IDF_Views_Source_Precondition::revisionValid'); + public function tree($request, $match) + { + $scm = IDF_Scm::get($request->project); + $commit = $match[2]; + + $request_file = $match[3]; + if (substr($request_file, -1) == '/') { + $request_file = substr($request_file, 0, -1); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::tree', + array($match[1], $match[2], + $request_file)); + return new Pluf_HTTP_Response_Redirect($url, 301); + } + + $request_file_info = $scm->getPathInfo($request_file, $commit); + if (!$request_file_info) { + // Redirect to the main branch + $fburl = Pluf_HTTP_URL_urlForView('IDF_Views_Source::treeBase', + array($request->project->shortname, + $scm->getMainBranch())); + return new Pluf_HTTP_Response_Redirect($fburl); + } + $branches = $scm->getBranches(); + $tags = $scm->getTags(); + if ($request_file_info->type != 'tree') { + $info = self::getRequestedFileMimeType($request_file_info, + $commit, $scm); + if (!IDF_FileUtil::isText($info)) { + $rep = new Pluf_HTTP_Response($scm->getFile($request_file_info), + $info[0]); + $rep->headers['Content-Disposition'] = 'attachment; filename="'.$info[1].'"'; + return $rep; + } else { + // We want to display the content of the file as text + $extra = array('branches' => $branches, + 'tags' => $tags, + 'commit' => $commit, + 'request_file' => $request_file, + 'request_file_info' => $request_file_info, + 'mime' => $info, + ); + return $this->viewFile($request, $match, $extra); + } + } + + $bc = self::makeBreadCrumb($request->project, $commit, $request_file_info->fullpath); + $title = sprintf(__('%1$s %2$s Source Tree'), + $request->project, $this->getScmType($request)); + + $page_title = $bc.' - '.$title; + $cobject = $scm->getCommit($commit); + if (!$cobject) { + // Redirect to the first branch + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::treeBase', + array($request->project->shortname, + $scm->getMainBranch())); + return new Pluf_HTTP_Response_Redirect($url); + } + $in_branches = $scm->inBranches($commit, $request_file); + $in_tags = $scm->inTags($commit, $request_file); + $cache = Pluf_Cache::factory(); + $key = sprintf('Project:%s::IDF_Views_Source::tree:%s::%s', + $request->project->id, $commit, $request_file); + if (null === ($res=$cache->get($key))) { + $res = new Pluf_Template_ContextVars($scm->getTree($commit, $request_file)); + $cache->set($key, $res); + } + // try to find the previous level if it exists. + $prev = explode('/', $request_file); + $l = array_pop($prev); + $previous = substr($request_file, 0, -strlen($l.' ')); + $scmConf = $request->conf->getVal('scm', 'git'); + $props = $scm->getProperties($commit, $request_file); + $res->uasort(array('IDF_Views_Source', 'treeSort')); + return Pluf_Shortcuts_RenderToResponse('idf/source/'.$scmConf.'/tree.html', + array( + 'page_title' => $page_title, + 'title' => $title, + 'breadcrumb' => $bc, + 'files' => $res, + 'commit' => $commit, + 'cobject' => $cobject, + 'base' => $request_file_info->file, + 'prev' => $previous, + 'tree_in' => $in_branches, + 'branches' => $branches, + 'tags' => $tags, + 'tags_in' => $in_tags, + 'props' => $props, + ), + $request); + } + + public static function makeBreadCrumb($project, $commit, $file, $sep='/') + { + $elts = explode('/', $file); + $out = array(); + $stack = ''; + $i = 0; + foreach ($elts as $elt) { + $stack .= ($i==0) ? rawurlencode($elt) : '/'.rawurlencode($elt); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::tree', + array($project->shortname, + $commit, $stack)); + $out[] = ''.Pluf_esc($elt).''; + $i++; + } + return ''.implode(''.$sep.'', $out).''; + } + + public $commit_precond = array('IDF_Precondition::accessSource', + 'IDF_Views_Source_Precondition::scmAvailable', + 'IDF_Views_Source_Precondition::revisionValid'); + public function commit($request, $match) + { + $scm = IDF_Scm::get($request->project); + $commit = $match[2]; + $large = $scm->isCommitLarge($commit); + $cobject = $scm->getCommit($commit, !$large); + if (!$cobject) { + throw new Exception('could not retrieve commit object for '. $commit); + } + $title = sprintf(__('%s Commit Details'), (string) $request->project); + $page_title = sprintf(__('%1$s Commit Details - %2$s'), (string) $request->project, $commit); + $rcommit = IDF_Commit::getOrAdd($cobject, $request->project); + $diff = new IDF_Diff($cobject->diff, $scm->getDiffPathStripLevel()); + $cobject->diff = null; + $diff->parse(); + $scmConf = $request->conf->getVal('scm', 'git'); + $changes = $scm->getChanges($commit); + $branches = $scm->getBranches(); + $in_branches = $scm->inBranches($cobject->commit, ''); + $tags = $scm->getTags(); + $in_tags = $scm->inTags($cobject->commit, ''); + return Pluf_Shortcuts_RenderToResponse('idf/source/'.$scmConf.'/commit.html', + array( + 'page_title' => $page_title, + 'title' => $title, + 'diff' => $diff, + 'cobject' => $cobject, + 'commit' => $commit, + 'changes' => $changes, + 'branches' => $branches, + 'tree_in' => $in_branches, + 'tags' => $tags, + 'tags_in' => $in_tags, + 'scm' => $scmConf, + 'rcommit' => $rcommit, + 'large_commit' => $large, + ), + $request); + } + + public $downloadDiff_precond = array('IDF_Precondition::accessSource', + 'IDF_Views_Source_Precondition::scmAvailable', + 'IDF_Views_Source_Precondition::revisionValid'); + public function downloadDiff($request, $match) + { + $scm = IDF_Scm::get($request->project); + $commit = $match[2]; + $cobject = $scm->getCommit($commit, true); + if (!$cobject) { + throw new Exception('could not retrieve commit object for '. $commit); + } + $rep = new Pluf_HTTP_Response($cobject->diff, 'text/plain'); + $rep->headers['Content-Disposition'] = 'attachment; filename="'.$commit.'.diff"'; + return $rep; + } + + /** + * Should only be called through self::tree + */ + public function viewFile($request, $match, $extra) + { + $title = sprintf(__('%1$s %2$s Source Tree'), (string) $request->project, + $this->getScmType($request)); + $scm = IDF_Scm::get($request->project); + $branches = $extra['branches']; + $tags = $extra['tags']; + $commit = $extra['commit']; + $request_file = $extra['request_file']; + $request_file_info = $extra['request_file_info']; + $bc = self::makeBreadCrumb($request->project, $commit, $request_file_info->fullpath); + $page_title = $bc.' - '.$title; + $cobject = $scm->getCommit($commit); + $in_branches = $scm->inBranches($commit, $request_file); + $in_tags = $scm->inTags($commit, ''); + // try to find the previous level if it exists. + $prev = explode('/', $request_file); + $l = array_pop($prev); + $previous = substr($request_file, 0, -strlen($l.' ')); + $scmConf = $request->conf->getVal('scm', 'git'); + $props = $scm->getProperties($commit, $request_file); + $content = IDF_FileUtil::highLight($extra['mime'], $scm->getFile($request_file_info)); + return Pluf_Shortcuts_RenderToResponse('idf/source/'.$scmConf.'/file.html', + array( + 'page_title' => $page_title, + 'title' => $title, + 'breadcrumb' => $bc, + 'file' => $content, + 'commit' => $commit, + 'cobject' => $cobject, + 'fullpath' => $request_file, + 'efullpath' => IDF_Scm::smartEncode($request_file), + 'base' => $request_file_info->file, + 'prev' => $previous, + 'tree_in' => $in_branches, + 'branches' => $branches, + 'tags' => $tags, + 'tags_in' => $in_tags, + 'props' => $props, + ), + $request); + } + + /** + * Get a given file at a given commit. + * + */ + public $getFile_precond = array('IDF_Precondition::accessSource', + 'IDF_Views_Source_Precondition::scmAvailable', + 'IDF_Views_Source_Precondition::revisionValid'); + public function getFile($request, $match) + { + $scm = IDF_Scm::get($request->project); + $commit = $match[2]; + $request_file = $match[3]; + $request_file_info = $scm->getPathInfo($request_file, $commit); + if (!$request_file_info or $request_file_info->type == 'tree') { + // Redirect to the first branch + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::treeBase', + array($request->project->shortname, + $scm->getMainBranch())); + return new Pluf_HTTP_Response_Redirect($url); + } + $info = self::getRequestedFileMimeType($request_file_info, + $commit, $scm); + $rep = new Pluf_HTTP_Response($scm->getFile($request_file_info), + $info[0]); + $rep->headers['Content-Disposition'] = 'attachment; filename="'.$info[1].'"'; + return $rep; + } + + /** + * Get a zip archive of the current commit. + * + */ + public $download_precond = array('IDF_Precondition::accessSource', + 'IDF_Views_Source_Precondition::scmAvailable', + 'IDF_Views_Source_Precondition::revisionValid'); + public function download($request, $match) + { + $commit = trim($match[2]); + $scm = IDF_Scm::get($request->project); + $base = $request->project->shortname.'-'.$commit; + $rep = $scm->getArchiveStream($commit, $base.'/'); + $rep->headers['Content-Transfer-Encoding'] = 'binary'; + $rep->headers['Content-Disposition'] = 'attachment; filename="'.$base.'.zip"'; + return $rep; + } + + /** + * Find the mime type of a requested file. + * + * @param stdClass Request file info + * @param string Commit at which we want the file + * @param IDF_Scm SCM object + * @param array Mime type found or 'application/octet-stream', basename, extension + */ + public static function getRequestedFileMimeType($file_info, $commit, $scm) + { + $mime = IDF_FileUtil::getMimeType($file_info->file); + if ('application/octet-stream' != $mime[0]) { + return $mime; + } + return IDF_FileUtil::getMimeTypeFromContent($file_info->file, + $scm->getFile($file_info)); + } + + /** + * Callback function to sort tree entries + */ + public static function treeSort($a, $b) + { + // compare two nodes of the same type + if ($a->type === $b->type) { + if (mb_convert_case($a->file, MB_CASE_LOWER) < + mb_convert_case ($b->file, MB_CASE_LOWER)) { + return -1; + } + return 1; + } + + // compare two nodes of different types, directories ("tree") + // should come before files ("blob") + if ($a->type > $b->type) { + return -1; + } + return 1; + } + + /** + * Get the scm type for page title + * + * @return String + */ + private function getScmType($request) + { + return mb_convert_case($request->conf->getVal('scm', 'git'), + MB_CASE_TITLE, 'UTF-8'); + } +} + +function IDF_Views_Source_PrettySize($size) +{ + return Pluf_Template::markSafe(str_replace(' ', ' ', + Pluf_Utils::prettySize($size))); +} + +function IDF_Views_Source_PrettySizeSimple($size) +{ + return Pluf_Utils::prettySize($size); +} + +function IDF_Views_Source_ShortenString($string, $length) +{ + $ellipse = "..."; + $length = max(mb_strlen($ellipse) + 2, $length); + $preflen = ceil($length / 10); + + if (mb_strlen($string) < $length) + return $string; + + return mb_substr($string, 0, $preflen).$ellipse. + mb_substr($string, -($length - $preflen - mb_strlen($ellipse))); +} diff --git a/indefero/src/IDF/Views/Source/Precondition.php b/indefero/src/IDF/Views/Source/Precondition.php new file mode 100644 index 0000000..3dd74c2 --- /dev/null +++ b/indefero/src/IDF/Views/Source/Precondition.php @@ -0,0 +1,74 @@ +project); + if (!$scm->isAvailable()) { + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::help', + array($request->project->shortname)); + return new Pluf_HTTP_Response_Redirect($url); + } + return true; + } + + /** + * Validates the revision given in the URL path and acts accordingly + * + * @param $request + * @return true | Pluf_HTTP_Response_Redirect + * @throws Exception + */ + static public function revisionValid($request) + { + list($url_info, $url_matches) = $request->view; + list(, $project, $commit) = $url_matches; + + $scm = IDF_Scm::get($request->project); + $res = $scm->validateRevision($commit); + switch ($res) { + case IDF_Scm::REVISION_VALID: + return true; + case IDF_Scm::REVISION_INVALID: + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::invalidRevision', + array($request->project->shortname, $commit)); + return new Pluf_HTTP_Response_Redirect($url); + case IDF_Scm::REVISION_AMBIGUOUS: + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::disambiguateRevision', + array($request->project->shortname, + $commit, + $url_info['model'].'::'.$url_info['method'])); + return new Pluf_HTTP_Response_Redirect($url); + default: + throw new Exception('unknown validation result: '. $res); + } + } +} diff --git a/indefero/src/IDF/Views/Source/Svn.php b/indefero/src/IDF/Views/Source/Svn.php new file mode 100644 index 0000000..81eaec3 --- /dev/null +++ b/indefero/src/IDF/Views/Source/Svn.php @@ -0,0 +1,84 @@ +project; + if ($request->conf->getVal('scm', 'git') != 'svn') { + // Redirect to tree base if not svn + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::treeBase', + array($prj->shortname, $prj->getScmRoot())); + return new Pluf_HTTP_Response_Redirect($url); + } + // Get revision value + if (!isset($request->REQUEST['rev']) + or trim($request->REQUEST['rev']) == '') { + $scmRoot = $prj->getScmRoot(); + } else { + $scmRoot = $request->REQUEST['rev']; + } + // Get source if not / + if (isset($request->REQUEST['sourcefile']) + and trim($request->REQUEST['sourcefile']) != '') { + $scmRoot .= '/'.$request->REQUEST['sourcefile']; + } + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::treeBase', + array($prj->shortname, $scmRoot)); + return new Pluf_HTTP_Response_Redirect($url); + } + + /** + * Display SVN changelog from specific revision + * + */ + public function changelogRev($request, $match) + { + $prj = $request->project; + if ($request->conf->getVal('scm', 'git') != 'svn') { + // Redirect to tree base if not svn + $scmRoot = $prj->getScmRoot(); + } else { + // Get revision value if svn + if (!isset($request->REQUEST['rev']) + or trim($request->REQUEST['rev']) == '') { + $scmRoot = $prj->getScmRoot(); + } else { + $scmRoot = $request->REQUEST['rev']; + } + } + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::changeLog', + array($prj->shortname, $scmRoot)); + return new Pluf_HTTP_Response_Redirect($url); + } +} \ No newline at end of file diff --git a/indefero/src/IDF/Views/User.php b/indefero/src/IDF/Views/User.php new file mode 100644 index 0000000..6e5f446 --- /dev/null +++ b/indefero/src/IDF/Views/User.php @@ -0,0 +1,293 @@ +user) as $project) { + $otags = array_merge($otags, $project->getTagIdsByStatus('open')); + } + if (count($otags) == 0) $otags[] = 0; + if ($working) { + $title = __('Your Dashboard - Working Issues'); + $f_sql = new Pluf_SQL('owner=%s AND status IN ('.implode(', ', $otags).')', array($request->user->id)); + } else { + $title = __('Your Dashboard - Submitted Issues'); + $f_sql = new Pluf_SQL('submitter=%s AND status IN ('.implode(', ', $otags).')', array($request->user->id)); + } + + // Get stats about the issues + $sql = new Pluf_SQL('submitter=%s AND status IN ('.implode(', ', $otags).')', array($request->user->id)); + $nb_submit = Pluf::factory('IDF_Issue')->getCount(array('filter'=>$sql->gen())); + $sql = new Pluf_SQL('owner=%s AND status IN ('.implode(', ', $otags).')', array($request->user->id)); + $nb_owner = Pluf::factory('IDF_Issue')->getCount(array('filter'=>$sql->gen())); + // Paginator to paginate the issues + $pag = new Pluf_Paginator(new IDF_Issue()); + $pag->class = 'recent-issues'; + $pag->item_extra_props = array('current_user' => $request->user); + $pag->summary = __('This table shows the open issues.'); + $pag->forced_where = $f_sql; + $pag->action = ($working) ? 'idf_dashboard' : 'idf_dashboard_submit'; + $pag->sort_order = array('modif_dtime', 'ASC'); // will be reverted + $pag->sort_reverse_order = array('modif_dtime'); + $list_display = array( + 'id' => __('Id'), + array('project', 'Pluf_Paginator_FkToString', __('Project')), + array('summary', 'IDF_Views_IssueSummaryAndLabels', __('Summary')), + array('status', 'IDF_Views_Issue_ShowStatus', __('Status')), + array('modif_dtime', 'Pluf_Paginator_DateAgo', __('Last Updated')), + ); + $pag->configure($list_display, array(), array('status', 'modif_dtime')); + $pag->items_per_page = 10; + $pag->no_results_text = ($working) ? __('No issues are assigned to you, yeah!') : __('All the issues you submitted are fixed, yeah!'); + $pag->setFromRequest($request); + return Pluf_Shortcuts_RenderToResponse('idf/user/dashboard.html', + array( + 'page_title' => $title, + 'nb_submit' => $nb_submit, + 'nb_owner' => $nb_owner, + 'issues' => $pag, + ), + $request); + } + + /** + * Simple management of the base info of the user. + */ + public $myAccount_precond = array('Pluf_Precondition::loginRequired'); + public function myAccount($request, $match) + { + // As the password is salted, we can directly take the sha1 of + // the salted password. + $api_key = sha1($request->user->password); + $ext_pass = substr(sha1($request->user->password.Pluf::f('secret_key')), 0, 8); + $params = array('user' => $request->user); + if ($request->method == 'POST') { + $form = new IDF_Form_UserAccount(array_merge( + (array)$request->POST, + (array)$request->FILES + ), $params); + if ($form->isValid()) { + $user = $form->save(); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_User::myAccount'); + $request->session->setData('pluf_language', $user->language); + $request->user->setMessage(__('Your personal information has been updated.')); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $data = $request->user->getData(); + unset($data['password']); + $form = new IDF_Form_UserAccount(null, $params); + } + $keys = $request->user->get_idf_key_list(); + $mailaddrs = Pluf::factory('IDF_EmailAddress')->get_email_addresses_for_user($request->user); + + return Pluf_Shortcuts_RenderToResponse('idf/user/myaccount.html', + array('page_title' => __('Your Account'), + 'api_key' => $api_key, + 'ext_pass' => $ext_pass, + 'keys' => $keys, + 'mailaddrs' => $mailaddrs, + 'form' => $form), + $request); + } + + /** + * Delete a public key. + * + * This is redirecting to the preferences + */ + public $deleteKey_precond = array('Pluf_Precondition::loginRequired'); + public function deleteKey($request, $match) + { + $url = Pluf_HTTP_URL_urlForView('IDF_Views_User::myAccount'); + if ($request->method == 'POST') { + $key = Pluf_Shortcuts_GetObjectOr404('IDF_Key', $match[1]); + if ($key->user != $request->user->id) { + return new Pluf_HTTP_Response_Forbidden($request); + } + $key->delete(); + $request->user->setMessage(__('The public key has been deleted.')); + } + return new Pluf_HTTP_Response_Redirect($url); + } + + /** + * Delete a mail address. + * + * This is redirecting to the preferences + */ + public $deleteMail_precond = array('Pluf_Precondition::loginRequired'); + public function deleteMail($request, $match) + { + $url = Pluf_HTTP_URL_urlForView('IDF_Views_User::myAccount'); + if ($request->method == 'POST') { + $address = Pluf_Shortcuts_GetObjectOr404('IDF_EmailAddress', $match[1]); + if ($address->user != $request->user->id) { + return new Pluf_HTTP_Response_Forbidden($request); + } + $address->delete(); + $request->user->setMessage(__('The address has been deleted.')); + } + return new Pluf_HTTP_Response_Redirect($url); + } + + /** + * Enter the key to change an email address. + * + * This is redirecting to changeEmailDo + */ + public $changeEmailInputKey_precond = array('Pluf_Precondition::loginRequired'); + public function changeEmailInputKey($request, $match) + { + if ($request->method == 'POST') { + $form = new IDF_Form_UserChangeEmail($request->POST); + if ($form->isValid()) { + $url = $form->save(); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $form = new IDF_Form_UserChangeEmail(); + } + return Pluf_Shortcuts_RenderToResponse('idf/user/changeemail.html', + array('page_title' => __('Confirm The Email Change'), + 'form' => $form), + $request); + + } + + /** + * Really change the email address. + */ + public $changeEmailDo_precond = array('Pluf_Precondition::loginRequired'); + public function changeEmailDo($request, $match) + { + $key = $match[1]; + $url = Pluf_HTTP_URL_urlForView('IDF_Views_User::changeEmailInputKey'); + try { + list($email, $id, $time, $type) = IDF_Form_UserChangeEmail::validateKey($key); + } catch (Pluf_Form_Invalid $e) { + return new Pluf_HTTP_Response_Redirect($url); + } + if ($id != $request->user->id) { + return new Pluf_HTTP_Response_Redirect($url); + } + // Now we have a change link coming from the right user. + if ($type == "primary") { + $request->user->email = $email; + $request->user->update(); + } else { + $mailaddress = new IDF_EmailAddress(); + $mailaddress->user = $request->user; + $mailaddress->address = $email; + $mailaddress->create(); + } + $request->user->setMessage(sprintf(__('Your new email address "%s" has been validated. Thank you!'), Pluf_esc($email))); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_User::myAccount'); + return new Pluf_HTTP_Response_Redirect($url); + } + + + /** + * Public profile of a user. + */ + public function view($request, $match) + { + $sql = new Pluf_SQL('login=%s', array($match[1])); + $users = Pluf::factory('Pluf_User')->getList(array('filter'=>$sql->gen())); + if (count($users) != 1 or !$users[0]->active) { + throw new Pluf_HTTP_Error404(); + } + + $user = $users[0]; + $user_data = IDF_UserData::factory($user); + //$projects = $request->user->getAllPermissions(); + //print_r($request->user->permissions); + //print_r($projects[0]); + //$projects = array(); + //foreach (IDF_Views::getProjects($request->user) as $project) { + // $projects[] = $project; + //} + $projects = IDF_Views::getProjects($request->user); + //print_r($projects); + return Pluf_Shortcuts_RenderToResponse('idf/user/public.html', + array('page_title' => (string) $user, + 'member' => $user, + 'user_data' => $user_data, + 'projects' => $projects + ), + $request); + } + +} + +/** + * Display the summary of an issue, then on a new line, display the + * list of labels with a link to a view "by label only". + * + * The summary of the issue is linking to the issue. + */ +function IDF_Views_IssueSummaryAndLabels($field, $issue, $extra='') +{ + $project = $issue->get_project(); + $edit = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view', + array($project->shortname, $issue->id)); + $tags = array(); + foreach ($issue->get_tags_list() as $tag) { + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::listLabel', + array($project->shortname, $tag->id, 'open')); + $tags[] = sprintf('%s', $url, Pluf_esc((string) $tag)); + } + $out = ''; + if (count($tags)) { + $out = '
'.implode(', ', $tags).''; + } + return sprintf('%s', $edit, Pluf_esc($issue->summary)).$out; +} diff --git a/indefero/src/IDF/Views/Wiki.php b/indefero/src/IDF/Views/Wiki.php new file mode 100644 index 0000000..8b6d7df --- /dev/null +++ b/indefero/src/IDF/Views/Wiki.php @@ -0,0 +1,725 @@ +project; + $title = sprintf(__('%s Documentation'), (string) $prj); + // Paginator to paginate the pages + $pag = new Pluf_Paginator(new IDF_Wiki_Page()); + $pag->class = 'recent-issues'; + $pag->item_extra_props = array('project_m' => $prj, + 'shortname' => $prj->shortname, + 'current_user' => $request->user); + $pag->summary = __('This table shows the documentation pages.'); + $pag->action = array('IDF_Views_Wiki::listPages', array($prj->shortname)); + $pag->edit_action = array('IDF_Views_Wiki::viewPage', 'shortname', 'title'); + $sql = 'project=%s'; + $ptags = self::getWikiTags($prj); + $dtag = array_pop($ptags); // The last tag is the deprecated tag. + $ids = self::getDeprecatedPagesIds($prj, $dtag); + if (count($ids)) { + $sql .= ' AND id NOT IN ('.implode(',', $ids).')'; + } + $pag->forced_where = new Pluf_SQL($sql, array($prj->id)); + $pag->extra_classes = array('right', '', 'a-c'); + $list_display = array( + 'title' => __('Page Title'), + array('summary', 'IDF_Views_Wiki_SummaryAndLabels', __('Summary')), + array('modif_dtime', 'Pluf_Paginator_DateYMD', __('Updated')), + ); + $pag->configure($list_display, array(), array('title', 'modif_dtime')); + $pag->items_per_page = 25; + $pag->no_results_text = __('No documentation pages were found.'); + $pag->sort_order = array('title', 'ASC'); + $pag->setFromRequest($request); + return Pluf_Shortcuts_RenderToResponse('idf/wiki/listPages.html', + array( + 'page_title' => $title, + 'pages' => $pag, + 'deprecated' => count($ids), + 'dlabel' => $dtag, + ), + $request); + } + + /** + * View list of resources for a given project. + */ + public $listResources_precond = array('IDF_Precondition::accessWiki', + 'Pluf_Precondition::loginRequired'); + public function listResources($request, $match) + { + $prj = $request->project; + $title = sprintf(__('%s Documentation Resources'), (string) $prj); + $pag = new Pluf_Paginator(new IDF_Wiki_Resource()); + $pag->class = 'recent-issues'; + $pag->item_extra_props = array('project_m' => $prj, + 'shortname' => $prj->shortname, + 'current_user' => $request->user); + $pag->summary = __('This table shows the resources that can be used on documentation pages.'); + $pag->action = array('IDF_Views_Wiki::listResources', array($prj->shortname)); + $pag->edit_action = array('IDF_Views_Wiki::viewResource', 'shortname', 'title'); + $pag->forced_where = new Pluf_SQL('project=%s', array($prj->id)); + $pag->extra_classes = array('right', 'a-c', 'left', 'a-c'); + $list_display = array( + 'title' => __('Resource Title'), + 'mime_type' => __('MIME type'), + 'summary' => __('Description'), + array('modif_dtime', 'Pluf_Paginator_DateYMD', __('Updated')), + ); + $pag->configure($list_display, array(), array('title', 'modif_dtime')); + $pag->items_per_page = 25; + $pag->no_results_text = __('No resources were found.'); + $pag->sort_order = array('title', 'ASC'); + $pag->setFromRequest($request); + return Pluf_Shortcuts_RenderToResponse('idf/wiki/listResources.html', + array( + 'page_title' => $title, + 'resources' => $pag, + ), + $request); + } + + public $search_precond = array('IDF_Precondition::accessWiki',); + public function search($request, $match) + { + $prj = $request->project; + if (!isset($request->REQUEST['q']) or trim($request->REQUEST['q']) == '') { + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::listPages', + array($prj->shortname)); + return new Pluf_HTTP_Response_Redirect($url); + } + $q = $request->REQUEST['q']; + $title = sprintf(__('Documentation Search - %s'), $q); + $pages = new Pluf_Search_ResultSet(IDF_Search::mySearch($q, $prj, 'IDF_Wiki_Page')); + if (count($pages) > 100) { + $pages->results = array_slice($pages->results, 0, 100); + } + $pag = new Pluf_Paginator(); + $pag->items = $pages; + $pag->class = 'recent-issues'; + $pag->item_extra_props = array('project_m' => $prj, + 'shortname' => $prj->shortname, + 'current_user' => $request->user); + $pag->summary = __('This table shows the pages found.'); + $pag->action = array('IDF_Views_Wiki::search', array($prj->shortname), array('q'=> $q)); + $pag->edit_action = array('IDF_Views_Wiki::viewPage', 'shortname', 'title'); + $pag->extra_classes = array('right', '', 'a-c'); + $list_display = array( + 'title' => __('Page Title'), + array('summary', 'IDF_Views_Wiki_SummaryAndLabels', __('Summary')), + array('modif_dtime', 'Pluf_Paginator_DateYMD', __('Updated')), + ); + $pag->configure($list_display); + $pag->items_per_page = 100; + $pag->no_results_text = __('No pages were found.'); + $pag->setFromRequest($request); + $params = array('page_title' => $title, + 'pages' => $pag, + 'q' => $q, + ); + return Pluf_Shortcuts_RenderToResponse('idf/wiki/search.html', $params, $request); + + } + + /** + * View list of pages with a given label. + */ + public $listPagesWithLabel_precond = array('IDF_Precondition::accessWiki'); + public function listPagesWithLabel($request, $match) + { + $prj = $request->project; + $tag = Pluf_Shortcuts_GetObjectOr404('IDF_Tag', $match[2]); + $prj->inOr404($tag); + $title = sprintf(__('%1$s Documentation Pages with Label %2$s'), (string) $prj, + (string) $tag); + // Paginator to paginate the pages + $ptags = self::getWikiTags($prj); + $dtag = array_pop($ptags); // The last tag is the deprecated tag. + $pag = new Pluf_Paginator(new IDF_Wiki_Page()); + $pag->model_view = 'join_tags'; + $pag->class = 'recent-issues'; + $pag->item_extra_props = array('project_m' => $prj, + 'shortname' => $prj->shortname); + $pag->summary = sprintf(__('This table shows the documentation pages with label %s.'), (string) $tag); + $pag->forced_where = new Pluf_SQL('project=%s AND idf_tag_id=%s', array($prj->id, $tag->id)); + $pag->action = array('IDF_Views_Wiki::listPagesWithLabel', array($prj->shortname, $tag->id)); + $pag->edit_action = array('IDF_Views_Wiki::viewPage', 'shortname', 'title'); + $pag->extra_classes = array('right', '', 'a-c'); + $list_display = array( + 'title' => __('Page Title'), + array('summary', 'IDF_Views_Wiki_SummaryAndLabels', __('Summary')), + array('modif_dtime', 'Pluf_Paginator_DateYMD', __('Updated')), + ); + $pag->configure($list_display, array(), array('title', 'modif_dtime')); + $pag->items_per_page = 25; + $pag->no_results_text = __('No documentation pages were found.'); + $pag->setFromRequest($request); + return Pluf_Shortcuts_RenderToResponse('idf/wiki/listPages.html', + array( + 'page_title' => $title, + 'label' => $tag, + 'pages' => $pag, + 'dlabel' => $dtag, + ), + $request); + } + + /** + * Create a new documentation page. + */ + public $createPage_precond = array('IDF_Precondition::accessWiki', + 'Pluf_Precondition::loginRequired'); + public function createPage($request, $match) + { + $prj = $request->project; + $title = __('New Page'); + $preview = false; + if ($request->method == 'POST') { + $form = new IDF_Form_WikiPageCreate($request->POST, + array('project' => $prj, + 'user' => $request->user + )); + if ($form->isValid() and !isset($request->POST['preview'])) { + $page = $form->save(); + $urlpage = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::viewPage', + array($prj->shortname, $page->title)); + $request->user->setMessage(sprintf(__('The page %2$s has been created.'), + $urlpage, Pluf_esc($page->title))); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::listPages', + array($prj->shortname)); + return new Pluf_HTTP_Response_Redirect($url); + } elseif (isset($request->POST['preview'])) { + $preview = $request->POST['content']; + } + } else { + $pagename = (isset($request->GET['name'])) ? + $request->GET['name'] : ''; + $form = new IDF_Form_WikiPageCreate(null, + array('name' => $pagename, + 'project' => $prj, + 'user' => $request->user)); + } + return Pluf_Shortcuts_RenderToResponse('idf/wiki/createPage.html', + array( + 'auto_labels' => self::autoCompleteArrays($prj), + 'page_title' => $title, + 'form' => $form, + 'preview' => $preview, + ), + $request); + } + + /** + * Create a new resource. + */ + public $createResource_precond = array('IDF_Precondition::accessWiki', + 'Pluf_Precondition::loginRequired'); + public function createResource($request, $match) + { + $prj = $request->project; + $title = __('New Resource'); + $preview = false; + if ($request->method == 'POST') { + $form = new IDF_Form_WikiResourceCreate(array_merge($request->POST, $request->FILES), + array('project' => $prj, 'user' => $request->user)); + if ($form->isValid()) { + $resource = $form->save(); + $urlresource = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::viewResource', + array($prj->shortname, $resource->title)); + $request->user->setMessage(sprintf(__('The resource %2$s has been created.'), $urlresource, Pluf_esc($resource->title))); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::listResources', + array($prj->shortname)); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $resourcename = (isset($request->GET['name'])) ? + $request->GET['name'] : ''; + $form = new IDF_Form_WikiResourceCreate(null, + array('name' => $resourcename, + 'project' => $prj, 'user' => $request->user)); + } + return Pluf_Shortcuts_RenderToResponse('idf/wiki/createResource.html', + array( + 'page_title' => $title, + 'form' => $form, + ), + $request); + } + + /** + * View a documentation page. + */ + public $viewPage_precond = array('IDF_Precondition::accessWiki'); + public function viewPage($request, $match) + { + $prj = $request->project; + // Find the page + $sql = new Pluf_SQL('project=%s AND title=%s', + array($prj->id, $match[2])); + $pages = Pluf::factory('IDF_Wiki_Page')->getList(array('filter'=>$sql->gen())); + if ($pages->count() != 1) { + return new Pluf_HTTP_Response_NotFound($request); + } + $page = $pages[0]; + $revision = $page->get_current_revision(); + + // We grab the old revision if requested. + if (isset($request->GET['rev']) and preg_match('/^[0-9]+$/', $request->GET['rev'])) { + $revision = Pluf_Shortcuts_GetObjectOr404('IDF_Wiki_PageRevision', + $request->GET['rev']); + if ($revision->wikipage != $page->id) { + return new Pluf_HTTP_Response_NotFound($request); + } + } + $ptags = self::getWikiTags($prj); + $dtag = array_pop($ptags); // The last tag is the deprecated tag. + $tags = $page->get_tags_list(); + $dep = Pluf_Model_InArray($dtag, $tags); + $title = $page->title; + $false = Pluf_DB_BooleanToDb(false, $page->getDbConnection()); + $revs = $page->get_revisions_list(array('order' => 'creation_dtime DESC', + 'filter' => 'is_head='.$false)); + return Pluf_Shortcuts_RenderToResponse('idf/wiki/viewPage.html', + array( + 'page_title' => $title, + 'page' => $page, + 'rev' => $revision, + 'revs' => $revs, + 'tags' => $tags, + 'deprecated' => $dep, + ), + $request); + } + + /** + * View a documentation resource. + */ + public $viewResource_precond = array('IDF_Precondition::accessWiki'); + public function viewResource($request, $match) + { + $prj = $request->project; + $sql = new Pluf_SQL('project=%s AND title=%s', + array($prj->id, $match[2])); + $resources = Pluf::factory('IDF_Wiki_Resource')->getList(array('filter'=>$sql->gen())); + if ($resources->count() != 1) { + return new Pluf_HTTP_Response_NotFound($request); + } + $resource = $resources[0]; + $revision = $resource->get_current_revision(); + + // grab the old revision if requested. + if (isset($request->GET['rev']) and preg_match('/^[0-9]+$/', $request->GET['rev'])) { + $revision = Pluf_Shortcuts_GetObjectOr404('IDF_Wiki_ResourceRevision', + $request->GET['rev']); + if ($revision->wikiresource != $resource->id) { + return new Pluf_HTTP_Response_NotFound($request); + } + } + $pagerevs = $revision->getPageRevisions(); + $title = $resource->title; + $false = Pluf_DB_BooleanToDb(false, $resource->getDbConnection()); + $revs = $resource->get_revisions_list(array('order' => 'creation_dtime DESC', + 'filter' => 'is_head='.$false)); + return Pluf_Shortcuts_RenderToResponse('idf/wiki/viewResource.html', + array( + 'page_title' => $title, + 'resource' => $resource, + 'rev' => $revision, + 'revs' => $revs, + 'pagerevs' => $pagerevs, + ), + $request); + } + + + /** + * Returns a bytestream to the given raw resource revision + */ + public $rawResource_precond = array('IDF_Precondition::accessWiki'); + public function rawResource($request, $match) + { + $prj = $request->project; + $rev = Pluf_Shortcuts_GetObjectOr404('IDF_Wiki_ResourceRevision', + $match[2]); + $res = $rev->get_wikiresource(); + if ($res->get_project()->id != $prj->id) { + return new Pluf_HTTP_Response_NotFound($request); + } + + $response = new Pluf_HTTP_Response_File($rev->getFilePath(), $res->mime_type); + if (isset($request->GET['attachment']) && $request->GET['attachment']) { + $response->headers['Content-Disposition'] = + 'attachment; filename="'.$res->title.'.'.$rev->fileext.'"'; + } + return $response; + } + + /** + * Remove a revision of a page. + */ + public $deletePageRev_precond = array('IDF_Precondition::accessWiki', + 'IDF_Precondition::projectMemberOrOwner'); + public function deletePageRev($request, $match) + { + $prj = $request->project; + $oldrev = Pluf_Shortcuts_GetObjectOr404('IDF_Wiki_PageRevision', $match[2]); + $page = $oldrev->get_wikipage(); + $prj->inOr404($page); + if ($oldrev->is_head == true) { + return new Pluf_HTTP_Response_NotFound($request); + } + if ($request->method == 'POST') { + $oldrev->delete(); + $request->user->setMessage(__('The old revision has been deleted.')); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::viewPage', + array($prj->shortname, $page->title)); + return new Pluf_HTTP_Response_Redirect($url); + } + + $title = sprintf(__('Delete Old Revision of %s'), $page->title); + $revision = $page->get_current_revision(); + $false = Pluf_DB_BooleanToDb(false, $page->getDbConnection()); + $revs = $page->get_revisions_list(array('order' => 'creation_dtime DESC', + 'filter' => 'is_head='.$false)); + return Pluf_Shortcuts_RenderToResponse('idf/wiki/deletePageRev.html', + array( + 'page_title' => $title, + 'page' => $page, + 'oldrev' => $oldrev, + 'rev' => $revision, + 'revs' => $revs, + 'tags' => $page->get_tags_list(), + ), + $request); + } + + /** + * Remove a revision of a resource. + */ + public $deleteResourceRev_precond = array('IDF_Precondition::accessWiki', + 'IDF_Precondition::projectMemberOrOwner'); + public function deleteResourceRev($request, $match) + { + $prj = $request->project; + $oldrev = Pluf_Shortcuts_GetObjectOr404('IDF_Wiki_ResourceRevision', $match[2]); + $resource = $oldrev->get_wikiresource(); + $prj->inOr404($resource); + if ($oldrev->is_head == true) { + return new Pluf_HTTP_Response_NotFound($request); + } + if ($request->method == 'POST') { + $oldrev->delete(); + $request->user->setMessage(__('The old revision has been deleted.')); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::viewResource', + array($prj->shortname, $resource->title)); + return new Pluf_HTTP_Response_Redirect($url); + } + + $title = sprintf(__('Delete Old Revision of %s'), $resource->title); + $false = Pluf_DB_BooleanToDb(false, $resource->getDbConnection()); + $revs = $resource->get_revisions_list(array('order' => 'creation_dtime DESC', + 'filter' => 'is_head='.$false)); + return Pluf_Shortcuts_RenderToResponse('idf/wiki/deleteResourceRev.html', + array( + 'page_title' => $title, + 'resource' => $resource, + 'oldrev' => $oldrev, + 'revs' => $revs, + ), + $request); + } + + /** + * Update a documentation page. + */ + public $updatePage_precond = array('IDF_Precondition::accessWiki', + 'Pluf_Precondition::loginRequired'); + public function updatePage($request, $match) + { + $prj = $request->project; + // Find the page + $sql = new Pluf_SQL('project=%s AND title=%s', + array($prj->id, $match[2])); + $pages = Pluf::factory('IDF_Wiki_Page')->getList(array('filter'=>$sql->gen())); + if ($pages->count() != 1) { + return new Pluf_HTTP_Response_NotFound($request); + } + $page = $pages[0]; + $title = sprintf(__('Update %s'), $page->title); + $revision = $page->get_current_revision(); + $preview = false; + $params = array('project' => $prj, + 'user' => $request->user, + 'page' => $page); + if ($request->method == 'POST') { + $form = new IDF_Form_WikiPageUpdate($request->POST, $params); + if ($form->isValid() and !isset($request->POST['preview'])) { + $page = $form->save(); + $urlpage = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::viewPage', + array($prj->shortname, $page->title)); + $request->user->setMessage(sprintf(__('The page %2$s has been updated.'), + $urlpage, Pluf_esc($page->title))); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::listPages', + array($prj->shortname)); + return new Pluf_HTTP_Response_Redirect($url); + } elseif (isset($request->POST['preview'])) { + $preview = $request->POST['content']; + } + } else { + + $form = new IDF_Form_WikiPageUpdate(null, $params); + } + return Pluf_Shortcuts_RenderToResponse('idf/wiki/updatePage.html', + array( + 'auto_labels' => self::autoCompleteArrays($prj), + 'page_title' => $title, + 'page' => $page, + 'rev' => $revision, + 'form' => $form, + 'preview' => $preview, + ), + $request); + } + + /** + * Update a documentation resource. + */ + public $updateResource_precond = array('IDF_Precondition::accessWiki', + 'Pluf_Precondition::loginRequired'); + public function updateResource($request, $match) + { + $prj = $request->project; + // Find the page + $sql = new Pluf_SQL('project=%s AND title=%s', + array($prj->id, $match[2])); + $resources = Pluf::factory('IDF_Wiki_Resource')->getList(array('filter'=>$sql->gen())); + if ($resources->count() != 1) { + return new Pluf_HTTP_Response_NotFound($request); + } + $resource = $resources[0]; + $title = sprintf(__('Update %s'), $resource->title); + $revision = $resource->get_current_revision(); + $params = array('project' => $prj, + 'user' => $request->user, + 'resource' => $resource); + if ($request->method == 'POST') { + $form = new IDF_Form_WikiResourceUpdate(array_merge($request->POST, $request->FILES), + $params); + if ($form->isValid()) { + $page = $form->save(); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::viewResource', + array($prj->shortname, $resource->title)); + $request->user->setMessage(sprintf(__('The resource %2$s has been updated.'), + $url, Pluf_esc($resource->title))); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::listResources', + array($prj->shortname)); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $form = new IDF_Form_WikiResourceUpdate(null, $params); + } + + return Pluf_Shortcuts_RenderToResponse('idf/wiki/updateResource.html', + array( + 'page_title' => $title, + 'resource' => $resource, + 'rev' => $revision, + 'form' => $form, + ), + $request); + } + + /** + * Delete a Wiki page. + */ + public $deletePage_precond = array('IDF_Precondition::accessWiki', + 'IDF_Precondition::projectMemberOrOwner'); + public function deletePage($request, $match) + { + $prj = $request->project; + $page = Pluf_Shortcuts_GetObjectOr404('IDF_Wiki_Page', $match[2]); + $prj->inOr404($page); + $params = array('page' => $page); + if ($request->method == 'POST') { + $form = new IDF_Form_WikiPageDelete($request->POST, $params); + if ($form->isValid()) { + $form->save(); + $request->user->setMessage(__('The documentation page has been deleted.')); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::listPages', + array($prj->shortname)); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $form = new IDF_Form_WikiPageDelete(null, $params); + } + $title = sprintf(__('Delete Page %s'), $page->title); + $revision = $page->get_current_revision(); + $false = Pluf_DB_BooleanToDb(false, $page->getDbConnection()); + $revs = $page->get_revisions_list(array('order' => 'creation_dtime DESC', + 'filter' => 'is_head='.$false)); + return Pluf_Shortcuts_RenderToResponse('idf/wiki/deletePage.html', + array( + 'page_title' => $title, + 'page' => $page, + 'form' => $form, + 'rev' => $revision, + 'revs' => $revs, + 'tags' => $page->get_tags_list(), + ), + $request); + } + + /** + * Delete a Wiki resource. + */ + public $deleteResource_precond = array('IDF_Precondition::accessWiki', + 'IDF_Precondition::projectMemberOrOwner'); + public function deleteResource($request, $match) + { + $prj = $request->project; + $resource = Pluf_Shortcuts_GetObjectOr404('IDF_Wiki_Resource', $match[2]); + $prj->inOr404($resource); + $params = array('resource' => $resource); + if ($request->method == 'POST') { + $form = new IDF_Form_WikiResourceDelete($request->POST, $params); + if ($form->isValid()) { + $form->save(); + $request->user->setMessage(__('The documentation resource has been deleted.')); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::listResources', + array($prj->shortname)); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $form = new IDF_Form_WikiResourceDelete(null, $params); + } + $title = sprintf(__('Delete Resource %s'), $resource->title); + $revision = $resource->get_current_revision(); + $false = Pluf_DB_BooleanToDb(false, $resource->getDbConnection()); + $revs = $resource->get_revisions_list(array('order' => 'creation_dtime DESC', + 'filter' => 'is_head='.$false)); + return Pluf_Shortcuts_RenderToResponse('idf/wiki/deleteResource.html', + array( + 'page_title' => $title, + 'resource' => $resource, + 'form' => $form, + 'rev' => $revision, + 'revs' => $revs, + ), + $request); + } + + /** + * Get the wiki tags. + * + * @param IDF_Project + * @return ArrayObject The tags + */ + public static function getWikiTags($project) + { + return $project->getTagsFromConfig('labels_wiki_predefined', + IDF_Form_WikiConf::init_predefined); + + } + + /** + * Get deprecated page ids. + * + * @param IDF_Project + * @param IDF_Tag Deprecated tag (null) + * @return array Ids of the deprecated pages. + */ + public static function getDeprecatedPagesIds($project, $dtag=null) + { + if (is_null($dtag)) { + $ptags = self::getWikiTags($project); + $dtag = array_pop($ptags); // The last tag is the deprecated tag + } + $sql = new Pluf_SQL('project=%s AND idf_tag_id=%s', array($project->id, + $dtag->id)); + $ids = array(); + foreach (Pluf::factory('IDF_Wiki_Page')->getList(array('filter' => $sql->gen(), 'view' => 'join_tags')) + as $file) { + $ids[] = (int) $file->id; + } + return $ids; + } + + /** + * Create the autocomplete arrays for the little AJAX stuff. + */ + public static function autoCompleteArrays($project) + { + $conf = new IDF_Conf(); + $conf->setProject($project); + $st = preg_split("/\015\012|\015|\012/", + $conf->getVal('labels_wiki_predefined', IDF_Form_WikiConf::init_predefined), -1, PREG_SPLIT_NO_EMPTY); + $auto = ''; + foreach ($st as $s) { + $v = ''; + $d = ''; + $_s = explode('=', $s, 2); + if (count($_s) > 1) { + $v = trim($_s[0]); + $d = trim($_s[1]); + } else { + $v = trim($_s[0]); + } + $auto .= sprintf('{ name: "%s", to: "%s" }, ', + Pluf_esc($d), Pluf_esc($v)); + } + return substr($auto, 0, -2); + } +} + +/** + * Display the summary of a page, then on a new line, display the + * list of labels. + */ +function IDF_Views_Wiki_SummaryAndLabels($field, $page, $extra='') +{ + $tags = array(); + foreach ($page->get_tags_list() as $tag) { + $tags[] = Pluf_esc((string) $tag); + } + $out = ''; + if (count($tags)) { + $out = '
'.implode(', ', $tags).''; + } + return Pluf_esc($page->summary).$out; +} diff --git a/indefero/src/IDF/Webhook.php b/indefero/src/IDF/Webhook.php new file mode 100644 index 0000000..9d33d09 --- /dev/null +++ b/indefero/src/IDF/Webhook.php @@ -0,0 +1,110 @@ + array( + // fall-back to POST for old queue items + 'method' => empty($payload['method']) ? 'POST' : $payload['method'], + 'content' => $data, + 'user_agent' => 'Indefero Hook Sender (http://www.indefero.net)', + 'max_redirects' => 0, + 'timeout' => 15, + 'header'=> $sign_header.': '.$sign."\r\n" + .'Content-Type: application/json'."\r\n", + ) + ); + $url = $payload['url']; + $ctx = stream_context_create($params); + $fp = @fopen($url, 'rb', false, $ctx); + if (!$fp) { + return false; + } + $meta = stream_get_meta_data($fp); + @fclose($fp); + if (!isset($meta['wrapper_data'][0]) or $meta['timed_out']) { + return false; + } + if (0 === strpos($meta['wrapper_data'][0], 'HTTP/1.1 2') or + 0 === strpos($meta['wrapper_data'][0], 'HTTP/1.1 3')) { + return true; + } + return false; + } + + + /** + * Process the webhook. + * + */ + public static function process($sender, &$params) + { + $item = $params['item']; + if (!in_array($item->type, array('new_commit', 'upload'))) { + // We do nothing. + return; + } + if (isset($params['res']['IDF_Webhook::process']) and + $params['res']['IDF_Webhook::process'] == true) { + // Already processed. + return; + } + if ($item->payload['url'] == '') { + // We do nothing. + return; + } + // We have either to retry or to push for the first time. + $res = self::processNotification($item->payload); + if ($res) { + $params['res']['IDF_Webhook::process'] = true; + } elseif ($item->trials >= 9) { + // We are at trial 10, give up + $params['res']['IDF_Webhook::process'] = true; + } else { + // Need to try again + $params['res']['IDF_Webhook::process'] = false; + } + } +} diff --git a/indefero/src/IDF/Wiki/Page.php b/indefero/src/IDF/Wiki/Page.php new file mode 100644 index 0000000..0c4a35c --- /dev/null +++ b/indefero/src/IDF/Wiki/Page.php @@ -0,0 +1,224 @@ +_a['table'] = 'idf_wikipages'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + 'blank' => true, + ), + 'project' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_Project', + 'blank' => false, + 'verbose' => __('project'), + 'relate_name' => 'wikipages', + ), + 'title' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 250, + 'verbose' => __('title'), + 'help_text' => __('The title of the page must only contain letters, digits or the dash character. For example: My-new-Wiki-Page.'), + ), + 'summary' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 250, + 'verbose' => __('summary'), + 'help_text' => __('A one line description of the page content.'), + ), + 'submitter' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'Pluf_User', + 'blank' => false, + 'verbose' => __('submitter'), + 'relate_name' => 'submitted_wikipages', + ), + 'interested' => + array( + 'type' => 'Pluf_DB_Field_Manytomany', + 'model' => 'Pluf_User', + 'blank' => true, + 'verbose' => __('interested users'), + 'help_text' => 'Interested users will get an email notification when the wiki page is changed.', + ), + 'tags' => + array( + 'type' => 'Pluf_DB_Field_Manytomany', + 'blank' => true, + 'model' => 'IDF_Tag', + 'verbose' => __('labels'), + ), + 'creation_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('creation date'), + ), + 'modif_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('modification date'), + ), + ); + $this->_a['idx'] = array( + 'modif_dtime_idx' => + array( + 'col' => 'modif_dtime', + 'type' => 'normal', + ), + ); + $table = $this->_con->pfx.'idf_tag_idf_wiki_page_assoc'; + $this->_a['views'] = array( + 'join_tags' => + array( + 'join' => 'LEFT JOIN '.$table + .' ON idf_wiki_page_id=id', + ), + ); + } + + function __toString() + { + return $this->title.' - '.$this->summary; + } + + function _toIndex() + { + $rev = $this->get_current_revision()->_toIndex(); + $str = str_repeat($this->title.' '.$this->summary.' ', 4).' '.$rev; + return Pluf_Text::cleanString(html_entity_decode($str, ENT_QUOTES, 'UTF-8')); + } + + /** + * We drop the information from the timeline. + */ + function preDelete() + { + IDF_Timeline::remove($this); + IDF_Search::remove($this); + } + + function get_current_revision() + { + $true = Pluf_DB_BooleanToDb(true, $this->getDbConnection()); + $rev = $this->get_revisions_list(array('filter' => 'is_head='.$true, + 'nb' => 1)); + return ($rev->count() == 1) ? $rev[0] : null; + } + + function preSave($create=false) + { + if ($this->id == '') { + $this->creation_dtime = gmdate('Y-m-d H:i:s'); + } + $this->modif_dtime = gmdate('Y-m-d H:i:s'); + } + + function postSave($create=false) + { + // Note: No indexing is performed here. The indexing is + // triggered in the postSave step of the revision to ensure + // that the page as a given revision in the database when + // doing the indexing. + if ($create) { + IDF_Timeline::insert($this, $this->get_project(), + $this->get_submitter()); + } + } + + /** + * Returns an HTML fragment used to display this wikipage in the + * timeline. + * + * The request object is given to be able to check the rights and + * as such create links to other items etc. You can consider that + * if displayed, you can create a link to it. + * + * @param Pluf_HTTP_Request + * @return Pluf_Template_SafeString + */ + public function timelineFragment($request) + { + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::viewPage', + array($request->project->shortname, + $this->title)); + $out = ''. + Pluf_esc(Pluf_Template_dateAgo($this->creation_dtime, 'without')). + ''; + $stag = new IDF_Template_ShowUser(); + $user = $stag->start($this->get_submitter(), $request, '', false); + $out .= sprintf(__('%2$s, %3$s'), $url, Pluf_esc($this->title), Pluf_esc($this->summary)).''; + $out .= "\n".' +
'.sprintf(__('Creation of page %2$s, by %3$s'), $url, Pluf_esc($this->title), $user).'
'; + return Pluf_Template::markSafe($out); + } + + public function feedFragment($request) + { + $url = Pluf::f('url_base') + .Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::viewPage', + array($request->project->shortname, + $this->title)); + $title = sprintf(__('%1$s: Documentation page %2$s added - %3$s'), + $request->project->name, + $this->title, $this->summary); + $date = Pluf_Date::gmDateToGmString($this->creation_dtime); + $context = new Pluf_Template_Context_Request( + $request, + array('url' => $url, + 'title' => $title, + 'page' => $this, + 'rev' => $this->get_current_revision(), + 'create' => true, + 'date' => $date) + ); + $tmpl = new Pluf_Template('idf/wiki/feedfragment-page.xml'); + return $tmpl->render($context); + } +} diff --git a/indefero/src/IDF/Wiki/PageRevision.php b/indefero/src/IDF/Wiki/PageRevision.php new file mode 100644 index 0000000..40924e7 --- /dev/null +++ b/indefero/src/IDF/Wiki/PageRevision.php @@ -0,0 +1,317 @@ +_a['table'] = 'idf_wikipagerevs'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + 'blank' => true, + ), + 'wikipage' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_Wiki_Page', + 'blank' => false, + 'verbose' => __('page'), + 'relate_name' => 'revisions', + ), + 'is_head' => + array( + 'type' => 'Pluf_DB_Field_Boolean', + 'blank' => false, + 'default' => false, + 'help_text' => 'If this revision is the latest, we mark it as being the head revision.', + 'index' => true, + + ), + 'summary' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 250, + 'verbose' => __('summary'), + 'help_text' => __('A one line description of the changes.'), + ), + 'content' => + array( + 'type' => 'Pluf_DB_Field_Compressed', + 'blank' => false, + 'verbose' => __('content'), + ), + 'submitter' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'Pluf_User', + 'blank' => false, + 'verbose' => __('submitter'), + ), + 'changes' => + array( + 'type' => 'Pluf_DB_Field_Serialized', + 'blank' => true, + 'verbose' => __('changes'), + 'help_text' => 'Serialized array of the changes in the page.', + ), + 'creation_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('creation date'), + ), + ); + $this->_a['idx'] = array( + 'creation_dtime_idx' => + array( + 'col' => 'creation_dtime', + 'type' => 'normal', + ), + ); + $table = $this->_con->pfx.'idf_wiki_pagerevision_idf_wiki_resourcerevision_assoc'; + $this->_a['views'] = array( + 'join_pagerevision' => + array( + 'join' => 'LEFT JOIN '.$table + .' ON idf_wiki_pagerevision_id=id', + ), + ); + } + + function changedRevision() + { + return (is_array($this->changes) and count($this->changes) > 0); + } + + function _toIndex() + { + return $this->content; + } + + /** + * We drop the information from the timeline. + */ + function preDelete() + { + IDF_Timeline::remove($this); + } + + function preSave($create=false) + { + if ($this->id == '') { + $this->creation_dtime = gmdate('Y-m-d H:i:s'); + $this->is_head = true; + } + } + + function postSave($create=false) + { + $page = $this->get_wikipage(); + + if ($create) { + // Check if more than one revision for this page. We do + // not want to insert the first revision in the timeline + // as the page itself is inserted. We do not insert on + // update as update is performed to change the is_head + // flag. + $sql = new Pluf_SQL('wikipage=%s', array($this->wikipage)); + $rev = Pluf::factory('IDF_Wiki_PageRevision')->getList(array('filter'=>$sql->gen())); + if ($rev->count() > 1) { + IDF_Timeline::insert($this, $page->get_project(), $this->get_submitter()); + foreach ($rev as $r) { + if ($r->id != $this->id and $r->is_head) { + $r->is_head = false; + $r->update(); + } + } + } + } + + IDF_Search::index($page); + $page->update(); // Will update the modification timestamp. + + // remember the resource revisions used in this page revision + if ($this->is_head) { + preg_match_all('#\[\[!([A-Za-z0-9\-]+)[^\]]*\]\]#im', $this->content, $matches, PREG_PATTERN_ORDER); + if (count($matches) > 1 && count($matches[1]) > 0) { + foreach ($matches[1] as $resourceName) { + $sql = new Pluf_SQL('project=%s AND title=%s', + array($page->get_project()->id, $resourceName)); + $resources = Pluf::factory('IDF_Wiki_Resource')->getList(array('filter'=>$sql->gen())); + if ($resources->count() == 0) + continue; + + $current_revision = $resources[0]->get_current_revision(); + $current_revision->setAssoc($this); + $this->setAssoc($current_revision); + } + } + } + } + + public function timelineFragment($request) + { + $page = $this->get_wikipage(); + $url = Pluf::f('url_base') + .Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::viewPage', + array($request->project->shortname, + $page->title), + array('rev' => $this->id)); + $out = "\n".''. + Pluf_esc(Pluf_Template_dateAgo($this->creation_dtime, 'without')). + ''; + $stag = new IDF_Template_ShowUser(); + $user = $stag->start($this->get_submitter(), $request, '', false); + $out .= sprintf(__('%2$s, %3$s'), $url, Pluf_esc($page->title), Pluf_esc($this->summary)); + if ($this->changedRevision()) { + $out .= '
'; + $changes = $this->changes; + foreach ($changes as $w => $v) { + $out .= ''; + switch ($w) { + case 'lb': + $out .= __('Labels:'); break; + } + $out .= ' '; + if ($w == 'lb') { + $out .= Pluf_esc(implode(', ', $v)); + } else { + $out .= Pluf_esc($v); + } + $out .= ' '; + } + $out .= '
'; + } + $out .= ''; + $out .= "\n".' +
'.sprintf(__('Change of %2$s, by %3$s'), $url, Pluf_esc($page->title), $user).'
'; + return Pluf_Template::markSafe($out); + } + + public function feedFragment($request) + { + $page = $this->get_wikipage(); + $url = Pluf::f('url_base') + .Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::viewPage', + array($request->project->shortname, + $page->title), + array('rev' => $this->id)); + + $title = sprintf(__('%1$s: Documentation page %2$s updated - %3$s'), + $request->project->name, + $page->title, $page->summary); + $date = Pluf_Date::gmDateToGmString($this->creation_dtime); + $context = new Pluf_Template_Context_Request( + $request, + array('url' => $url, + 'title' => $title, + 'page' => $page, + 'rev' => $this, + 'create' => false, + 'date' => $date) + ); + $tmpl = new Pluf_Template('idf/wiki/feedfragment-page.xml'); + return $tmpl->render($context); + } + + + + /** + * Notification of change of a Wiki Page. + * + * The content of a WikiPage is in the IDF_WikiRevision object, + * this is why we send the notificatin from there. This means that + * when the create flag is set, this is for the creation of a + * wikipage and not, for the addition of a new revision. + * + * Usage: + *
+     * $this->notify($conf); // Notify the creation of a wiki page
+     * $this->notify($conf, false); // Notify the update of the page
+     * 
+ * + * @param IDF_Conf Current configuration + * @param bool Creation (true) + */ + public function notify($conf, $create=true) + { + $wikipage = $this->get_wikipage(); + $project = $wikipage->get_project(); + $current_locale = Pluf_Translation::getLocale(); + + $from_email = Pluf::f('from_email'); + $messageId = '<'.md5('wiki'.$wikipage->id.md5(Pluf::f('secret_key'))).'@'.Pluf::f('mail_host', 'localhost').'>'; + $recipients = $project->getNotificationRecipientsForTab('wiki'); + + foreach ($recipients as $address => $language) { + + if ($this->get_submitter()->email === $address) { + continue; + } + + Pluf_Translation::loadSetLocale($language); + + $context = new Pluf_Template_Context(array( + 'page' => $wikipage, + 'rev' => $this, + 'project' => $project, + 'url_base' => Pluf::f('url_base'), + )); + + $tplfile = 'idf/wiki/wiki-created-email.txt'; + $subject = __('New Documentation Page %1$s - %2$s (%3$s)'); + $headers = array('Message-ID' => $messageId); + if (!$create) { + $tplfile = 'idf/wiki/wiki-updated-email.txt'; + $subject = __('Documentation Page Changed %1$s - %2$s (%3$s)'); + $headers = array('References' => $messageId); + } + + $tmpl = new Pluf_Template($tplfile); + $text_email = $tmpl->render($context); + + $email = new Pluf_Mail($from_email, + $address, + sprintf($subject, + $wikipage->title, + $wikipage->summary, + $project->shortname)); + $email->addTextMessage($text_email); + $email->addHeaders($headers); + $email->sendMail(); + } + + Pluf_Translation::loadSetLocale($current_locale); + } +} diff --git a/indefero/src/IDF/Wiki/Resource.php b/indefero/src/IDF/Wiki/Resource.php new file mode 100644 index 0000000..487cf1a --- /dev/null +++ b/indefero/src/IDF/Wiki/Resource.php @@ -0,0 +1,204 @@ +_a['table'] = 'idf_wikiresources'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + 'blank' => true, + ), + 'project' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_Project', + 'blank' => false, + 'verbose' => __('project'), + 'relate_name' => 'wikipages', + ), + 'title' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 250, + 'verbose' => __('title'), + 'help_text' => __('The title of the resource must only contain letters, digits, dots or the dash character. For example: my-resource.png.'), + ), + 'mime_type' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 100, + 'verbose' => __('MIME media type'), + 'help_text' => __('The MIME media type of the resource.'), + ), + 'summary' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 250, + 'verbose' => __('summary'), + 'help_text' => __('A one line description of the resource.'), + ), + 'submitter' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'Pluf_User', + 'blank' => false, + 'verbose' => __('submitter'), + 'relate_name' => 'submitted_wikipages', + ), + 'creation_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('creation date'), + ), + 'modif_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('modification date'), + ), + ); + $this->_a['idx'] = array( + 'modif_dtime_idx' => + array( + 'col' => 'modif_dtime', + 'type' => 'normal', + ), + ); + } + + function __toString() + { + return $this->title.' - '.$this->summary; + } + + /** + * We drop the information from the timeline. + */ + function preDelete() + { + IDF_Timeline::remove($this); + IDF_Search::remove($this); + } + + function get_current_revision() + { + $true = Pluf_DB_BooleanToDb(true, $this->getDbConnection()); + $rev = $this->get_revisions_list(array('filter' => 'is_head='.$true, + 'nb' => 1)); + return ($rev->count() == 1) ? $rev[0] : null; + } + + function preSave($create=false) + { + if ($this->id == '') { + $this->creation_dtime = gmdate('Y-m-d H:i:s'); + } + $this->modif_dtime = gmdate('Y-m-d H:i:s'); + } + + function postSave($create=false) + { + // Note: No indexing is performed here. The indexing is + // triggered in the postSave step of the revision to ensure + // that the page as a given revision in the database when + // doing the indexing. + if ($create) { + IDF_Timeline::insert($this, $this->get_project(), + $this->get_submitter()); + } + } + + /** + * Returns an HTML fragment used to display this resource in the + * timeline. + * + * The request object is given to be able to check the rights and + * as such create links to other items etc. You can consider that + * if displayed, you can create a link to it. + * + * @param Pluf_HTTP_Request + * @return Pluf_Template_SafeString + */ + public function timelineFragment($request) + { + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::viewResource', + array($request->project->shortname, + $this->title)); + $out = ''. + Pluf_esc(Pluf_Template_dateAgo($this->creation_dtime, 'without')). + ''; + $stag = new IDF_Template_ShowUser(); + $user = $stag->start($this->get_submitter(), $request, '', false); + $out .= sprintf(__('%2$s, %3$s'), $url, Pluf_esc($this->title), Pluf_esc($this->summary)).''; + $out .= "\n".' +
'.sprintf(__('Creation of resource %2$s, by %3$s'), $url, Pluf_esc($this->title), $user).'
'; + return Pluf_Template::markSafe($out); + } + + public function feedFragment($request) + { + $url = Pluf::f('url_base') + .Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::viewResource', + array($request->project->shortname, + $this->title)); + $title = sprintf(__('%1$s: Documentation resource %2$s added - %3$s'), + $request->project->name, + $this->title, $this->summary); + $date = Pluf_Date::gmDateToGmString($this->creation_dtime); + $context = new Pluf_Template_Context_Request( + $request, + array('url' => $url, + 'title' => $title, + 'resource' => $this, + 'rev' => $this->get_current_revision(), + 'create' => true, + 'date' => $date) + ); + $tmpl = new Pluf_Template('idf/wiki/feedfragment-resource.xml'); + return $tmpl->render($context); + } +} diff --git a/indefero/src/IDF/Wiki/ResourceRevision.php b/indefero/src/IDF/Wiki/ResourceRevision.php new file mode 100644 index 0000000..ee1a3ea --- /dev/null +++ b/indefero/src/IDF/Wiki/ResourceRevision.php @@ -0,0 +1,340 @@ +_a['table'] = 'idf_wikiresourcerevs'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + 'blank' => true, + ), + 'wikiresource' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'IDF_Wiki_Resource', + 'blank' => false, + 'verbose' => __('resource'), + 'relate_name' => 'revisions', + ), + 'is_head' => + array( + 'type' => 'Pluf_DB_Field_Boolean', + 'blank' => false, + 'default' => false, + 'help_text' => 'If this revision is the latest, we mark it as being the head revision.', + 'index' => true, + ), + 'summary' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 250, + 'verbose' => __('summary'), + 'help_text' => __('A one line description of the changes.'), + ), + 'filesize' => + array( + 'type' => 'Pluf_DB_Field_Integer', + 'blank' => false, + 'default' => 0, + 'verbose' => __('file size in bytes'), + ), + 'fileext' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 10, + 'verbose' => __('File extension'), + 'help_text' => __('The file extension of the uploaded resource.'), + ), + 'submitter' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'Pluf_User', + 'blank' => false, + 'verbose' => __('submitter'), + 'relate_name' => 'submitted_downloads', + ), + 'pageusage' => + array( + 'type' => 'Pluf_DB_Field_Manytomany', + 'model' => 'IDF_Wiki_PageRevision', + 'blank' => true, + 'verbose' => __('page usage'), + 'help_text' => 'Records on which pages this resource revision is used.', + ), + 'creation_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('creation date'), + ), + ); + $table = $this->_con->pfx.'idf_wiki_pagerevision_idf_wiki_resourcerevision_assoc'; + $this->_a['views'] = array( + 'join_pagerevision' => + array( + 'join' => 'LEFT JOIN '.$table + .' ON idf_wiki_resourcerevision_id=id', + ), + ); + } + + function __toString() + { + return sprintf(__('id %d: %s'), $this->id, $this->summary); + } + + function _toIndex() + { + return ''; + } + + function preDelete() + { + // if we kill off a head revision, ensure that we either mark a previous revision as head + if ($this->is_head) { + $sql = new Pluf_SQL('wikiresource=%s and id!=%s', array($this->wikiresource, $this->id)); + $revs = Pluf::factory('IDF_Wiki_ResourceRevision')->getList(array('filter'=>$sql->gen(), 'order'=>'id DESC')); + if ($revs->count() > 0) { + $previous = $revs[0]; + $previous->is_head = true; + $previous->update(); + } + } + + @unlink($this->getFilePath()); + IDF_Timeline::remove($this); + } + + function preSave($create=false) + { + if ($this->id == '') { + $this->creation_dtime = gmdate('Y-m-d H:i:s'); + $this->is_head = true; + } + } + + function postSave($create=false) + { + $resource = $this->get_wikiresource(); + + if ($create) { + $sql = new Pluf_SQL('wikiresource=%s', array($this->wikiresource)); + $rev = Pluf::factory('IDF_Wiki_ResourceRevision')->getList(array('filter'=>$sql->gen())); + if ($rev->count() > 1) { + IDF_Timeline::insert($this, $resource->get_project(), $this->get_submitter()); + foreach ($rev as $r) { + if ($r->id != $this->id and $r->is_head) { + $r->is_head = false; + $r->update(); + } + } + } + } + + // update the modification timestamp + $resource->update(); + } + + function getFilePath() + { + return sprintf(Pluf::f('upload_path').'/'.$this->get_wikiresource()->get_project()->shortname.'/wiki/res/%d/%d.%s', + $this->get_wikiresource()->id, $this->id, $this->fileext); + } + + function getViewURL() + { + $prj = $this->get_wikiresource()->get_project(); + $resource = $this->get_wikiresource(); + return Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::viewResource', + array($prj->shortname, $resource->title), + array('rev' => $this->id)); + } + + function getRawURL($attachment = false) + { + $query = $attachment ? array('attachment' => 1) : array(); + $prj = $this->get_wikiresource()->get_project(); + return Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::rawResource', + array($prj->shortname, $this->id), + $query); + } + + /** + * Returns the page revisions which contain references to this resource revision + */ + function getPageRevisions() + { + $db =& Pluf::db(); + $sql_results = $db->select( + 'SELECT idf_wiki_pagerevision_id as id '. + 'FROM '.Pluf::f('db_table_prefix', '').'idf_wiki_pagerevision_idf_wiki_resourcerevision_assoc '. + 'WHERE idf_wiki_resourcerevision_id='.$this->id + ); + $ids = array(0); + foreach ($sql_results as $id) { + $ids[] = $id['id']; + } + $ids = implode (',', $ids); + + $sql = new Pluf_SQL('id IN ('.$ids.')'); + return Pluf::factory('IDF_Wiki_PageRevision') + ->getList(array('filter' => $sql->gen())); + } + + /** + * Renders the resource with the given view options, including a link to the resource' detail page + */ + function render($opts = array()) + { + // give some reasonable defaults + $opts = array_merge(array( + 'align' => 'left', + 'width' => '', + 'height' => '', + 'preview' => 'yes', // if possible + 'title' => '', + ), $opts); + + $attrs = array('class="resource-container"'); + $styles = array(); + if (!empty($opts['align'])) { + switch ($opts['align']) { + case 'left': + $styles[] = 'float: left'; + $styles[] = 'margin-right: 10px'; + break; + case 'center': + $styles[] = 'margin: 0 auto 0 auto'; + break; + case 'right': + $styles[] = 'float: right'; + $styles[] = 'margin-left: 10px'; + break; + } + } + if (!empty($opts['width'])) { + $styles[] = 'width:'.$opts['width']; + } + if (!empty($opts['height'])) { + $styles[] = 'height:'.$opts['height']; + } + + $raw = $this->renderRaw(); + $viewUrl = $this->getViewURL(); + $download = ''; + $html = '
'; + if ($opts['preview'] == 'yes' && !empty($raw)) { + $html .= '
'.$raw.'
'."\n"; + } else { + $rawUrl = $this->getRawURL(true); + $download = ''; + } + $resource = $this->get_wikiresource(); + $title = $opts['title']; + if (empty($title)) { + $title = $resource->title.' - '.$resource->mime_type.' - '.Pluf_Utils::prettySize($this->filesize); + } + $html .= '
'.$download.''.$title.'
'."\n"; + $html .= '
'; + return $html; + } + + /** + * Renders a raw version of the resource, without any possibilities of formatting or the like + */ + function renderRaw() + { + $resource = $this->get_wikiresource(); + $url = $this->getRawURL(); + if (preg_match('#^image/(gif|jpeg|png|tiff)$#', $resource->mime_type)) { + return sprintf('%s', $url, $resource->title); + } + + if (preg_match('#^text/(plain|xml|html|sgml|javascript|ecmascript|css)$#', $resource->mime_type)) { + return sprintf('', $url, $resource->title); + } + + return ''; + } + + + public function timelineFragment($request) + { + $resource = $this->get_wikiresource(); + $url = Pluf::f('url_base') + .Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::viewResource', + array($request->project->shortname, + $resource->title), + array('rev' => $this->id)); + + $out = "\n".''. + Pluf_esc(Pluf_Template_dateAgo($this->creation_dtime, 'without')). + ''; + $stag = new IDF_Template_ShowUser(); + $user = $stag->start($this->get_submitter(), $request, '', false); + $out .= sprintf(__('%2$s, %3$s'), $url, Pluf_esc($resource->title), Pluf_esc($this->summary)); + $out .= ''; + $out .= "\n".' +
'.sprintf(__('Change of %2$s, by %3$s'), $url, Pluf_esc($resource->title), $user).'
'; + return Pluf_Template::markSafe($out); + } + + public function feedFragment($request) + { + $resource = $this->get_wikiresource(); + $url = Pluf::f('url_base') + .Pluf_HTTP_URL_urlForView('IDF_Views_Wiki::viewResource', + array($request->project->shortname, + $resource->title), + array('rev' => $this->id)); + + $title = sprintf(__('%1$s: Documentation resource %2$s updated - %3$s'), + $request->project->name, + $resource->title, $resource->summary); + $date = Pluf_Date::gmDateToGmString($this->creation_dtime); + $context = new Pluf_Template_Context_Request( + $request, + array('url' => $url, + 'title' => $title, + 'resource' => $resource, + 'rev' => $this, + 'create' => false, + 'date' => $date) + ); + $tmpl = new Pluf_Template('idf/wiki/feedfragment-resource.xml'); + return $tmpl->render($context); + } +} diff --git a/indefero/src/IDF/conf/idf.php b/indefero/src/IDF/conf/idf.php new file mode 100644 index 0000000..43a0e89 --- /dev/null +++ b/indefero/src/IDF/conf/idf.php @@ -0,0 +1,561 @@ +/dev/null | base64 -w 0 +$cfg['secret_key'] = ''; + +# ---------------------------------------------------------------------------- # +# Debug section # +# ---------------------------------------------------------------------------- # + +# In debug mode Indefero renders stack traces in case of an error that include +# more information about a specific problem. Since these stack traces often +# contain sensible data, this option MUST BE DEACTIVATED in production mode. +# (see $cfg['admins'] below to learn how you can still be notified about +# problems without 'debug' being enabled). +$cfg['debug'] = true; + + +# This is used to help generate the stats at the bottom of the page +# This can also be used to help debug DB issues as it will get passed +# to Pluf_DB_Stats_getConnection as the debug parameter +# If you set this to false then the query stats will not be shown +$cfg['db_debug'] = true; + + +# ---------------------------------------------------------------------------- # +# Path section # +# ---------------------------------------------------------------------------- # + +# Temporary folder where the application is writing compiled templates, +# cached data and other temporary resources to. +# It must be writeable by your webserver instance. +$cfg['tmp_folder'] = '/tmp'; + +# Path to the PEAR folder +$cfg['pear_path'] = '/usr/share/php'; + +# Path to the upload folder +$cfg['upload_path'] = '/home/www/indefero/www/media/upload'; + +# The following path MUST NOT be accessible through a web browser, +# as user will otherwise be able to upload executable files (*.php) and +# this can create TERRIBLE security issues. In this folder, the attachments +# to the issues will be uploaded and we do not restrict the content type. +$cfg['upload_issue_path'] = '/home/www/indefero/attachments'; + +# If your SCM binary is not accessible for the web user (for example, because +# it is not in the system PATH), you can enter the full path to it here. +$cfg['svn_path'] = 'svn'; +$cfg['svnlook_path'] = 'svnlook'; +$cfg['svnadmin_path'] = 'svnadmin'; +$cfg['hg_path'] = 'hg'; +$cfg['git_path'] = 'git'; +$cfg['mtn_path'] = 'mtn'; + +# The monotone backend allow you to add extra options for the started monotone +# process; please keep the default if unsure. +$cfg['mtn_opts'] = array('--no-workspace', '--no-standard-rcfiles'); + + +# ---------------------------------------------------------------------------- # +# URL section # +# ---------------------------------------------------------------------------- # + +# Examples: +# You have: +# http://www.mydomain.com/myfolder/index.php +# Put: +# $cfg['idf_base'] = '/myfolder/index.php'; +# $cfg['url_base'] = 'http://www.mydomain.com'; +# +# You have mod_rewrite: +# http://www.mydomain.com/ +# Put: +# $cfg['idf_base'] = '/index.php'; +# $cfg['url_base'] = 'http://www.mydomain.com'; +# +$cfg['idf_base'] = ''; +$cfg['url_base'] = 'http://www.mydomain.com'; + +# URL to access the media folder which is in the www folder +# of the distribution archive +$cfg['url_media'] = 'https://www.mydomain.com/media'; + +# URL to access a folder in which the files you upload through +# the downloads tab will be stored. +$cfg['url_upload'] = 'https://mydomain.com/media/upload'; + + +# ---------------------------------------------------------------------------- # +# Internationalization section # +# ---------------------------------------------------------------------------- # + +# Enter a valid time zone here to ensure that external timestamps, coming from +# the SCM for example, are translated into this time zone. +# A list of available time zones can be found at +# +$cfg['time_zone'] = 'America/Chicago'; + +# Configure which languages should be available in your forge. +# If you want to enable an additional language, ensure that the +# language file in question resides in 'src/IDF/locale'. +$cfg['languages'] = array('en', 'fr', 'de', 'es_ES', 'ru'); + + +# ---------------------------------------------------------------------------- # +# Email section # +# ---------------------------------------------------------------------------- # +# +# Indefero uses the PEAR Mail class to send mails. Available mail backend are: +# +# - The PHP Mail built-in function (mail) +# - Sendmail (sendmail) +# - Simple Mail Transfer Protocol (smtp) +# +# Sendmail and SMTP need extra configuration, see the examples below. +# + +# This is a general lock to enable or disable the mail sending process. +# True enables mail sending, false disables it. +$cfg['send_emails'] = true; + +# The mail backend to use: mail, sendmail, or smtp +$cfg['mail_backend'] = 'mail'; + +# Mails sent by indefero will have thoses headers: +$cfg['from_email'] = 'email@mydomain.com'; + +$cfg['bounce_email'] = ' '; + +# The following persons will get an email in case of errors, i.e. when the +# system is in not in debug mode (see $cfg['debug'] above). +$cfg['admins'] = array( + array('Bob', 'bob@example.com'), +); + +## +## Example SMTP configuration +## +## The server to connect. Default is localhost +#$cfg['mail_host'] = 'localhost'; +## The port to connect. Default is 25 +#$cfg['mail_port'] = 25; +## The username to use for SMTP authentication. +#$cfg['mail_username'] = ''; +## The password to use for SMTP authentication. +#$cfg['mail_password'] = ''; +## The value to give when sending EHLO or HELO. Default is localhost +#$cfg['mail_localhost'] = 'localhost'; +## The SMTP connection timeout. Default is NULL (no timeout) +#$cfg['mail_timeout'] = NULL; +## Whether to use VERP or not. Default is FALSE +#$cfg['mail_verp'] = FALSE; + +## +## Example sendmail configuration +## +## The location of the sendmail program on the filesystem. +## Default is /usr/bin/sendmail +#$cfg['mail_sendmail_path'] = '/usr/bin/sendmail'; +## Additional parameters to pass to the sendmail. Default is -i +#$cfg['sendmail_args'] = '-i'; + + +# ---------------------------------------------------------------------------- # +# Database section # +# ---------------------------------------------------------------------------- # +# +# WARNING: DO NOT USE SQLITE IN PRODUCTION +# +# This is not because of problems with the quality of the SQLite +# driver or with SQLite itself, but due to the lack of migration +# support in Pluf for SQLite. This means we cannot modify the DB +# easily once it is loaded with data. +# + +# Enter one of the supported database engines: SQLite, MySQL, or PostgreSQL +$cfg['db_engine'] = 'MySQL'; + +# The database name for MySQL and PostgreSQL, and the absolute path +# to the database file if you are using SQLite. +$cfg['db_database'] = 'indefero'; + +# The database server to connect. +$cfg['db_server'] = ''; + +# Information about the database user. +$cfg['db_login'] = 'indefero'; +$cfg['db_password'] = ''; + +# The version of your database server, only needed for MySQL +$cfg['db_version'] = '5.1'; + +# A prefix for your table name; this can be useful if you plan to run +# multiple indefero installations on the same database instance. +$cfg['db_table_prefix'] = 'indefero_'; + + +# ---------------------------------------------------------------------------- # +# Cache section # +# ---------------------------------------------------------------------------- # + +# The cache is used to speed up the operations of most of the SCM commands. +# +# Indefero supports three methods to handle the cache, and you need to +# configure it with one of them: +# +# - Files (Pluf_Cache_File) +# - Alternative PHP Cache (Pluf_Cache_Apc) +# - Memcached (Pluf_Cache_Memcached) +# +# Both, APC and Memcached, need additional extensions to be compiled into +# your PHP installation, so the easiest is to use the file-based cache +# for an initial setup. +# +# For more information on APC, see . +# Memcached is documented at . +# +$cfg['cache_engine'] = 'Pluf_Cache_File'; +$cfg['cache_timeout'] = 300; +$cfg['cache_file_folder'] = $cfg['tmp_folder'].'/cache'; + +#$cfg['cache_engine'] = 'Pluf_Cache_Apc'; +#$cfg['cache_timeout'] = 300; +#$cfg['cache_apc_keyprefix'] = 'uniqueforapp'; +#$cfg['cache_apc_compress'] = true; + +#$cfg['cache_engine'] = 'Pluf_Cache_Memcached'; +#$cfg['cache_timeout'] = 300; +#$cfg['cache_memcached_keyprefix'] = 'uniqueforapp'; +#$cfg['cache_memcached_server'] = 'localhost'; +#$cfg['cache_memcached_port'] = 11211; +#$cfg['cache_memcached_compress'] = MEMCACHE_COMPRESSED; + + +# ---------------------------------------------------------------------------- # +# Git SCM section # +# ---------------------------------------------------------------------------- # +# +# Read the file 'doc/syncgit.mdtext' for more information +# + +# Uncomment this line to enable git support. +$cfg['allowed_scm']['git'] = 'IDF_Scm_Git'; + +# The path to the git repositories. '%s' is replaced with the project name. +# Do not forget to give read access to these folders to your www user, +# for example by adding the www user to the git group. +$cfg['git_repositories'] = '/home/git/repositories/%s.git'; + +# Git URL for public access to a repository. '%s' is again replaced with +# the project name. See 'doc/syncgit.mdtext' for the git-daemon configuration. +$cfg['git_remote_url'] = 'git://mydomain.com/%s.git'; + +# Git URL for private / write access to a repository. Again, '%s' is replaced +# with the name of the project. See 'doc/syncgit.mdtext' for more information +# about SSH authentification +['git_write_remote_url'] = 'ssh://git@mydomain.com/%s.git'; + +# The 'core.quotepath' option is configured on all new repositories created by +# indefero. This option disable characters to be escaped, when git commands run +# on an UTF-8 shell. +# +# - true: All characters above 0x80 will be escaped (default) +# - false: Characters are printed directly, which for example enables +# accented characters in an UTF-8 shell +# +# If you see malformed filenames in the source view, try to set this to false. +# $cfg['git_core_quotepath'] = false; + +# Path to the gitserve.py script +$cfg['idf_plugin_syncgit_path_gitserve'] = '/home/www/indefero/scripts/gitserve.py'; + +# Path to the 'authorized_keys' file of your git user +$cfg['idf_plugin_syncgit_path_authorized_keys'] = '/home/git/.ssh/authorized_keys'; + +# Path to the temporary file for key synchronization +$cfg['idf_plugin_syncgit_sync_file'] = '/tmp/SYNC-GIT'; + +# Path to the git home +$cfg['idf_plugin_syncgit_git_home_dir'] = '/home/git'; + +# Path to the folder which contains all git repositories +$cfg['idf_plugin_syncgit_base_repositories'] = '/home/git/repositories'; + +# Set a custom git-post-update script. Use this only, if you know you are doing! +# $cfg['idf_plugin_syncgit_post_update'] = '/my/script'; + +# Automatically delete git repositories of deleted projects +# $cfg['idf_plugin_syncgit_remove_orphans'] = true; + + +# ---------------------------------------------------------------------------- # +# SVN SCM section # +# ---------------------------------------------------------------------------- # +# +# Read the file doc/syncsvn.mdtext for more information +# + +# Uncomment this line to enable the SVN support. +$cfg['allowed_scm']['svn'] = 'IDF_Scm_Svn'; + +# In case of subversion, you can either use a local or a remote repository. +# The forge admin can configure a remote repository directly from the +# web interface. Local repositories cannot be configured from there, +# for security reasons, but have to be defined here. +# '%s' is replaced with the project name. +$cfg['svn_repositories'] = 'file:///home/svn/repositories/%s'; + +# The HTTP URL to the local SVN repository. +# We add 'trunk' to invite people to checkout the trunk of the project. +# Again, '%s' is replaced with the project name. +$cfg['svn_remote_url'] = 'https://mydomain.com/svn/%s/trunk'; + +# Path to the authentification files for dav_svn +$cfg['idf_plugin_syncsvn_authz_file'] = '/home/svn/dav_svn.authz'; +$cfg['idf_plugin_syncsvn_passwd_file'] = '/home/svn/dav_svn.passwd'; + +# Path to the folder which contains all SVN repositories +$cfg['idf_plugin_syncsvn_svn_path'] = '/home/svn/repositories'; + +# You can customize permissions for each user group. +# $cfg['idf_plugin_syncsvn_access_owners'] = 'rw'; +# $cfg['idf_plugin_syncsvn_access_members'] = 'rw'; +# $cfg['idf_plugin_syncsvn_access_extra'] = 'r'; +# $cfg['idf_plugin_syncsvn_access_public'] = 'r'; +# $cfg['idf_plugin_syncsvn_access_private'] = ''; + +# Automatically delete local SVN repositories of deleted projects +# $cfg['idf_plugin_syncsvn_remove_orphans'] = true; + + +# ---------------------------------------------------------------------------- # +# Mercurial SCM section # +# ---------------------------------------------------------------------------- # +# +# Read the file doc/syncmercurial.mdtext for more information +# + +# Uncomment this line to enable the Mercurial support. +$cfg['allowed_scm']['mercurial'] = 'IDF_Scm_Mercurial'; + +# The path to mercurial repositories. '%s' is replaced with the project name. +$cfg['mercurial_repositories'] = '/home/mercurial/repositories/%s'; + +$cfg['mercurial_remote_url'] = 'https://mydomain.com/hg/%s'; + +$cfg['idf_plugin_syncmercurial_hgrc'] = array( + 'web' => array('push_ssl' => 'true', + 'allow_push' => '', + 'description' => '', + 'allow_archive' => 'bz2, zip, gz', + 'style' => 'gitweb', + 'contact' => ''), + 'hooks' => array(), + 'extensions' => array(), +); + +# Based on the paths provided in the Apache configuration, +# you need to setup the following lines. +$cfg['idf_plugin_syncmercurial_passwd_file'] = '/home/mercurial/.htpasswd'; +$cfg['idf_plugin_syncmercurial_path'] = '/home/mercurial/repositories'; +$cfg['idf_plugin_syncmercurial_private_notify'] = '/home/mercurial/tmp/notify.tmp'; +$cfg['idf_plugin_syncmercurial_private_url'] = '/hg/%s'; + +# Authentification file for private repositories +// $cfg['idf_plugin_syncmercurial_private_include'] = '/home/mercurial/scripts/private_indefero.conf'; +$cfg['idf_plugin_syncmercurial_private_include'] = '/home/www/indefero/scripts/private_indefero.conf'; + +# Password storage type (see 'doc/syncmercurial.mdtext') +# $cfg['idf_plugin_syncmercurial_passwd_mode'] = 'sha'; + + +# ---------------------------------------------------------------------------- # +# Monotone SCM section # +# ---------------------------------------------------------------------------- # +# +# Read the file doc/syncmonotone.mdtext for more information +# + +# Uncomment this line to enable the monotone support. +# $cfg['allowed_scm']['mtn'] = 'IDF_Scm_Monotone'; + +# The path to a specific database (local use) or a writable project +# directory (remote / usher use). '%s' is replaced with the project name. +$cfg['mtn_repositories'] = '/home/mtn/repositories/%s.mtn'; + +# The URL which is displayed as sync URL to the user and which is also +# used to connect to a remote usher. +$cfg['mtn_remote_url'] = 'mtn://example.com/%s'; + +# Whether the particular database(s) are accessed locally (via automate stdio) +# or remotely (via automate remote_stdio). 'remote' is the default for +# use with usher and the SyncMonotone plugin, while 'local' access should be +# choosed for manual setups and / or ssh access. +$cfg['mtn_db_access'] = 'local'; + +# Needs to be configured for remote / usher usage. +# This allows basic control of a running usher process via the forge +# administration. The variable must point to the full (writable) +# path of the usher configuration file which gets updated when new projects +# are added. +# $cfg['mtn_usher_conf'] = '/var/lib/usher/usher.conf'; + +# Full path to the directory tree which contains default configuration files +# that are automatically created for new projects. This is only needed +# if $cfg['mtn_db_access'] is set to remote, i.e. in case the SyncMonotone +# plugin should be used. If unset, it defaults to the tree underknees +# src/IDF/Plugin/SyncMonotone/. Don't forget the trailing slash! +# $cfg['mtn_confdir'] = '/path/to/dir/tree/'; + +# Additional configuration files you want to create / copy for new setups. +# All these file paths have to be relative to $cfg['mtn_confdir']. +# $cfg['mtn_confdir_extra'] = array('hooks.d/something.lua') + + +# ---------------------------------------------------------------------------- # +# Hacker section (for advanced users) # +# ---------------------------------------------------------------------------- # + +$cfg['installed_apps'] = array('Pluf', 'IDF'); + +$cfg['pluf_use_rowpermission'] = true; + +$cfg['middleware_classes'] = array( + 'Pluf_Middleware_Csrf', + 'Pluf_Middleware_Session', + //'Pluf_Middleware_Debug', + 'Pluf_Middleware_Stats', + 'IDF_Middleware', + 'Pluf_Middleware_Translation', + ); + +$cfg['template_context_processors'] = array('IDF_Middleware_ContextPreProcessor'); + +$cfg['idf_views'] = dirname(__FILE__).'/urls.php'; + +# If you want to customize some of the template files, you must tell the +# template system where it can find your updated files by adding the particular +# folder to the following array. +$cfg['template_folders'] = array( + dirname(__FILE__).'/../templates', +); + +# You can customize the URL redirection after a login or logout action. +$cfg['login_success_url'] = $cfg['url_base'].$cfg['idf_base']; +$cfg['after_logout_page'] = $cfg['url_base'].$cfg['idf_base']; + +# Set to true if uploaded public keys should not only be validated +# syntactically, but also by a specific backend. For SSH public +# keys, ssh-keygen(3) must be available and usable in the system PATH, +# for monotone public keys, the monotone binary (as configured above) +# is used. +$cfg['idf_strong_key_check'] = false; + +# If you want to use another mime types database, enter its path here. +# $cfg['idf_mimetypes_db'] = '/etc/mime.types'; + +# Extentions of additional text files that should be displayed inline. +# $cfg['idf_extra_text_ext'] = 'ext1 ext2 ext3'; + +# If you can execute the needed shell commands to query information from your +# SCM, but the same shell commands do not work from within the indefero +# instance, this can be due to the environment variables not being set +# correctly. ATTENTION: Do not forget the trailing space! +# $cfg['idf_exec_cmd_prefix'] = '/usr/bin/env -i '; + +# If you do not want to let indefero calculate the sizes of repositories, +# attachments, or downloads, set this to true. (You can temporarily set this +# to false in case you want to quickly check some size, of course.) +# $cfg['idf_no_size_check'] = false; + +# The file extensions for file uploads (issues and downloads view) are limited. +# You can allow additional extensions here. +# $cfg['idf_extra_upload_ext'] = 'ext1 ext2'; + +# By default, the size of a single file upload is limited to 2MB. +# The php.ini upload_max_filesize and post_max_size configuration setting will +# always have precedence. +# $cfg['max_upload_size'] = 2097152; // Size in bytes + +# If a download archive is uploaded, the size of the archive is limited to 20MB. +# The php.ini upload_max_filesize and post_max_size configuration setting will +# always have precedence. +# $cfg['max_upload_archive_size'] = 20971520; // Size in bytes + +# Older versions of Indefero submitted a POST request to a configured +# post-commit web hook when new revisions arrived, whereas a PUT request +# would have been more appropriate. Also, the payload's HMAC digest was +# submitted as value of the HTTP header 'Post-Commit-Hook-Hmac' during +# such a request. Since newer versions of Indefero use the same authentication +# mechanism (based on the same secret key) for other web hooks of the same +# project as well, the name of this HTTP header was no longer appropriate +# and as such changed to simply 'Web-Hook-Hmac'. +# +# Setting the following configuration option to 'compat' now restores the +# old behaviour in both cases. Please notice however that this compatibility +# option is likely to go away in the next major version of Indefero, so you +# should really change the other end of your web hooks! +$cfg['webhook_processing'] = 'compat'; + +# If IDF recalculates the activity index of the forge's projects, it does so +# by looking at the created and updated items in a particular tab / section +# for each project. +# +# You can now edit the weights that are applied to the calculation for each +# section in order to give other things more precendence. For example, if you +# do not use the documentation part to a great extent in most of your projects, +# you can weight this section lower and get an overall better activity value. +# +# If a section is removed, then activity in this section is neglected during +# the calculation. The same is true in case a section is disabled in the +# project administration. +$cfg['activity_section_weights'] = array( + 'source' => 4, + 'issues' => 2, + 'wiki' => 2, + 'downloads' => 2, + 'review' => 1, +); + +# Here you can define the timespan in days how long the activity calculation +# process should look into the history to get meaningful activity values for +# each project. +# +# If you have many low-profile projects in your forge, i.e. projects that only +# record very little activity, then it might be a good idea to bump this value +# high enough to show a proper activity index for those projects as well. +$cfg['activity_lookback'] = 7; +//$cfg["log_level"] = Pluf_Log::ALL; +//$cfg["log_handler"] = 'Pluf_Log_File'; +//$cfg["log_delayed"] = true; +//$cfg["pluf_log_file"] = '/home/www/pluf.log'; +//Pluf_Log::$level = Pluf_Log::ALL; +return $cfg; diff --git a/indefero/src/IDF/conf/path.php b/indefero/src/IDF/conf/path.php new file mode 100644 index 0000000..d8c90ca --- /dev/null +++ b/indefero/src/IDF/conf/path.php @@ -0,0 +1,38 @@ + '#^/$#', + 'base' => $base, + 'model' => 'IDF_Views', + 'method' => 'index'); + +$ctl[] = array('regex' => '#^/projects/$#', + 'base' => $base, + 'model' => 'IDF_Views', + 'method' => 'listProjects'); + +$ctl[] = array('regex' => '#^/projects/label/(\w+)/(\w+)/$#', + 'base' => $base, + 'model' => 'IDF_Views', + 'method' => 'listProjectsByLabel'); + +$ctl[] = array('regex' => '#^/login/$#', + 'base' => $base, + 'model' => 'IDF_Views', + 'method' => 'login', + 'name' => 'login_view'); + +$ctl[] = array('regex' => '#^/preferences/$#', + 'base' => $base, + 'model' => 'IDF_Views_User', + 'method' => 'myAccount'); + +$ctl[] = array('regex' => '#^/dashboard/$#', + 'base' => $base, + 'model' => 'IDF_Views_User', + 'method' => 'dashboard', + 'name' => 'idf_dashboard'); + +$ctl[] = array('regex' => '#^/dashboard/submitted/$#', + 'base' => $base, + 'model' => 'IDF_Views_User', + 'method' => 'dashboard', + 'params' => false, + 'name' => 'idf_dashboard_submit'); + +$ctl[] = array('regex' => '#^/u/(.*)/$#', + 'base' => $base, + 'model' => 'IDF_Views_User', + 'method' => 'view'); + +$ctl[] = array('regex' => '#^/logout/$#', + 'base' => $base, + 'model' => 'IDF_Views', + 'method' => 'logout'); + +$ctl[] = array('regex' => '#^/help/$#', + 'base' => $base, + 'model' => 'IDF_Views', + 'method' => 'faq', + 'name' => 'idf_faq'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Project', + 'method' => 'home'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/logo/$#', + 'base' => $base, + 'model' => 'IDF_Views_Project', + 'method' => 'logo'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/timeline/(\w+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Project', + 'method' => 'timeline'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/feed/timeline/(\w+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Project', + 'method' => 'timelineFeed', + 'name' => 'idf_project_timeline_feed'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/feed/timeline/(\w+)/token/(.*)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Project', + 'method' => 'timelineFeed', + 'name' => 'idf_project_timeline_feed_auth'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/timeline/$#', + 'base' => $base, + 'model' => 'IDF_Views_Project', + 'method' => 'timelineCompat'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/feed/timeline/$#', + 'base' => $base, + 'model' => 'IDF_Views_Project', + 'method' => 'timelineFeedCompat', + 'name' => 'idf_project_timeline_feed'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/feed/timeline/token/(.*)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Project', + 'method' => 'timelineFeedCompat', + 'name' => 'idf_project_timeline_feed_auth'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/$#', + 'base' => $base, + 'model' => 'IDF_Views_Issue', + 'method' => 'index'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/summary/$#', + 'base' => $base, + 'model' => 'IDF_Views_Issue', + 'method' => 'summary'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/search/$#', + 'base' => $base, + 'model' => 'IDF_Views_Issue', + 'method' => 'search'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/search/status/(\w+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Issue', + 'method' => 'searchStatus'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/search/label/(\d+)/(\w+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Issue', + 'method' => 'searchLabel'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/(\d+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Issue', + 'method' => 'view'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/(\d+)/star/$#', + 'base' => $base, + 'model' => 'IDF_Views_Issue', + 'method' => 'star'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/status/(\w+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Issue', + 'method' => 'listStatus'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/label/(\d+)/(\w+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Issue', + 'method' => 'listLabel'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/create/$#', + 'base' => $base, + 'model' => 'IDF_Views_Issue', + 'method' => 'create'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/(.*)/(\w+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Issue', + 'method' => 'userIssues'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/attachment/(\d+)/(.*)$#', + 'base' => $base, + 'model' => 'IDF_Views_Issue', + 'method' => 'getAttachment'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/view/attachment/(\d+)/(.*)$#', + 'base' => $base, + 'model' => 'IDF_Views_Issue', + 'method' => 'viewAttachment'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/watchlist/(\w+)$#', + 'base' => $base, + 'model' => 'IDF_Views_Issue', + 'method' => 'watchList'); + +$ctl[] = array('regex' => '#^/watchlist/(\w+)$#', + 'base' => $base, + 'model' => 'IDF_Views_Issue', + 'method' => 'forgeWatchList'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/autocomplete/(\d*)$#', + 'base' => $base, + 'model' => 'IDF_Views_Issue', + 'method' => 'autoCompleteIssueList'); + +// ---------- SCM ---------------------------------------- + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/source/help/$#', + 'base' => $base, + 'model' => 'IDF_Views_Source', + 'method' => 'help'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/source/invalid/([^/]+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Source', + 'method' => 'invalidRevision'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/source/disambiguate/([^/]+)/from/([^/]+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Source', + 'method' => 'disambiguateRevision'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/source/tree/([^/]+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Source', + 'method' => 'treeBase'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/source/tree/([^/]+)/(.*)$#', + 'base' => $base, + 'model' => 'IDF_Views_Source', + 'method' => 'tree'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/source/changes/([^/]+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Source', + 'method' => 'changeLog'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/source/commit/([^/]+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Source', + 'method' => 'commit'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/source/ddiff/([^/]+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Source', + 'method' => 'downloadDiff'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/source/download/([^/]+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Source', + 'method' => 'download'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/source/file/([^/]+)/(.*)$#', + 'base' => $base, + 'model' => 'IDF_Views_Source', + 'method' => 'getFile'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/source/treerev/$#', + 'base' => $base, + 'model' => 'IDF_Views_Source_Svn', + 'method' => 'treeRev'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/source/changesrev/$#', + 'base' => $base, + 'model' => 'IDF_Views_Source_Svn', + 'method' => 'changelogRev'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/source/repo/(.*)$#', + 'base' => $base, + 'model' => 'IDF_Views_Source', + 'method' => 'repository'); + +// ---------- WIKI ----------------------------------------- + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/doc/$#', + 'base' => $base, + 'model' => 'IDF_Views_Wiki', + 'method' => 'listPages'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/res/$#', + 'base' => $base, + 'model' => 'IDF_Views_Wiki', + 'method' => 'listResources'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/doc/create/$#', + 'base' => $base, + 'model' => 'IDF_Views_Wiki', + 'method' => 'createPage'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/res/create/$#', + 'base' => $base, + 'model' => 'IDF_Views_Wiki', + 'method' => 'createResource'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/doc/search/$#', + 'base' => $base, + 'model' => 'IDF_Views_Wiki', + 'method' => 'search'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/doc/label/(\d+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Wiki', + 'method' => 'listPagesWithLabel'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/doc/update/(.*)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Wiki', + 'method' => 'updatePage'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/res/update/(.*)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Wiki', + 'method' => 'updateResource'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/doc/delrev/(\d+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Wiki', + 'method' => 'deletePageRev'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/res/delrev/(\d+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Wiki', + 'method' => 'deleteResourceRev'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/doc/delete/(\d+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Wiki', + 'method' => 'deletePage'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/res/delete/(\d+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Wiki', + 'method' => 'deleteResource'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/res/raw/(.*)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Wiki', + 'method' => 'rawResource'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/page/(.*)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Wiki', + 'method' => 'viewPage'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/resource/(.*)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Wiki', + 'method' => 'viewResource'); + +// ---------- Downloads ------------------------------------ + +$ctl[] = array('regex' => '#^/help/archive-format/$#', + 'base' => $base, + 'model' => 'IDF_Views', + 'method' => 'faqArchiveFormat'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/downloads/$#', + 'base' => $base, + 'model' => 'IDF_Views_Download', + 'method' => 'index'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/downloads/label/(\d+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Download', + 'method' => 'listLabel'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/downloads/(\d+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Download', + 'method' => 'view'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/downloads/get/(.+)$#', + 'base' => $base, + 'model' => 'IDF_Views_Download', + 'method' => 'download'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/downloads/(\d+)/get/$#', + 'base' => $base, + 'model' => 'IDF_Views_Download', + 'method' => 'downloadById'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/downloads/create/$#', + 'base' => $base, + 'model' => 'IDF_Views_Download', + 'method' => 'create'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/downloads/create/archive/$#', + 'base' => $base, + 'model' => 'IDF_Views_Download', + 'method' => 'createFromArchive'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/downloads/(\d+)/delete/$#', + 'base' => $base, + 'model' => 'IDF_Views_Download', + 'method' => 'delete'); + +// ---------- CODE REVIEW -------------------------------- + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/review/$#', + 'base' => $base, + 'model' => 'IDF_Views_Review', + 'method' => 'index'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/review/(\d+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Review', + 'method' => 'view'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/review/create/$#', + 'base' => $base, + 'model' => 'IDF_Views_Review', + 'method' => 'create'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/review/getpatch/(\d+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Review', + 'method' => 'getPatch'); + + +// ---------- ADMIN -------------------------------------- + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/admin/$#', + 'base' => $base, + 'model' => 'IDF_Views_Project', + 'method' => 'admin'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/admin/issues/$#', + 'base' => $base, + 'model' => 'IDF_Views_Project', + 'method' => 'adminIssues'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/admin/downloads/$#', + 'base' => $base, + 'model' => 'IDF_Views_Project', + 'method' => 'adminDownloads'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/admin/wiki/$#', + 'base' => $base, + 'model' => 'IDF_Views_Project', + 'method' => 'adminWiki'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/admin/source/$#', + 'base' => $base, + 'model' => 'IDF_Views_Project', + 'method' => 'adminSource'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/admin/members/$#', + 'base' => $base, + 'model' => 'IDF_Views_Project', + 'method' => 'adminMembers'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/admin/tabs/$#', + 'base' => $base, + 'model' => 'IDF_Views_Project', + 'method' => 'adminTabs'); + +// ---------- API ---------------------------------------- + +$ctl[] = array('regex' => '#^/help/api/$#', + 'base' => $base, + 'model' => 'IDF_Views', + 'method' => 'faqApi'); + +$ctl[] = array('regex' => '#^/api/p/([\-\w]+)/issues/$#', + 'base' => $base, + 'model' => 'IDF_Views_Api', + 'method' => 'issuesIndex'); + +$ctl[] = array('regex' => '#^/api/p/([\-\w]+)/issues/create/$#', + 'base' => $base, + 'model' => 'IDF_Views_Api', + 'method' => 'issueCreate'); + +$ctl[] = array('regex' => '#^/api/$#', + 'base' => $base, + 'model' => 'IDF_Views_Api', + 'method' => 'projectIndex'); + +// ---------- FORGE ADMIN -------------------------------- + +$ctl[] = array('regex' => '#^/admin/forge/$#', + 'base' => $base, + 'model' => 'IDF_Views_Admin', + 'method' => 'forge'); + +$ctl[] = array('regex' => '#^/admin/projects/$#', + 'base' => $base, + 'model' => 'IDF_Views_Admin', + 'method' => 'projects'); + +$ctl[] = array('regex' => '#^/admin/projects/(\d+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Admin', + 'method' => 'projectUpdate'); + +$ctl[] = array('regex' => '#^/admin/projects/labels/$#', + 'base' => $base, + 'model' => 'IDF_Views_Admin', + 'method' => 'projectLabels'); + +$ctl[] = array('regex' => '#^/admin/projects/create/$#', + 'base' => $base, + 'model' => 'IDF_Views_Admin', + 'method' => 'projectCreate'); + +$ctl[] = array('regex' => '#^/admin/projects/(\d+)/delete/$#', + 'base' => $base, + 'model' => 'IDF_Views_Admin', + 'method' => 'projectDelete'); + +$ctl[] = array('regex' => '#^/admin/users/$#', + 'base' => $base, + 'model' => 'IDF_Views_Admin', + 'method' => 'users'); + +$ctl[] = array('regex' => '#^/admin/users/create/$#', + 'base' => $base, + 'model' => 'IDF_Views_Admin', + 'method' => 'userCreate'); + +$ctl[] = array('regex' => '#^/admin/users/notvalid/$#', + 'base' => $base, + 'model' => 'IDF_Views_Admin', + 'method' => 'usersNotValidated'); + +$ctl[] = array('regex' => '#^/admin/users/(\d+)/$#', + 'base' => $base, + 'model' => 'IDF_Views_Admin', + 'method' => 'userUpdate'); + +if (Pluf::f("mtn_usher_conf", null) !== null) +{ + $ctl[] = array('regex' => '#^/admin/usher/$#', + 'base' => $base, + 'model' => 'IDF_Views_Admin', + 'method' => 'usher'); + + $ctl[] = array('regex' => '#^/admin/usher/control/(.*)$#', + 'base' => $base, + 'model' => 'IDF_Views_Admin', + 'method' => 'usherControl'); + + $ctl[] = array('regex' => '#^/admin/usher/server/(.+)/control/(.+)$#', + 'base' => $base, + 'model' => 'IDF_Views_Admin', + 'method' => 'usherServerControl'); + + $ctl[] = array('regex' => '#^/admin/usher/server/(.+)/connections/$#', + 'base' => $base, + 'model' => 'IDF_Views_Admin', + 'method' => 'usherServerConnections'); +} + +// ---------- UTILITY VIEWS ------------------------------- + +$ctl[] = array('regex' => '#^/register/$#', + 'base' => $base, + 'model' => 'IDF_Views', + 'method' => 'register'); + +$ctl[] = array('regex' => '#^/register/k/(.*)/$#', + 'base' => $base, + 'model' => 'IDF_Views', + 'method' => 'registerConfirmation'); + +$ctl[] = array('regex' => '#^/register/ik/$#', + 'base' => $base, + 'model' => 'IDF_Views', + 'method' => 'registerInputKey'); + +$ctl[] = array('regex' => '#^/password/$#', + 'base' => $base, + 'model' => 'IDF_Views', + 'method' => 'passwordRecoveryAsk'); + +$ctl[] = array('regex' => '#^/password/ik/$#', + 'base' => $base, + 'model' => 'IDF_Views', + 'method' => 'passwordRecoveryInputCode'); + +$ctl[] = array('regex' => '#^/password/k/(.*)/$#', + 'base' => $base, + 'model' => 'IDF_Views', + 'method' => 'passwordRecovery'); + +$ctl[] = array('regex' => '#^/preferences/email/ik/$#', + 'base' => $base, + 'model' => 'IDF_Views_User', + 'method' => 'changeEmailInputKey'); + +$ctl[] = array('regex' => '#^/preferences/email/ak/(.*)/$#', + 'base' => $base, + 'model' => 'IDF_Views_User', + 'method' => 'changeEmailDo'); + +$ctl[] = array('regex' => '#^/preferences/email/(\d+)/delete/$#', + 'base' => $base, + 'model' => 'IDF_Views_User', + 'method' => 'deleteMail'); + +$ctl[] = array('regex' => '#^/preferences/key/(\d+)/delete/$#', + 'base' => $base, + 'model' => 'IDF_Views_User', + 'method' => 'deleteKey'); + + +return $ctl; diff --git a/indefero/src/IDF/locale/cs/idf.po b/indefero/src/IDF/locale/cs/idf.po new file mode 100644 index 0000000..c0f3a26 --- /dev/null +++ b/indefero/src/IDF/locale/cs/idf.po @@ -0,0 +1,5469 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# William MARTIN , 2011. +msgid "" +msgstr "" +"Project-Id-Version: Indefero\n" +"Report-Msgid-Bugs-To: http://projects.ceondo.com/p/indefero/issues/\n" +"POT-Creation-Date: 2012-03-22 01:16+0100\n" +"PO-Revision-Date: 2011-10-31 00:19+0000\n" +"Last-Translator: tommyd \n" +"Language-Team: Czech (http://www.transifex.net/projects/p/indefero/team/" +"cs/)\n" +"Language: cs\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2\n" + +#: IDF/Commit.php:55 IDF/Conf.php:54 IDF/Issue.php:52 +#: IDF/ProjectActivity.php:49 IDF/Review.php:65 IDF/Search/Occ.php:69 +#: IDF/Tag.php:52 IDF/Upload.php:49 IDF/Wiki/Page.php:54 +#: IDF/Wiki/Resource.php:56 +msgid "project" +msgstr "projekt" + +#: IDF/Commit.php:63 IDF/Issue.php:67 IDF/IssueComment.php:65 +#: IDF/IssueFile.php:57 IDF/IssueRelation.php:69 IDF/Review/Comment.php:69 +#: IDF/Review.php:80 IDF/Upload.php:91 IDF/Wiki/Page.php:78 +#: IDF/Wiki/PageRevision.php:79 IDF/Wiki/Resource.php:88 +#: IDF/Wiki/ResourceRevision.php:86 +msgid "submitter" +msgstr "odesílatel" + +#: IDF/Commit.php:87 IDF/Issue.php:60 IDF/Review/Patch.php:60 +#: IDF/Review.php:73 IDF/Upload.php:57 IDF/Wiki/Page.php:70 +#: IDF/Wiki/PageRevision.php:65 IDF/Wiki/Resource.php:80 +#: IDF/Wiki/ResourceRevision.php:63 +msgid "summary" +msgstr "souhrn" + +#: IDF/Commit.php:93 +msgid "changelog" +msgstr "seznam změn" + +#: IDF/Commit.php:100 IDF/Issue.php:105 IDF/IssueComment.php:79 +#: IDF/IssueFile.php:96 IDF/IssueRelation.php:75 IDF/Review/Comment.php:90 +#: IDF/Review/FileComment.php:75 IDF/Review/Patch.php:87 IDF/Review.php:108 +#: IDF/Upload.php:112 IDF/Wiki/Page.php:100 IDF/Wiki/PageRevision.php:92 +#: IDF/Wiki/Resource.php:95 IDF/Wiki/ResourceRevision.php:101 +msgid "creation date" +msgstr "datum vytvoření" + +#: IDF/Commit.php:238 +#, fuzzy, php-format +msgid "Commit %1$s, by %2$s" +msgstr "Commit %s, %s" + +#: IDF/Commit.php:337 +#, fuzzy, php-format +msgid "New Commit %1$s - %2$s (%3$s)" +msgstr "Nový commit %s - %s (%s)" + +#: IDF/Conf.php:61 IDF/Gconf.php:73 +msgid "key" +msgstr "klíč" + +#: IDF/Conf.php:67 IDF/Gconf.php:79 IDF/ProjectActivity.php:62 +msgid "value" +msgstr "hodnota" + +#: IDF/Diff.php:460 +msgid "Old" +msgstr "" + +#: IDF/Diff.php:460 +msgid "New" +msgstr "" + +#: IDF/EmailAddress.php:49 IDF/Key.php:49 +msgid "user" +msgstr "uživatel" + +#: IDF/EmailAddress.php:55 +msgid "email" +msgstr "" + +#: IDF/Form/Admin/ForgeConf.php:34 +msgid "Custom forge page enabled" +msgstr "" + +#: IDF/Form/Admin/ForgeConf.php:39 IDF/Form/WikiPageCreate.php:80 +#: IDF/Form/WikiPageUpdate.php:72 +msgid "Content" +msgstr "" + +#: IDF/Form/Admin/LabelConf.php:40 +msgid "Predefined project labels" +msgstr "" + +#: IDF/Form/Admin/LabelConf.php:55 +#, php-format +msgid "" +"The label \"%s\" is invalid: A label must only consist of alphanumeric " +"characters and dashes, and can optionally contain a \":\" with a group " +"prefix." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:38 IDF/Views/Project.php:600 +msgid "git" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:39 IDF/Views/Project.php:601 +msgid "Subversion" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:40 IDF/Views/Project.php:602 +msgid "mercurial" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:41 IDF/Views/Project.php:603 +msgid "monotone" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:49 IDF/Form/Admin/ProjectUpdate.php:44 +#: IDF/Form/ProjectConf.php:39 IDF/Views/Admin.php:86 IDF/Views/Admin.php:273 +msgid "Name" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:55 IDF/Form/TabsConf.php:101 +#: IDF/gettexttemplates/idf/base-full.html.php:5 +#: IDF/gettexttemplates/idf/base-full.html~.php:5 +#: IDF/gettexttemplates/idf/base.html.php:5 +#: IDF/gettexttemplates/idf/base.html~.php:5 +#: IDF/gettexttemplates/idf/main-menu.html.php:9 +#: IDF/gettexttemplates/idf/project-list.html.php:5 +#: IDF/gettexttemplates/idf/project-list.html.php:7 +msgid "Private project" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:62 +msgid "Shortname" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:64 +msgid "" +"It must be unique for each project and composed only of letters, digits and " +"dash (-) like \"my-project\"." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:69 IDF/Form/Admin/ProjectUpdate.php:50 +msgid "Short description" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:70 IDF/Form/Admin/ProjectUpdate.php:51 +#: IDF/Project.php:79 +msgid "A one line description of the project." +msgstr "Jednořádkový popis projektu." + +#: IDF/Form/Admin/ProjectCreate.php:77 IDF/Form/Admin/ProjectUpdate.php:58 +#: IDF/Form/ProjectConf.php:56 +msgid "External URL" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:84 +msgid "Repository type" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:92 +msgid "Remote Subversion repository" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:99 IDF/Form/SourceConf.php:40 +msgid "Repository username" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:106 IDF/Form/SourceConf.php:47 +msgid "Repository password" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:113 IDF/Form/Admin/ProjectUpdate.php:66 +msgid "Master branch" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:116 IDF/Form/Admin/ProjectUpdate.php:69 +msgid "" +"This should be a world-wide unique identifier for your project. A reverse " +"DNS notation like \"com.my-domain.my-project\" is a good idea." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:121 IDF/Form/Admin/ProjectUpdate.php:95 +#: IDF/Form/MembersConf.php:46 IDF/Form/TabsConf.php:53 +#: IDF/Form/TabsConf.php:72 +msgid "Project owners" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:130 IDF/Form/Admin/ProjectUpdate.php:103 +#: IDF/Form/MembersConf.php:54 IDF/Form/TabsConf.php:52 +#: IDF/Form/TabsConf.php:78 +msgid "Project members" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:140 IDF/Form/Admin/ProjectUpdate.php:85 +#: IDF/Form/IssueCreate.php:168 IDF/Form/IssueUpdate.php:164 +#: IDF/Form/ProjectConf.php:73 IDF/Form/UpdateUpload.php:71 +#: IDF/Form/Upload.php:70 IDF/Form/WikiPageCreate.php:93 +#: IDF/Form/WikiPageUpdate.php:104 +msgid "Labels" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:155 +msgid "Project template" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:157 +msgid "" +"Use the given project to initialize the new project. Access rights and " +"general configuration will be taken from the template project." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:204 +msgid "" +"Only a remote repository available through HTTP or HTTPS is allowed. For " +"example \"http://somewhere.com/svn/trunk\"." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:220 IDF/Form/Admin/ProjectUpdate.php:117 +msgid "" +"The master branch is empty or contains illegal characters, please use only " +"letters, digits, dashes and dots as separators." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:230 IDF/Form/Admin/ProjectUpdate.php:128 +msgid "This master branch is already used. Please select another one." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:241 +msgid "" +"This shortname contains illegal characters, please use only letters, digits " +"and dash (-)." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:244 +msgid "The shortname cannot start with the dash (-) character." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:247 +msgid "The shortname cannot end with the dash (-) character." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:252 +msgid "This shortname is already used. Please select another one." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:303 IDF/Form/Admin/ProjectDelete.php:78 +#: IDF/Form/Admin/ProjectUpdate.php:153 IDF/Form/Admin/UserCreate.php:106 +#: IDF/Form/Admin/UserUpdate.php:191 IDF/Form/IssueCreate.php:338 +#: IDF/Form/IssueUpdate.php:329 IDF/Form/MembersConf.php:64 +#: IDF/Form/Password.php:76 IDF/Form/Register.php:112 +#: IDF/Form/ReviewCreate.php:187 IDF/Form/ReviewFileComment.php:143 +#: IDF/Form/TabsConf.php:122 IDF/Form/UpdateUpload.php:126 +#: IDF/Form/Upload.php:149 IDF/Form/UploadArchive.php:137 +#: IDF/Form/UserAccount.php:216 IDF/Form/UserChangeEmail.php:80 +#: IDF/Form/WikiPageCreate.php:167 IDF/Form/WikiPageDelete.php:59 +#: IDF/Form/WikiPageUpdate.php:178 IDF/Form/WikiResourceCreate.php:123 +#: IDF/Form/WikiResourceDelete.php:59 IDF/Form/WikiResourceUpdate.php:124 +msgid "Cannot save the model from an invalid form." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:341 +msgid "" +"Click on the Project Management tab to set the description of your project." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:426 +msgid "This project is not available." +msgstr "" + +#: IDF/Form/Admin/ProjectDelete.php:41 +msgid "Confirmation code" +msgstr "" + +#: IDF/Form/Admin/ProjectDelete.php:46 +msgid "I have made a backup of all the important data of this project." +msgstr "" + +#: IDF/Form/Admin/ProjectDelete.php:55 +msgid "" +"The confirmation code does not match. Please provide a valid confirmation " +"code to delete the project." +msgstr "" + +#: IDF/Form/Admin/ProjectDelete.php:63 +msgid "Sorry, you really need to backup your data before deletion." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:37 IDF/Form/Admin/UserUpdate.php:38 +#: IDF/Form/RegisterConfirmation.php:50 IDF/Form/UserAccount.php:40 +msgid "First name" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:46 IDF/Form/Admin/UserUpdate.php:47 +#: IDF/Form/RegisterConfirmation.php:59 IDF/Form/UserAccount.php:49 +msgid "Last name" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:56 +msgid "Login" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:60 +msgid "" +"The login must be between 3 and 15 characters long and contains only letters " +"and digits." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:69 IDF/Form/Admin/UserUpdate.php:57 +msgid "Email" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:71 +msgid "" +"Double check the email address as the password is sent directly to the user." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:76 IDF/Form/Admin/UserUpdate.php:67 +#: IDF/Form/UserAccount.php:66 +msgid "Language" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:87 IDF/Form/UserAccount.php:161 +msgid "Add a public key" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:92 +msgid "" +"Paste a SSH or monotone public key. Be careful to not provide your private " +"key here!" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:157 +msgid "Your details to access your forge." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:189 IDF/Form/UserAccount.php:429 +#: IDF/Form/UserAccount.php:438 +#, php-format +msgid "The email \"%s\" is already used." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:198 IDF/Form/Register.php:72 +#, php-format +msgid "The login \"%s\" can only contain letters and digits." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:203 IDF/Form/Register.php:77 +#, php-format +msgid "The login \"%s\" is already used, please find another one." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:78 +msgid "Password" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:81 +msgid "Leave blank if you do not want to change the password." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:81 +msgid "" +"The password must be hard for other people to guess, but easy for the user " +"to remember." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:89 +msgid "Confirm password" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:100 IDF/Form/IssueCreate.php:66 +#: IDF/Form/ProjectConf.php:48 IDF/Form/ReviewCreate.php:54 +#: IDF/Form/UpdateUpload.php:51 IDF/Form/Upload.php:49 +#: IDF/Form/UserAccount.php:101 IDF/Form/WikiPageCreate.php:70 +#: IDF/Form/WikiPageUpdate.php:60 IDF/Form/WikiResourceCreate.php:54 +#: IDF/Form/WikiResourceUpdate.php:46 IDF/Views/Wiki.php:102 +msgid "Description" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:109 IDF/Form/UserAccount.php:110 +msgid "Twitter username" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:119 IDF/Form/UserAccount.php:120 +msgid "Public email address" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:129 IDF/Form/UserAccount.php:130 +msgid "Website URL" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:139 IDF/Form/UserAccount.php:140 +msgid "Upload custom avatar" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:146 IDF/Form/UserAccount.php:147 +msgid "" +"An image file with a width and height not larger than 60 pixels (bigger " +"images are scaled down)." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:151 IDF/Form/UserAccount.php:152 +msgid "Remove custom avatar" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:155 IDF/Form/UserAccount.php:156 +msgid "Tick this to delete the custom avatar." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:161 IDF/Views/Admin.php:274 +msgid "Staff" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:164 +msgid "If you give staff rights to a user, you really need to trust him." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:172 IDF/Views/Admin.php:276 +msgid "Active" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:176 +msgid "" +"If the user is not getting the confirmation email or is abusing the system, " +"you can directly enable or disable their account here." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:274 +msgid "--- is not a valid first name." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:290 +msgid "" +"A user with this email already exists, please provide another email address." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:301 IDF/Form/UserAccount.php:398 +msgid "For security reason, you cannot upload a file with this extension." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:316 IDF/Form/UserAccount.php:461 +msgid "The passwords do not match. Please give them again." +msgstr "" + +#: IDF/Form/Field/EmailList.php:45 +msgid "Please enter one or more valid email addresses." +msgstr "" + +#: IDF/Form/IssueCreate.php:57 IDF/Form/IssueUpdate.php:46 +#: IDF/Form/ReviewCreate.php:45 IDF/Form/ReviewFileComment.php:73 +#: IDF/Form/UpdateUpload.php:42 IDF/Form/Upload.php:40 +#: IDF/gettexttemplates/idf/issues/base.html.php:3 IDF/Views/Download.php:65 +#: IDF/Views/Download.php:347 IDF/Views/Issue.php:62 IDF/Views/Issue.php:221 +#: IDF/Views/Issue.php:302 IDF/Views/Issue.php:391 IDF/Views/Issue.php:543 +#: IDF/Views/Issue.php:766 IDF/Views/Issue.php:825 IDF/Views/Review.php:58 +#: IDF/Views/User.php:83 IDF/Views/Wiki.php:62 IDF/Views/Wiki.php:145 +#: IDF/Views/Wiki.php:186 +msgid "Summary" +msgstr "" + +#: IDF/Form/IssueCreate.php:76 IDF/Form/IssueUpdate.php:66 +#: IDF/Form/ReviewCreate.php:83 +msgid "The \"upload_issue_path\" configuration variable was not set." +msgstr "" + +#: IDF/Form/IssueCreate.php:86 IDF/Form/IssueUpdate.php:76 +msgid "Attach a file" +msgstr "" + +#: IDF/Form/IssueCreate.php:99 IDF/Form/IssueUpdate.php:89 +#: IDF/Form/ReviewCreate.php:103 IDF/Form/ReviewFileComment.php:83 +#: IDF/Views/Issue.php:63 IDF/Views/Issue.php:222 IDF/Views/Issue.php:304 +#: IDF/Views/Issue.php:392 IDF/Views/Issue.php:544 IDF/Views/Issue.php:767 +#: IDF/Views/Issue.php:826 IDF/Views/Review.php:59 IDF/Views/User.php:84 +msgid "Status" +msgstr "" + +#: IDF/Form/IssueCreate.php:108 IDF/Form/IssueUpdate.php:99 +msgid "Owner" +msgstr "" + +#: IDF/Form/IssueCreate.php:118 IDF/Form/IssueUpdate.php:112 +#: IDF/Form/IssueUpdate.php:129 +msgid "This issue" +msgstr "" + +#: IDF/Form/IssueCreate.php:210 +msgid "You cannot add a label with the \"Status\" prefix to an issue." +msgstr "" + +#: IDF/Form/IssueCreate.php:211 IDF/Form/IssueCreate.php:218 +#: IDF/Form/UpdateUpload.php:110 IDF/Form/Upload.php:121 +#: IDF/Form/WikiPageCreate.php:151 IDF/Form/WikiPageUpdate.php:162 +msgid "You provided an invalid label." +msgstr "" + +#: IDF/Form/IssueCreate.php:217 IDF/Form/UpdateUpload.php:109 +#, php-format +msgid "You cannot provide more than one label from the %s class to an issue." +msgstr "" + +#: IDF/Form/IssueCreate.php:228 IDF/Form/IssueUpdate.php:194 +msgid "You need to provide a description of the issue." +msgstr "" + +#: IDF/Form/IssueCreate.php:251 IDF/Form/ReviewCreate.php:159 +msgid "You provided an invalid status." +msgstr "" + +#: IDF/Form/IssueCreate.php:272 +msgid "You provided an invalid relation type." +msgstr "" + +#: IDF/Form/IssueCreate.php:294 +#, php-format +msgid "The value \"%s\" is not a valid issue id." +msgstr "" + +#: IDF/Form/IssueCreate.php:300 +#, php-format +msgid "The issue \"%s\" does not exist." +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:86 +msgid "is related to" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:87 +msgid "blocks" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:88 +msgid "is blocked by" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:89 +msgid "duplicates" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:90 +msgid "is duplicated by" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:97 +msgid "" +"Define an issue template to hint the reporter to provide certain information" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:106 +msgid "Open issue status values" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:114 +msgid "Closed issue status values" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:123 +msgid "Predefined issue labels" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:125 +msgid "" +"The first \"Type:\" and \"Priority:\" entries found in this list are " +"automatically chosen as defaults for new issues." +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:133 +msgid "Each issue may have at most one label with each of these classes." +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:140 +msgid "Issue relations" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:142 +msgid "" +"You can define bidirectional relations like \"is related to\" or \"blocks, " +"is blocked by\". For standard relations pre-configured translations exist, " +"new relations should however be defined in a language that is understood by " +"all project members." +msgstr "" + +#: IDF/Form/IssueUpdate.php:56 IDF/Form/ReviewFileComment.php:45 +#: IDF/Form/WikiPageUpdate.php:82 IDF/Form/WikiResourceUpdate.php:66 +msgid "Comment" +msgstr "" + +#: IDF/Form/IssueUpdate.php:316 +msgid "No changes were entered." +msgstr "" + +#: IDF/Form/MembersConf.php:104 +#, php-format +msgid "The following login is invalid: %s." +msgid_plural "The following logins are invalid: %s." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: IDF/Form/Password.php:34 +msgid "Your login or email" +msgstr "" + +#: IDF/Form/Password.php:35 +msgid "Provide either your login or your email to recover your password." +msgstr "" + +#: IDF/Form/Password.php:49 IDF/Form/Password.php:64 +msgid "" +"Sorry, we cannot find a user with this email address or login. Feel free to " +"try again." +msgstr "" + +#: IDF/Form/Password.php:100 +msgid "Password Recovery - InDefero" +msgstr "" + +#: IDF/Form/PasswordInputKey.php:36 IDF/Form/PasswordReset.php:39 +#: IDF/Form/UserChangeEmail.php:36 +msgid "Your verification key" +msgstr "" + +#: IDF/Form/PasswordInputKey.php:50 IDF/Form/PasswordReset.php:89 +msgid "" +"We are sorry but this validation key is not valid. Maybe you should directly " +"copy/paste it from your validation email." +msgstr "" + +#: IDF/Form/PasswordInputKey.php:61 IDF/Form/PasswordReset.php:100 +msgid "" +"Sorry, but this verification key has expired, please restart the password " +"recovery sequence. For security reasons, the verification key is only valid " +"24h." +msgstr "" + +#: IDF/Form/PasswordInputKey.php:76 IDF/Form/PasswordReset.php:108 +#: IDF/Form/RegisterConfirmation.php:137 IDF/Form/RegisterInputKey.php:72 +msgid "Cannot save an invalid form." +msgstr "" + +#: IDF/Form/PasswordReset.php:45 IDF/Form/RegisterConfirmation.php:69 +#: IDF/Form/UserAccount.php:77 +msgid "Your password" +msgstr "" + +#: IDF/Form/PasswordReset.php:48 IDF/Form/UserAccount.php:80 +msgid "" +"Your password must be hard for other people to find it, but easy for you to " +"remember." +msgstr "" + +#: IDF/Form/PasswordReset.php:56 IDF/Form/RegisterConfirmation.php:80 +#: IDF/Form/UserAccount.php:89 +msgid "Confirm your password" +msgstr "" + +#: IDF/Form/PasswordReset.php:74 IDF/Form/RegisterConfirmation.php:122 +msgid "The two passwords must be the same." +msgstr "" + +#: IDF/Form/PasswordReset.php:77 +msgid "" +"This account is not active. Please contact the forge administrator to " +"activate it." +msgstr "" + +#: IDF/Form/ProjectConf.php:43 +msgid "Short Description" +msgstr "" + +#: IDF/Form/ProjectConf.php:85 +msgid "The \"upload_path\" configuration variable was not set." +msgstr "" + +#: IDF/Form/ProjectConf.php:90 +msgid "Update the logo" +msgstr "" + +#: IDF/Form/ProjectConf.php:92 +msgid "The logo must be a picture with a size of 32 by 32." +msgstr "" + +#: IDF/Form/ProjectConf.php:103 +msgid "Remove the current logo" +msgstr "" + +#: IDF/Form/ProjectConf.php:139 +msgid "Could not determine the size of the uploaded picture." +msgstr "" + +#: IDF/Form/ProjectConf.php:143 +msgid "The picture must have a size of 32 by 32." +msgstr "" + +#: IDF/Form/ProjectConf.php:164 +msgid "The entered URL is invalid. Only http and https URLs are allowed." +msgstr "" + +#: IDF/Form/Register.php:41 +msgid "Your login" +msgstr "" + +#: IDF/Form/Register.php:45 +msgid "" +"The login must be between 3 and 15 characters long and contain only letters " +"and digits." +msgstr "" + +#: IDF/Form/Register.php:53 IDF/Form/UserAccount.php:59 +msgid "Your email" +msgstr "" + +#: IDF/Form/Register.php:55 +msgid "We will never send you any unsolicited emails. We hate spam too!" +msgstr "" + +#: IDF/Form/Register.php:60 +msgid "I agree to the terms and conditions." +msgstr "" + +#: IDF/Form/Register.php:88 +msgid "" +"We know, this is boring, but you need to agree with the terms and conditions." +msgstr "" + +#: IDF/Form/Register.php:97 +#, php-format +msgid "" +"The email \"%1$s\" is already used. If you need to, you can recover your password." +msgstr "" + +#: IDF/Form/Register.php:148 +msgid "Confirm the creation of your account." +msgstr "" + +#: IDF/Form/RegisterConfirmation.php:40 IDF/Form/RegisterInputKey.php:36 +msgid "Your confirmation key" +msgstr "" + +#: IDF/Form/RegisterConfirmation.php:72 +msgid "" +"Your password must be hard for other people to guess, but easy for you to " +"remember." +msgstr "" + +#: IDF/Form/RegisterConfirmation.php:99 IDF/Form/RegisterInputKey.php:50 +msgid "" +"We are sorry but this confirmation key is not valid. Maybe you should " +"directly copy/paste it from your confirmation email." +msgstr "" + +#: IDF/Form/RegisterConfirmation.php:110 +#, php-format +msgid "" +"This account has already been confirmed. Maybe should you try to recover your password." +msgstr "" + +#: IDF/Form/ReviewCreate.php:74 +#: IDF/gettexttemplates/idf/source/base.html.php:5 +#: IDF/gettexttemplates/idf/source/changelog.html.php:7 +msgid "Commit" +msgstr "" + +#: IDF/Form/ReviewCreate.php:92 +msgid "Patch" +msgstr "" + +#: IDF/Form/ReviewCreate.php:119 +msgid "We were not able to parse your patch. Please provide a valid patch." +msgstr "" + +#: IDF/Form/ReviewCreate.php:128 +msgid "You provided an invalid commit." +msgstr "" + +#: IDF/Form/ReviewCreate.php:202 +msgid "Initial patch to be reviewed." +msgstr "" + +#: IDF/Form/ReviewFileComment.php:56 +msgid "General comment" +msgstr "" + +#: IDF/Form/ReviewFileComment.php:113 +msgid "" +"You need to provide your general comment about the proposal, or comments on " +"at least one file." +msgstr "" + +#: IDF/Form/ReviewFileComment.php:124 +msgid "The status have been updated." +msgstr "" + +#: IDF/Form/ReviewFileComment.php:130 +msgid "This field is required." +msgstr "" + +#: IDF/Form/SourceConf.php:54 IDF/Form/UploadConf.php:70 +msgid "Webhook URL" +msgstr "" + +#: IDF/Form/TabsConf.php:38 IDF/gettexttemplates/idf/admin/base.html.php:4 +#: IDF/gettexttemplates/idf/base-full.html.php:8 +#: IDF/gettexttemplates/idf/base-full.html~.php:7 +#: IDF/gettexttemplates/idf/base.html.php:8 +#: IDF/gettexttemplates/idf/base.html~.php:7 +#: IDF/gettexttemplates/idf/downloads/base.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:14 +#: IDF/Views/Project.php:97 +msgid "Downloads" +msgstr "" + +#: IDF/Form/TabsConf.php:39 IDF/gettexttemplates/idf/base-full.html.php:12 +#: IDF/gettexttemplates/idf/base-full.html~.php:11 +#: IDF/gettexttemplates/idf/base.html.php:12 +#: IDF/gettexttemplates/idf/base.html~.php:11 +msgid "Code Review" +msgstr "" + +#: IDF/Form/TabsConf.php:40 IDF/gettexttemplates/idf/admin/base.html.php:5 +#: IDF/gettexttemplates/idf/base-full.html.php:9 +#: IDF/gettexttemplates/idf/base-full.html~.php:8 +#: IDF/gettexttemplates/idf/base.html.php:9 +#: IDF/gettexttemplates/idf/base.html~.php:8 +msgid "Documentation" +msgstr "" + +#: IDF/Form/TabsConf.php:41 IDF/gettexttemplates/idf/admin/base.html.php:7 +#: IDF/gettexttemplates/idf/base-full.html.php:11 +#: IDF/gettexttemplates/idf/base-full.html~.php:10 +#: IDF/gettexttemplates/idf/base.html.php:11 +#: IDF/gettexttemplates/idf/base.html~.php:10 +msgid "Source" +msgstr "" + +#: IDF/Form/TabsConf.php:42 IDF/gettexttemplates/idf/base-full.html.php:10 +#: IDF/gettexttemplates/idf/base-full.html~.php:9 +#: IDF/gettexttemplates/idf/base.html.php:10 +#: IDF/gettexttemplates/idf/base.html~.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:17 +msgid "Issues" +msgstr "" + +#: IDF/Form/TabsConf.php:50 +msgid "Open to all" +msgstr "" + +#: IDF/Form/TabsConf.php:51 +msgid "Signed in users" +msgstr "" + +#: IDF/Form/TabsConf.php:54 +msgid "Closed" +msgstr "" + +#: IDF/Form/TabsConf.php:84 +#, fuzzy +msgid "Others" +msgstr "Ostatní" + +#: IDF/Form/TabsConf.php:107 +msgid "Extra authorized users" +msgstr "" + +#: IDF/Form/Upload.php:59 IDF/Form/WikiResourceCreate.php:65 +#: IDF/Form/WikiResourceUpdate.php:56 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:7 +#: IDF/Views/Download.php:64 IDF/Views/Download.php:346 +msgid "File" +msgstr "" + +#: IDF/Form/Upload.php:87 IDF/Form/WikiResourceCreate.php:96 +#: IDF/Form/WikiResourceUpdate.php:83 +msgid "For security reasons, you cannot upload a file with this extension." +msgstr "" + +#: IDF/Form/Upload.php:120 +#, php-format +msgid "You cannot provide more than one label from the %s class to a download." +msgstr "" + +#: IDF/Form/UploadArchive.php:41 +#, fuzzy +msgid "Archive file" +msgstr "Archív" + +#: IDF/Form/UploadArchive.php:67 +#, php-format +msgid "" +"For security reasons, you cannot upload a file (%s) with this extension." +msgstr "" + +#: IDF/Form/UploadArchive.php:98 +#, php-format +msgid "" +"You cannot provide more than label from the %1$s class to a download (%2$s)." +msgstr "" + +#: IDF/Form/UploadArchive.php:109 +#, php-format +msgid "" +"A file with the name \"%s\" has already been uploaded and is not marked to " +"be replaced." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:41 +msgid "The archive does not exist." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:48 +#, php-format +msgid "The archive could not be read (code %d)." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:53 +msgid "The archive does not contain a manifest.xml." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:61 +#, php-format +msgid "The archive's manifest is invalid: %s" +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:77 +#, php-format +msgid "The entry %d in the manifest is missing a file name." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:82 +#, php-format +msgid "The entry %d in the manifest is missing a summary." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:86 +msgid "The manifest must not reference itself." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:91 +#, php-format +msgid "The entry %s in the manifest does not exist in the archive." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:96 +#, php-format +msgid "The entry %s in the manifest is referenced more than once." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:108 +#, php-format +msgid "The entry %s in the manifest has more than the six allowed labels set." +msgstr "" + +#: IDF/Form/UploadConf.php:53 +msgid "Predefined download labels" +msgstr "" + +#: IDF/Form/UploadConf.php:62 +msgid "Each download may have at most one label with each of these classes" +msgstr "" + +#: IDF/Form/UserAccount.php:61 +msgid "" +"If you change your email address, an email will be sent to the new address " +"to confirm it." +msgstr "" + +#: IDF/Form/UserAccount.php:80 +msgid "Leave blank if you do not want to change your password." +msgstr "" + +#: IDF/Form/UserAccount.php:166 +msgid "" +"Paste an SSH or monotone public key. Be careful to not provide your private " +"key here!" +msgstr "" + +#: IDF/Form/UserAccount.php:171 +msgid "Add a secondary email address" +msgstr "" + +#: IDF/Form/UserAccount.php:173 +msgid "You will get an email to confirm that you own the address you specify." +msgstr "" + +#: IDF/Form/UserAccount.php:200 +msgid "Confirm your new email address." +msgstr "" + +#: IDF/Form/UserAccount.php:203 +#, php-format +msgid "" +"A validation email has been sent to \"%s\" to validate the email address " +"change." +msgstr "" + +#: IDF/Form/UserAccount.php:341 +msgid "" +"Please check the key as it does not appear to be a valid SSH public key." +msgstr "" + +#: IDF/Form/UserAccount.php:363 +msgid "" +"Please check the key as it does not appear to be a valid monotone public key." +msgstr "" + +#: IDF/Form/UserAccount.php:371 +msgid "Public key looks like neither an SSH nor monotone public key." +msgstr "" + +#: IDF/Form/UserAccount.php:383 +msgid "You already have uploaded this key." +msgstr "" + +#: IDF/Form/UserChangeEmail.php:63 +msgid "" +"The validation key is not valid. Please copy/paste it from your confirmation " +"email." +msgstr "" + +#: IDF/Form/WikiConf.php:49 +msgid "Predefined documentation page labels" +msgstr "" + +#: IDF/Form/WikiConf.php:58 +msgid "" +"Each documentation page may have at most one label with each of these classes" +msgstr "" + +#: IDF/Form/WikiPageCreate.php:38 +msgid "" +"# Introduction\n" +"\n" +"Add your content here.\n" +"\n" +"\n" +"# Details\n" +"\n" +"Add your content here. Format your content with:\n" +"\n" +"* Text in **bold** or *italic*.\n" +"* Headings, paragraphs, and lists.\n" +"* Links to other [[WikiPage]].\n" +msgstr "" + +#: IDF/Form/WikiPageCreate.php:57 +msgid "PageName" +msgstr "" + +#: IDF/Form/WikiPageCreate.php:60 IDF/Form/WikiPageUpdate.php:50 +msgid "Page title" +msgstr "" + +#: IDF/Form/WikiPageCreate.php:66 IDF/Form/WikiPageUpdate.php:56 +msgid "" +"The page name must contains only letters, digits and the dash (-) character." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:71 IDF/Form/WikiPageUpdate.php:61 +msgid "This one line description is displayed in the list of pages." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:108 IDF/Form/WikiPageUpdate.php:119 +#: IDF/Form/WikiResourceCreate.php:78 +msgid "The title contains invalid characters." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:114 IDF/Form/WikiPageUpdate.php:125 +msgid "A page with this title already exists." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:150 IDF/Form/WikiPageUpdate.php:161 +#, php-format +msgid "You cannot provide more than one label from the %s class to a page." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:200 +msgid "Initial page creation" +msgstr "" + +#: IDF/Form/WikiPageDelete.php:39 +msgid "Yes, I understand that the page and all its revisions will be deleted." +msgstr "" + +#: IDF/Form/WikiPageDelete.php:50 IDF/Form/WikiResourceDelete.php:50 +msgid "You need to confirm the deletion." +msgstr "" + +#: IDF/Form/WikiPageUpdate.php:83 IDF/Form/WikiResourceUpdate.php:67 +msgid "One line to describe the changes you made." +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:40 +msgid "ResourceName" +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:44 +msgid "Resource title" +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:50 +#, fuzzy +msgid "" +"The resource name must contains only letters, digits and the dash (-) " +"character." +msgstr "" +"Nadpis musí obsahovat pouze písmena, čísla nebo pomlčku. Např. Moje-nova-" +"WiKi-Stranka." + +#: IDF/Form/WikiResourceCreate.php:55 IDF/Form/WikiResourceUpdate.php:47 +#, fuzzy +msgid "This one line description is displayed in the list of resources." +msgstr "Jednořádkový popis projektu." + +#: IDF/Form/WikiResourceCreate.php:84 +msgid "A resource with this title already exists." +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:142 +msgid "Initial resource creation" +msgstr "" + +#: IDF/Form/WikiResourceDelete.php:39 +msgid "" +"Yes, I understand that the resource and all its revisions will be deleted." +msgstr "" + +#: IDF/Form/WikiResourceUpdate.php:89 +#, php-format +msgid "" +"The mime type of the uploaded file \"%1$s\" does not match the mime type of " +"this resource \"%2$s\"" +msgstr "" + +#: IDF/Form/WikiResourceUpdate.php:97 +msgid "The current version of the resource and the uploaded file are equal." +msgstr "" + +#: IDF/Gconf.php:60 IDF/Search/Occ.php:56 +msgid "model class" +msgstr "třída modelu" + +#: IDF/Gconf.php:66 IDF/Search/Occ.php:62 +msgid "model id" +msgstr "id modelu" + +#: IDF/gettexttemplates/idf/admin/base.html.php:3 +msgid "Project Summary" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/base.html.php:6 +msgid "Issue Tracking" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/base.html.php:8 +msgid "Project Members" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/base.html.php:9 +msgid "Tabs Access and Notifications" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:3 +#: IDF/gettexttemplates/idf/admin/issue-tracking.html.php:3 +#: IDF/gettexttemplates/idf/admin/wiki.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/labels.html.php:3 +msgid "" +"\n" +"

Instructions:

\n" +"

List one status value per line in desired sort-order.

\n" +"

Optionally, use an equals-sign to document the meaning of each status " +"value.

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:8 +msgid "" +"

The webhook URL setting specifies an URL to which a HTTP PUT\n" +"request is sent after a new download has been added or to which a HTTP " +"POST\n" +"request is sent after an existing download has been updated.\n" +"If this field is empty, notifications are disabled.

\n" +"\n" +"

Only properly-escaped HTTP URLs are supported, for " +"example:

\n" +"\n" +"
    \n" +"
  • http://domain.com/upload
  • \n" +"
  • http://domain.com/upload?my%20param
  • \n" +"
\n" +"\n" +"

In addition, the URL may contain the following \"%\" notation, which\n" +"will be replaced with specific project values for each download:

\n" +"\n" +"
    \n" +"
  • %p - project name
  • \n" +"
  • %d - download id
  • \n" +"
\n" +"\n" +"

For example, updating download 123 of project 'my-project' with\n" +"web hook URL http://mydomain.com/%p/%d would send a POST " +"request to\n" +"http://mydomain.com/my-project/123.

" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:31 +#: IDF/gettexttemplates/idf/admin/source.html.php:30 +msgid "Web-Hook authentication key:" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:32 +#: IDF/gettexttemplates/idf/admin/issue-tracking.html.php:8 +#: IDF/gettexttemplates/idf/admin/members.html.php:13 +#: IDF/gettexttemplates/idf/admin/source.html.php:31 +#: IDF/gettexttemplates/idf/admin/summary.html.php:11 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:12 +#: IDF/gettexttemplates/idf/admin/wiki.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/forge/index.html.php:13 +#: IDF/gettexttemplates/idf/gadmin/projects/labels.html.php:8 +msgid "Save Changes" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/members.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:3 +msgid "" +"\n" +"

Instructions:

\n" +"

Specify each person by its login. Each person must have already " +"registered with the given login.

\n" +"

Separate the logins with commas and/or new lines.

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/members.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:8 +msgid "" +"\n" +"

Notes:

\n" +"

A project owner may make any change to this project, including removing " +"other project owners. You need to be carefull when you give owner rights.\n" +"

A project member will not have access to the administration area but will " +"have more options available in the use of the project.

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:3 +msgid "You can find here the current repository configuration of your project." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:4 +msgid "" +"

The webhook URL setting specifies an URL to which a HTTP \n" +"%%hook_request_method%% request is sent after each " +"repository\n" +"commit. If this field is empty, notifications are disabled.

\n" +"\n" +"

Only properly-escaped HTTP URLs are supported, for " +"example:

\n" +"\n" +"
    \n" +"
  • http://domain.com/commit
  • \n" +"
  • http://domain.com/commit?my%20param
  • \n" +"
\n" +"\n" +"

In addition, the URL may contain the following \"%\" notation, which\n" +"will be replaced with specific project values for each commit:

\n" +"\n" +"
    \n" +"
  • %p - project name
  • \n" +"
  • %r - revision number
  • \n" +"
\n" +"\n" +"

For example, committing revision 123 to project 'my-project' with\n" +"post-commit URL http://mydomain.com/%p/%r would send a request " +"to\n" +"http://mydomain.com/my-project/123.

" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:26 +msgid "" +"The form contains some errors. Please correct them to update the source " +"configuration." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:27 +msgid "Repository type:" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:28 +msgid "Repository access:" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:29 +msgid "Repository size:" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

The description of the project can be improved using the Markdown syntax.

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:7 +msgid "" +"The form contains some errors. Please correct them to update the summary." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:8 +msgid "Current logo" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:9 +#: IDF/gettexttemplates/idf/base-full.html.php:4 +#: IDF/gettexttemplates/idf/base-full.html~.php:4 +#: IDF/gettexttemplates/idf/base.html.php:4 +#: IDF/gettexttemplates/idf/base.html~.php:4 +#: IDF/gettexttemplates/idf/main-menu.html.php:8 +#: IDF/gettexttemplates/idf/project-list.html.php:4 +msgid "Project logo" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:10 +msgid "Your project does not have a logo configured yet." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:3 +msgid "" +"This section allows you to configure project tabs access rights and " +"notifications." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:4 +msgid "" +"Tab access controls whether a single user can navigate into a particular " +"section of your project via the main menu or automatically generated object " +"links." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:5 +msgid "" +"If you mark a project as private, only the project members and " +"administrators, together with the extra authorized users you provide will " +"have access to the project as a whole. You will still be able to define " +"further access rights for the different tabs but the \"Open to all\" and " +"\"Signed in users\" will default to authorized users only." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:6 +msgid "" +"For the extra authorized user list, specify each person by its login. Each " +"person must have already registered with the given login. Separate the " +"logins with commas and/or new lines." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:7 +msgid "" +"Only project members and admins have write access to the source. If you " +"restrict the access to the source, anonymous access is not provided and the " +"users must authenticate themselves with their password or SSH key." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:8 +#, php-format +msgid "" +"Here you can configure who should be notified about changes in a particular " +"section. You can also configure additional addresses, like the one of a " +"mailing list, that should be notified. (Keep in mind that you might have to " +"register the sender address %%from_email%% to let the " +"mailing list actually accept notification emails.) Multiple email addresses " +"must be separated through commas (',')." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:9 +msgid "" +"The form contains some errors. Please correct them to update the access " +"rights." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:10 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:13 +msgid "Access Rights" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:11 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:14 +#, fuzzy +msgid "Notifications" +msgstr "datum změny" + +#: IDF/gettexttemplates/idf/base-full.html.php:3 +#: IDF/gettexttemplates/idf/base-full.html~.php:3 +#: IDF/gettexttemplates/idf/base.html.php:3 +#: IDF/gettexttemplates/idf/base.html~.php:3 +#, php-format +msgid "" +"Sign in or create your account to create issues or " +"add comments" +msgstr "" + +#: IDF/gettexttemplates/idf/base-full.html.php:6 +#: IDF/gettexttemplates/idf/base.html.php:6 +#: IDF/gettexttemplates/idf/project-list.html.php:6 +msgid "External link to project" +msgstr "" + +#: IDF/gettexttemplates/idf/base-full.html.php:7 +#: IDF/gettexttemplates/idf/base-full.html~.php:6 +#: IDF/gettexttemplates/idf/base.html.php:7 +#: IDF/gettexttemplates/idf/base.html~.php:6 +msgid "Project Home" +msgstr "" + +#: IDF/gettexttemplates/idf/base-full.html.php:13 +#: IDF/gettexttemplates/idf/base-full.html~.php:12 +#: IDF/gettexttemplates/idf/base.html.php:13 +#: IDF/gettexttemplates/idf/base.html~.php:12 +msgid "Project Management" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/base.html.php:4 +#: IDF/gettexttemplates/idf/downloads/index.html.php:4 +#: IDF/Views/Download.php:235 +msgid "New Download" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/base.html.php:5 +#, fuzzy +msgid "Upload Archive" +msgstr "Archív" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:3 +msgid "" +"Each file must have a distinct name and file contents\n" +"cannot be changed, so be sure to include release numbers in each file\n" +"name." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:6 +#, php-format +msgid "" +"You can use the Markdown syntax for the description." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:7 +msgid "The form contains some errors. Please correct them to submit the file." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:8 +msgid "Submit File" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:9 +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:8 +#: IDF/gettexttemplates/idf/downloads/delete.html.php:7 +#: IDF/gettexttemplates/idf/downloads/view.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:21 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:14 +#: IDF/gettexttemplates/idf/issues/create.html.php:14 +#: IDF/gettexttemplates/idf/issues/view.html.php:27 +#: IDF/gettexttemplates/idf/register/confirmation.html.php:7 +#: IDF/gettexttemplates/idf/register/index.html.php:8 +#: IDF/gettexttemplates/idf/register/inputkey.html.php:5 +#: IDF/gettexttemplates/idf/review/create.html.php:12 +#: IDF/gettexttemplates/idf/review/view.html.php:41 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:5 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:13 +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:7 +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:9 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:5 +msgid "Cancel" +msgstr "Storno" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:10 +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:9 +#: IDF/gettexttemplates/idf/register/inputkey.html.php:6 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:6 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:6 +msgid "Instructions" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:3 +msgid "" +"The archive must include a manifest.xml file with meta " +"information about the\n" +"files to process inside the archive. All processed files must be unique or " +"replace existing files explicitely." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:5 +#, php-format +msgid "" +"You can learn more about the archive format here." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:6 +#, fuzzy +msgid "" +"The form contains some errors. Please correct them to submit the archive." +msgstr "" +"Formulář obsahuje nějaké chyby. Prosím opravte je a poté odešlete předmět k " +"řešení." + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:7 +#, fuzzy +msgid "Submit Archive" +msgstr "Archív" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:3 +msgid "" +"Attention! If you want to delete a specific version of your " +"software, maybe, someone is depending on this specific version to run his " +"systems. Are you sure, you will not affect anybody when removing this file?" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:4 +#, php-format +msgid "" +"Instead of deleting the file, you could mark it as " +"deprecated." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:5 +#: IDF/gettexttemplates/idf/downloads/view.html.php:4 +#: IDF/gettexttemplates/idf/issues/attachment.html.php:4 +#: IDF/gettexttemplates/idf/issues/view.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:5 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:7 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:7 +#, php-format +msgid "by %%submitter%%" +msgstr "kým %%submitter%%" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:6 +msgid "Delete File" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:8 +#: IDF/gettexttemplates/idf/downloads/view.html.php:14 +msgid "Uploaded:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:9 +#: IDF/gettexttemplates/idf/downloads/view.html.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:29 +#: IDF/gettexttemplates/idf/review/view.html.php:27 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:12 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:14 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:14 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:15 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:17 +msgid "Updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:10 +#: IDF/gettexttemplates/idf/downloads/view.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:6 +#: IDF/gettexttemplates/idf/listProjects.html.php:17 +msgid "Downloads:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:11 +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:7 +#: IDF/gettexttemplates/idf/downloads/view.html.php:17 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:6 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:6 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:11 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:16 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:10 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:21 +#: IDF/gettexttemplates/idf/issues/view.html.php:33 +#: IDF/gettexttemplates/idf/project-list.html.php:8 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:6 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:13 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:16 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:12 +#: IDF/IssueComment.php:157 IDF/Wiki/PageRevision.php:204 +msgid "Labels:" +msgstr "Nálepky:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:3 +msgid "A new file is available for download:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:4 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:6 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:5 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:8 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:4 +msgid "Hello," +msgstr "Ahoj," + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:6 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:5 +msgid "Project:" +msgstr "Projekt:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:6 +msgid "Submitted by:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:8 +msgid "Download:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/view.html.php:31 +#: IDF/gettexttemplates/idf/user/public.html.php:4 +msgid "Description:" +msgstr "Popis:" + +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:3 +msgid "A file download was updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/feedfragment.xml.php:3 +msgid "Details" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/index.html.php:3 +#, php-format +msgid "See the deprecated files." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/index.html.php:5 +msgid "Number of files:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:3 +msgid "" +"Attention! This file is marked as deprecated, download it " +"only if you are sure you need this specific version." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:5 +msgid "md5:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:6 +msgid "Changes" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:7 +msgid "The form contains some errors. Please correct them to update the file." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:8 +msgid "Update File" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:10 +#: IDF/gettexttemplates/idf/downloads/view.html.php:12 +msgid "Remove this file" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:11 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:18 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:7 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:12 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:12 +msgid "Trash" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:13 +msgid "Delete this file" +msgstr "" + +#: IDF/gettexttemplates/idf/faq-api.html.php:3 +#: IDF/gettexttemplates/idf/faq-archive-format.html.php:3 +#: IDF/gettexttemplates/idf/faq.html.php:65 +msgid "Here we are, just to help you." +msgstr "" + +#: IDF/gettexttemplates/idf/faq-api.html.php:4 +#: IDF/gettexttemplates/idf/faq-archive-format.html.php:4 +#: IDF/gettexttemplates/idf/faq.html.php:66 +#: IDF/gettexttemplates/idf/gadmin/base.html.php:4 +#: IDF/gettexttemplates/idf/index.html.php:4 IDF/Views/Admin.php:77 +#: IDF/Views.php:91 +msgid "Projects" +msgstr "Projekty" + +#: IDF/gettexttemplates/idf/faq.html.php:3 +msgid "" +"

This is simple:

\n" +"
    \n" +"
  1. Write in the comments \"This is a duplicate of issue 123\" or - if you " +"are a member of the crew -\n" +"directly add the \"duplicates\" relation with the value \"123\" below the " +"comment field. Change \"123\"\n" +"with the corresponding issue number.
  2. \n" +"
  3. Change the status of the current issue to Duplicate.
  4. \n" +"
  5. Submit the changes.
  6. \n" +"
" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:11 +msgid "" +"You need to create an account on Gravatar, this takes about 5 minutes and is free." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:12 +msgid "" +"\n" +"

To embed any previously uploaded resource into your wiki page, you can " +"use the [[!ResourceName]] syntax.

\n" +"\n" +"

The rendering of the resource can then be further fine-tuned:\n" +"

    \n" +"
  • [[!ImageResource, align=right, width=200]] renders " +"\"ImageResource\" right-aligned and scale its width to 200
  • \n" +"
  • [[!TextResource, align=center, width=300, height=300]] " +"renders \"TextResource\" in a centered, 300 by 300 px iframe
  • \n" +"
  • [[!AnyResource, preview=no]] does not render a preview of " +"the resource, but only provides a download link (default for binary " +"resources)
  • \n" +"
  • [[!BinaryResource, title=Download]] renders the download " +"link of \"BinaryResource\" with an alternative title
  • \n" +"
\n" +"

\n" +"\n" +"Resources are versioned, just like wiki pages. If you update a resource, old " +"wiki pages still show the state of the resource\n" +"at the time when the wiki page was edited. If you specifically want to " +"update a resource on a page, you therefor need to update\n" +"the resource at first and then also the page where it is referenced, " +"otherwise the change won't be visible until the next regular edit. \n" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:28 +msgid "" +"

If you have to publish many files at once for a new release, it is a very " +"tedious task\n" +"to upload them one after another and enter meta information like a summary, " +"a description or additional\n" +"labels for each of them.

\n" +"

InDefero therefore supports a special archive format that is basically a " +"standard zip file which comes with\n" +"some meta information. These meta information are kept in a special manifest " +"file, which is distinctly kept from\n" +"the rest of the files in the archive that should be published.

\n" +"

Once this archive has been uploaded, InDefero reads in the meta " +"information, unpacks the other files from\n" +"the archive and creates new individual downloads for each of them.

" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:36 +#, fuzzy, php-format +msgid "Learn more about the archive format." +msgstr "Přihlásit se pro odpověď na tento komentář." + +#: IDF/gettexttemplates/idf/faq.html.php:37 +msgid "" +"The API (Application Programming Interface) is used to interact with " +"InDefero with another program. For example, this can be used to create a " +"desktop program to submit new tickets easily." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:38 +#, php-format +msgid "Learn more about the API." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:39 +#: IDF/gettexttemplates/idf/faq.html.php:45 +msgid "What are the keyboard shortcuts?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:40 +#: IDF/gettexttemplates/idf/faq.html.php:60 +msgid "How to mark an issue as duplicate?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:41 +#: IDF/gettexttemplates/idf/faq.html.php:61 +msgid "How can I display my head next to my comments?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:42 +#: IDF/gettexttemplates/idf/faq.html.php:62 +msgid "How can I embed images and other resources in my documentation pages?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:43 +#: IDF/gettexttemplates/idf/faq.html.php:63 +msgid "What is this \"Upload Archive\" functionality about?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:44 +#: IDF/gettexttemplates/idf/faq.html.php:64 +msgid "What is the API and how is it used?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:46 +msgid "Shift+h: This help page." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:47 +msgid "If you are in a project, you have the following shortcuts:" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:48 +msgid "Shift+u: Project updates." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:49 +msgid "Shift+d: Downloads." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:50 +msgid "Shift+o: Documentation." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:51 +msgid "Shift+a: Create a new issue." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:52 +msgid "Shift+i: List of open issues." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:53 +msgid "Shift+m: The issues you submitted." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:54 +msgid "Shift+w: The issues assigned to you." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:55 +msgid "Shift+s: Source." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:56 +msgid "You also have the standard access keys:" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:57 +msgid "Alt+1: Home." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:58 +msgid "Alt+2: Skip the menus." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:59 +msgid "Alt+4: Search (when available)." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:3 +msgid "Forge" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:5 +msgid "People" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:6 +msgid "Usher" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/forge/base.html.php:3 +#, fuzzy +msgid "Frontpage" +msgstr "stránka" + +#: IDF/gettexttemplates/idf/gadmin/forge/index.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

You can set up a custom forge page that is used as entry page for the " +"forge instead of the plain project listing. This page is then also " +"accessible via the 'Home' link in main menu bar.

\n" +"

The content of the page can use the Markdown syntax with the Extra extension.

\n" +"

Additionally, the following macros are available:
\n" +"

    \n" +"
  • {projectlist, label=..., order=(name|activity), limit=...} - Renders a project list that can optionally be filtered by label, " +"ordered by 'name' or 'activity' and / or limited to a specific number of " +"projects.
  • \n" +"
\n" +"

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:3 +#: IDF/gettexttemplates/idf/main-menu.html.php:7 +msgid "Project List" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:4 +#: IDF/Views/Admin.php:110 +#, fuzzy +msgid "Project Labels" +msgstr "Projekty" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:16 +#: IDF/gettexttemplates/idf/listProjects.html.php:6 IDF/Views/Admin.php:186 +msgid "Create Project" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:6 +msgid "Change Project Details" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:3 +msgid "" +"You can select the type of repository you want. In the case of subversion, " +"you can use optionally a remote repository instead of the local one." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:4 +msgid "" +"Once you have defined the repository type, you cannot change it." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:5 +msgid "" +"\n" +"

Specify each person by its login. Each person must have already " +"registered with the given login.

\n" +"

Separate the logins with commas and/or new lines.

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:14 +msgid "" +"The form contains some errors. Please correct them to create the project." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:15 +msgid "Provide at least one owner for the project or use a template." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:15 +msgid "Instructions:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:3 +#, php-format +msgid "" +"Confirmation code to confirm the deletion of the project: \n" +"%%code%%." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:5 +msgid "" +"\n" +"Attention! Deleting a project is a one second operation\n" +"with the consequences that all the data related to the \n" +"project will be deleted.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:10 +msgid "" +"The form contains some errors. Please correct them to delete the project." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:11 +msgid "Project Statistics" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:12 +msgid "Tab" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:13 +msgid "Number" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:15 +msgid "Code reviews" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:16 +#: IDF/Views/Project.php:93 +msgid "Commits" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:18 +msgid "Documentation pages" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:19 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:20 +msgid "Delete Project" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:22 +msgid "" +"For large projects, the suppression can take a while, please be patient." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:3 +msgid "Space Usage Statistics" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:4 +msgid "Repositories:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:5 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:11 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:18 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:16 +msgid "Attachments:" +msgstr "Přílohy:" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:7 +msgid "Database:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:8 +msgid "Total Forge:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:13 +msgid "" +"The form contains some errors. Please correct them to update the project." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:14 +msgid "Provide at least one owner for the project." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:15 +msgid "Update Project" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:19 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:20 +msgid "Delete this project" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:21 +msgid "You will be asked to confirm." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:3 +#: IDF/Views/Admin.php:264 +msgid "User List" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:13 +msgid "Update User" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:4 +msgid "Create User" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:3 +msgid "The form contains some errors. Please correct them to create the user." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:6 +msgid "The user password will be sent by email to the user." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/createuser-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"An account on the forge has been created for you by\n" +"the administrator %%admin%%.\n" +"\n" +"Please find here your details to access the forge:\n" +"\n" +" Address: %%url%%\n" +" Login: %%user.login%%\n" +" Password: %%password%%\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:3 +#, php-format +msgid "See not validated users." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:4 +msgid "

You have here an overview of the users registered in the forge.

" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:5 +msgid "Number of users:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:3 +msgid "" +"If you are changing the email address of the user, you\n" +"need to ensure that you are providing a valid email\n" +"address" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:6 +msgid "" +"If you give the user staff rights, the user will be\n" +"able to create new projects and update other non staff users.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:9 +msgid "The form contains some errors. Please correct them to update the user." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:10 +#: IDF/gettexttemplates/idf/register/confirmation.html.php:4 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:4 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:4 +msgid "Login:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:11 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:5 +msgid "Public Profile" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:12 +msgid "Administrative" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/base.html.php:3 +msgid "Configured servers" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/base.html.php:4 +#: IDF/Views/Admin.php:421 +msgid "Usher control" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html~.php:3 +msgid "address" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html~.php:4 +msgid "port" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:5 +msgid "No connections found." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:3 +msgid "current server status:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:4 +msgid "startup" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:5 +msgid "shutdown" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:6 +msgid "reload server configuration:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:7 +msgid "reload" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:11 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:11 +msgid "Status explanation" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:9 +msgid "active with n total open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:10 +msgid "waiting for new connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:11 +msgid "usher is being shut down, not accepting connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:12 +msgid "" +"usher is shut down, all local servers are stopped and not accepting " +"connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:3 +msgid "server name" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:4 IDF/Issue.php:99 +#: IDF/Review.php:102 +msgid "status" +msgstr "status" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:5 +msgid "action" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:6 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:6 +msgid "No monotone servers configured." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:7 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:7 +msgid "stop" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:8 +msgid "start" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:9 +msgid "kill" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:10 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:10 +msgid "active connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:12 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:12 +msgid "remote server without open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:13 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:13 +msgid "server with n open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:14 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:14 +msgid "local server running, without open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:15 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:15 +msgid "local server not running, waiting for connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:16 +msgid "local server is about to stop, n connections still open" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:17 +msgid "local server not running, not accepting connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:18 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:18 +msgid "usher is shut down, not running and not accepting connections" +msgstr "" + +#: IDF/gettexttemplates/idf/index.atom.php:3 +#, php-format +msgid "Personal project feed for %%user%%." +msgstr "" + +#: IDF/gettexttemplates/idf/index.html.php:3 +#: IDF/gettexttemplates/idf/main-menu.html.php:6 +msgid "Home" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:3 +#, php-format +msgid "Attachment to issue %%issue.id%%" +msgstr "Příloha k předmětu %%issue.id%%" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:5 +#: IDF/gettexttemplates/idf/review/view.html.php:35 +#: IDF/gettexttemplates/idf/source/commit.html.php:23 +#: IDF/gettexttemplates/idf/source/commit.html~.php:22 +#: IDF/gettexttemplates/idf/source/git/file.html.php:6 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:7 +msgid "Archive" +msgstr "Archív" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:6 +#: IDF/gettexttemplates/idf/source/git/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:12 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:12 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:10 +msgid "Download this file" +msgstr "Stáhnout tento soubor" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:7 +#: IDF/gettexttemplates/idf/issues/view.html.php:28 +#: IDF/gettexttemplates/idf/review/view.html.php:26 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:13 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:14 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:16 +msgid "Created:" +msgstr "Vytvořeno:" + +#: IDF/gettexttemplates/idf/issues/base.html.php:4 +msgid "All Issues" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/base.html.php:5 +msgid "My Issues" +msgstr "Moje předmět k řešení" + +#: IDF/gettexttemplates/idf/issues/base.html.php:6 +msgid "My watch list" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/base.html.php:7 +#: IDF/gettexttemplates/idf/issues/by-label.html.php:6 +#: IDF/gettexttemplates/idf/issues/index.html.php:5 +#: IDF/gettexttemplates/idf/issues/project-watchlist.html.php:5 +#: IDF/gettexttemplates/idf/issues/search.html.php:8 +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:5 +msgid "New Issue" +msgstr "Nový předmět k řešení" + +#: IDF/gettexttemplates/idf/issues/base.html.php:8 +#: IDF/gettexttemplates/idf/wiki/base.html.php:9 +msgid "Search" +msgstr "Hledat" + +#: IDF/gettexttemplates/idf/issues/base.html.php:9 +msgid "Back to the issue" +msgstr "Zpátky k předmětu" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:3 +#, php-format +msgid "" +"

Open issues: %%open%%

\n" +"

Closed issues: %%closed%%

\n" +msgstr "" +"

Otevřené předměty k řešení: " +"%%open%%

\n" +"

Zavřené předměty k řešení: " +"%%closed%%

\n" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:7 +msgid "Label:" +msgstr "Nálepka:" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:8 +msgid "Completion:" +msgstr "Doplňování:" + +#: IDF/gettexttemplates/idf/issues/create.html.php:3 +msgid "" +"

When you submit the issue do not forget to provide the following " +"information:

\n" +"
    \n" +"
  • The steps to reproduce the problem.
  • \n" +"
  • The version of the software and your operating system.
  • \n" +"
  • Any information that can help the developers to solve the issue.
  • \n" +"
  • Do not provide any password or confidential information!
  • \n" +"
" +msgstr "" +"

Před odesláním předmetu k řešení, nezapomeňte poskytnout následující " +"informace:

\n" +"
    \n" +"
  • Kroky potřebné pro zopakování problému.
  • \n" +"
  • Verzi softwaru a typ operačního systému, který používate.
  • \n" +"
  • Jakákoli informace, která může pomoci vývojářům vyřešit problém.
  • \n" +"
  • Neposkytujte žádná hesla ani jiné citlivé informace!\n" +"
" + +#: IDF/gettexttemplates/idf/issues/create.html.php:10 +msgid "The form contains some errors. Please correct them to submit the issue." +msgstr "" +"Formulář obsahuje nějaké chyby. Prosím opravte je a poté odešlete předmět k " +"řešení." + +#: IDF/gettexttemplates/idf/issues/create.html.php:11 +#: IDF/gettexttemplates/idf/issues/create.html.php:13 +#: IDF/gettexttemplates/idf/issues/view.html.php:24 +#: IDF/gettexttemplates/idf/issues/view.html.php:26 +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:5 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:5 +msgid "Preview" +msgstr "Náhled" + +#: IDF/gettexttemplates/idf/issues/create.html.php:12 +msgid "Submit Issue" +msgstr "Odeslat předmět k řešení" + +#: IDF/gettexttemplates/idf/issues/create.html.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:34 +msgid "Attach file" +msgstr "Přiložit soubor" + +#: IDF/gettexttemplates/idf/issues/create.html.php:16 +#: IDF/gettexttemplates/idf/issues/create.html.php:17 +#: IDF/gettexttemplates/idf/issues/view.html.php:35 +#: IDF/gettexttemplates/idf/issues/view.html.php:36 +msgid "Attach another file" +msgstr "Přiložit další soubor" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:3 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:3 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:13 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:12 +#: IDF/gettexttemplates/idf/issues/view.html.php:18 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:3 +#: IDF/gettexttemplates/idf/review/view.html.php:38 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:11 +#: IDF/IssueComment.php:151 +msgid "Summary:" +msgstr "Souhrn:" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:4 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:4 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:8 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:14 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:13 +#: IDF/gettexttemplates/idf/issues/view.html.php:19 +#: IDF/gettexttemplates/idf/issues/view.html.php:30 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:4 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/view.html.php:39 IDF/IssueComment.php:153 +msgid "Status:" +msgstr "Status:" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:5 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:15 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:14 +#: IDF/gettexttemplates/idf/issues/view.html.php:20 +#: IDF/gettexttemplates/idf/issues/view.html.php:31 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:5 +#: IDF/IssueComment.php:155 +msgid "Owner:" +msgstr "Vlastník:" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:17 +#: IDF/gettexttemplates/idf/issues/view.html.php:22 IDF/IssueComment.php:159 +msgid "Relations:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/forge-watchlist.html.php:3 +#: IDF/gettexttemplates/idf/issues/index.html.php:3 +#: IDF/gettexttemplates/idf/issues/project-watchlist.html.php:3 +#, php-format +msgid "" +"

Open issues: %%open%%

\n" +"

Closed issues: %%closed%%

" +msgstr "" +"

Otevřené předměty k řešení: " +"%%open%%

\n" +"

Zavřené předměty k řešení: " +"%%closed%%

" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:3 +#, fuzzy +msgid "A new issue has been created and assigned to you:" +msgstr "Nový předmět k řešení byl vytvořen a vám přiřazen:" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:4 +#, fuzzy +msgid "A new issue has been created:" +msgstr "Nový předmět k řešení byl vytvořen a vám přiřazen:" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:8 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:11 +msgid "Reported by:" +msgstr "Nahlášeno kým:" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:12 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:19 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:17 +msgid "Issue:" +msgstr "Předmět k řešení:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:3 +#, fuzzy +msgid "The following issue you are owning has been updated:" +msgstr "Následující předmět k řešení byl aktualizován:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:4 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:3 +msgid "The following issue has been updated:" +msgstr "Následující předmět k řešení byl aktualizován:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:4 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:4 +#, php-format +msgid "By %%who%%, %%c.creation_dtime%%:" +msgstr "Kým %%who%%, %%c.creation_dtime%%:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:10 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:9 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:12 +msgid "URL:" +msgstr "URL:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:12 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:11 +msgid "Comments (last first):" +msgstr "Komentář (poslední jako první):" + +#: IDF/gettexttemplates/idf/issues/search.html.php:3 +#, php-format +msgid "" +"\n" +"

Found open issues: %%open%%

\n" +"

Found closed issues: %%closed" +"%%

" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/search.html.php:6 +#, php-format +msgid "" +"

Label:\n" +"%%tag.class%%:" +"%%tag.name%%

" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:3 +msgid "View all open issues." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:4 +msgid "Create an issue." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:5 +#, php-format +msgid "" +"The issue tracker is empty.
Create your " +"first issue." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:6 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:4 +#, php-format +msgid "Unresolved: By %%key%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:7 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:5 +msgid "Status Summary" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:8 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:6 +msgid "Unresolved: By Assignee" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html~.php:3 +#, php-format +msgid "" +"The issue tracker is empty.
You can create your first issue here." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:3 +#, php-format +msgid "" +"See the %%nb_submit_closed%% closed." +msgid_plural "" +"See the %%nb_submit_closed%% closed." +msgstr[0] "" +"Zobrazit %%nb_submit_closed%% zavřené." +msgstr[1] "" +"Zobrazit %%nb_submit_closed%% zavřené." +msgstr[2] "" +"Zobrazit %%nb_submit_closed%% zavřené." + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:4 +#, php-format +msgid "" +"See the %%nb_owner_closed%% closed." +msgid_plural "" +"See the %%nb_owner_closed%% closed." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:6 +#: IDF/gettexttemplates/idf/user/dashboard.html.php:7 +msgid "Submitted issues:" +msgstr "Odeslané předměty k řešení:" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:7 +#: IDF/gettexttemplates/idf/user/dashboard.html.php:6 +msgid "Working issues:" +msgstr "Rozpracované předmět k řešení:" + +#: IDF/gettexttemplates/idf/issues/view.html.php:3 +#, php-format +msgid "Reported by %%submitter%%, %%c.creation_dtime%%" +msgstr "Nahlášeno kým %%submitter%%, %%c.creation_dtime%%" + +#: IDF/gettexttemplates/idf/issues/view.html.php:4 +#: IDF/gettexttemplates/idf/review/view.html.php:22 +#, php-format +msgid "" +"Comment %%i%% by %%submitter%%, %%c.creation_dtime%%" +msgstr "" +"Komentář %%i%% kým %%submitter%%, %%c.creation_dtime" +"%%" + +#: IDF/gettexttemplates/idf/issues/view.html.php:5 +#, php-format +msgid "Sign in to reply to this comment." +msgstr "Přihlásit se pro odpověď na tento komentář." + +#: IDF/gettexttemplates/idf/issues/view.html.php:6 +msgid "" +"This issue is marked as closed, add a comment only if you think this issue " +"is still valid and more work is needed to fully fix it." +msgstr "" +"Předmět je nahlášen jako uzavřený, přidejte komentář jen tehdy, pokud si " +"myslíte, že problém nebyl vyřešen a potřebuje další práci k jeho opravě." + +#: IDF/gettexttemplates/idf/issues/view.html.php:8 +#, php-format +msgid "%%interested%% person" +msgid_plural "%%interested%% persons" +msgstr[0] "%%interested%% osoba" +msgstr[1] "%%interested%% osoby" +msgstr[2] "%%interested%% osoby" + +#: IDF/gettexttemplates/idf/issues/view.html.php:9 +#, php-format +msgid "This issue %%verb%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:10 +msgid "Remove this issue from your watch list" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:11 +msgid "Add this issue to your watch list" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:12 +#, fuzzy +msgid "View the previous closed issue" +msgstr "Tato tabulka ukazuje uzavřené předměty k řešení." + +#: IDF/gettexttemplates/idf/issues/view.html.php:13 +msgid "View the previous open issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:14 +#, fuzzy +msgid "View the next closed issue" +msgstr "Tato tabulka ukazuje uzavřené předměty k řešení." + +#: IDF/gettexttemplates/idf/issues/view.html.php:15 +msgid "View the next open issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:16 +msgid "download" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:17 +msgid "view" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:23 +msgid "The form contains some errors. Please correct them to change the issue." +msgstr "" +"Formulář obsahuje nějaké chyby. Prosím opravte je ke změně předmětu k řešení." + +#: IDF/gettexttemplates/idf/issues/view.html.php:25 +msgid "Submit Changes" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:32 +msgid "Followed by:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:3 +#, fuzzy, php-format +msgid "1 project" +msgid_plural "%%label.project_count%% projects" +msgstr[0] "projekt" +msgstr[1] "projekt" +msgstr[2] "projekt" + +#: IDF/gettexttemplates/idf/listProjects.html.php:4 +#, php-format +msgid "Remove filter for %%tag%%" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:5 +msgid "No projects managed with InDefero were found." +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:7 +msgid "Filter projects by label" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:8 +#, fuzzy +msgid "No projects with labels found." +msgstr "Projekt \"%s\" nenalezen." + +#: IDF/gettexttemplates/idf/listProjects.html.php:9 +msgid "Order" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:10 +#, fuzzy +msgid "By name" +msgstr "jméno" + +#: IDF/gettexttemplates/idf/listProjects.html.php:11 +msgid "By activity" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:12 +msgid "Filtered project stats" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:13 +msgid "Members:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:14 +msgid "Issues:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:15 +msgid "Commits:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:16 +msgid "Documentations:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:18 +msgid "Code reviews:" +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:3 +#, php-format +msgid "" +"You can create an account if you don't have one yet." +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:4 +msgid "What is your account information?" +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:5 +msgid "My login is" +msgstr "Můj login je" + +#: IDF/gettexttemplates/idf/login_form.html.php:6 +msgid "My password is" +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:7 +msgid "Sign in" +msgstr "Přihlásit" + +#: IDF/gettexttemplates/idf/login_form.html.php:8 +msgid "I lost my password!" +msgstr "Ztratil jsem heslo!" + +#: IDF/gettexttemplates/idf/login_form.html.php:9 +msgid "Welcome." +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:10 +msgid "It takes less than a minute to create your account." +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:3 +#, php-format +msgid "" +"Welcome, %%user%%." +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:4 +msgid "Sign Out" +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:5 +msgid "Sign in or create your account" +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:10 IDF/Views/Admin.php:40 +msgid "Forge Management" +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:11 +msgid "Help and accessibility features" +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:12 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:14 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:14 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:15 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:13 +msgid "Help" +msgstr "" + +#: IDF/gettexttemplates/idf/project/home.html.php:3 +#: IDF/gettexttemplates/idf/project/timeline.html.php:4 IDF/Views.php:46 +msgid "Welcome" +msgstr "Vítejte" + +#: IDF/gettexttemplates/idf/project/home.html.php:4 +#: IDF/gettexttemplates/idf/project/timeline.html.php:5 +msgid "Latest Updates" +msgstr "Poslední změny" + +#: IDF/gettexttemplates/idf/project/home.html.php:5 +msgid "Featured Downloads" +msgstr "Doporučené soubory ke stažení" + +#: IDF/gettexttemplates/idf/project/home.html.php:6 +#, fuzzy +msgid "Show more featured downloads" +msgstr "Doporučené soubory ke stažení" + +#: IDF/gettexttemplates/idf/project/home.html.php:7 +#: IDF/gettexttemplates/idf/project/home.html.php:10 +msgid "show more..." +msgstr "zobrazit více.." + +#: IDF/gettexttemplates/idf/project/home.html.php:8 +msgid "Featured Documentation" +msgstr "Doporučená dokumentace" + +#: IDF/gettexttemplates/idf/project/home.html.php:9 +#, fuzzy +msgid "Show more featured documentation" +msgstr "Doporučená dokumentace" + +#: IDF/gettexttemplates/idf/project/home.html.php:11 +msgid "Development Team" +msgstr "Vývojářksý team" + +#: IDF/gettexttemplates/idf/project/home.html.php:12 +msgid "Admins" +msgstr "Administrátoři" + +#: IDF/gettexttemplates/idf/project/home.html.php:13 +msgid "Happy Crew" +msgstr "Šťastný team" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:3 +msgid "Latest updates" +msgstr "Poslední změny" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:6 +#: IDF/Views/Project.php:90 +msgid "All Updates" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:7 +msgid "Filter by type" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:8 +msgid "Subscribe to this timeline" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:9 +msgid "RSS" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:10 +msgid "Atom feed" +msgstr "" + +#: IDF/gettexttemplates/idf/project-list.html.php:3 +msgid "Project activity: %%activity%%%" +msgstr "" + +#: IDF/gettexttemplates/idf/project-list.html.php:9 +msgid "n/a" +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation-email.txt.php:3 +#, php-format +msgid "" +"Hello,\n" +"\n" +"You have requested the creation of an account to\n" +"participate in the life of a software project.\n" +"\n" +"To confirm the account please follow this link:\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following confirmation key:\n" +"\n" +"%%key%%\n" +"\n" +"If you are not interested any longer in taking\n" +"part in the life of the software project or if\n" +"you can't remember having requested the creation\n" +"of an account, please excuse us and simply ignore\n" +"this email. \n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:3 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:3 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:3 +msgid "Oops, please check the form for errors." +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:5 +msgid "Email:" +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:6 +msgid "Enable Your Account" +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:8 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:8 +msgid "" +"This is the last step, but just be sure to have the cookies enabled to log in afterwards." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:3 +msgid "" +"Read the terms and conditions – " +"basically \"Please be nice, we respect you\"." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:4 +#, php-format +msgid "" +"If you have just forgotten your login information, then there is no need to " +"create a new account. You can just recover your login " +"name and password." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:5 +#, php-format +msgid "" +"With your account, you will able to participate in the life of all the " +"projects hosted here. Participating in a software project must be fun, so if " +"you have troubles, you can let us know about your issues " +"at anytime!" +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:6 +msgid "Oops, please check the provided login and email address to register." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:7 IDF/Views.php:137 +msgid "Create Your Account" +msgstr "Vytvořte si účet" + +#: IDF/gettexttemplates/idf/register/index.html.php:9 +msgid "" +"Be sure to provide a valid email address, as we are sending a validation " +"link by email." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:10 +msgid "Did you know?" +msgstr "" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:3 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:3 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:3 +msgid "Oops, we found an error in the form." +msgstr "" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:4 +msgid "Confirm Your Account" +msgstr "" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:7 +msgid "" +"Use your email software to read your emails and open your confirmation " +"email. Either click directly on the confirmation link or copy/paste the " +"confirmation key in the box and submit the form." +msgstr "" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:8 +msgid "" +"Just after providing the confirmation key, you will be able to set your " +"password and start using this website fully." +msgstr "" + +#: IDF/gettexttemplates/idf/review/base-full.html.php:3 +#: IDF/gettexttemplates/idf/review/base.html.php:3 +msgid "Open Reviews" +msgstr "" + +#: IDF/gettexttemplates/idf/review/base.html.php:4 +#: IDF/gettexttemplates/idf/review/create.html.php:11 +#: IDF/gettexttemplates/idf/review/index.html.php:3 IDF/Views/Review.php:83 +msgid "Start Code Review" +msgstr "" + +#: IDF/gettexttemplates/idf/review/create.html.php:3 +msgid "" +"

To start a code review, you need to provide:

\n" +"
    \n" +"
  • A commit or revision of the current code in the repository from which " +"you started your work.
  • \n" +"
  • A patch describing your changes with respect to the reference commit.\n" +"
  • Check your patch does not provide any password or confidential " +"information!
  • \n" +"
" +msgstr "" + +#: IDF/gettexttemplates/idf/review/create.html.php:9 +msgid "" +"The form contains some errors. Please correct them to submit the code review." +msgstr "" + +#: IDF/gettexttemplates/idf/review/create.html.php:10 +msgid "" +"Select the commit against which you created your patch to be sure it applies " +"correctly." +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:3 +msgid "The following review has been created:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:16 +msgid "Review:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:3 +msgid "The following review has been updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:5 +#, php-format +msgid "" +"By %%who%%, %%c.creation_dtime%%, on file:\n" +"%%c.cfile%%\n" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:14 +msgid "General comments (last first):" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:15 +msgid "Detailed file comments (last first):" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:3 +msgid "" +"Code review is a process in which\n" +"after or before changes are commited into the code repository,\n" +"different people discuss the code changes. The goal is\n" +"to improve the quality of the code and the\n" +"contributions, as such, you must be pragmatic when writing\n" +"your review. Correctly mention the line numbers (in the old or in the\n" +"new file) and try to keep a good balance between seriousness and fun.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:11 +msgid "" +"\n" +"Proposing code for review is intimidating, you know\n" +"you will receive critics, so please, as a reviewer, keep this\n" +"process fun, use it to help your contributor learn your\n" +"coding standards and the structure of the code and make them want\n" +"to propose more contributions.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:18 +#: IDF/gettexttemplates/idf/source/commit.html.php:3 +#: IDF/gettexttemplates/idf/source/commit.html~.php:3 +#, php-format +msgid "%%ndiff%% diff" +msgid_plural "%%ndiff%% diffs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: IDF/gettexttemplates/idf/review/view.html.php:19 +#, php-format +msgid "%%nc%% comment" +msgid_plural "%%nc%% comments" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: IDF/gettexttemplates/idf/review/view.html.php:20 +#, php-format +msgid "" +"Comment %%i%% by %%who%%, " +"%%c.creation_dtime%%" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:21 +#, php-format +msgid "Your comments on the changes in file %%file%%:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:23 +#, php-format +msgid "Sign in to participate in the review." +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:24 +msgid "" +"The form contains some errors. Please correct them to submit your review." +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:25 +msgid "How to Participate in a Code Review" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:28 +#: IDF/gettexttemplates/idf/source/commit.html.php:5 +#: IDF/gettexttemplates/idf/source/commit.html~.php:5 +msgid "Author:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:29 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/source/commit.html.php:7 +#: IDF/gettexttemplates/idf/source/commit.html~.php:7 +msgid "Commit:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:30 +#: IDF/gettexttemplates/idf/source/commit.html.php:8 +#: IDF/gettexttemplates/idf/source/commit.html~.php:8 +msgid "View corresponding source tree" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:32 +msgid "Reviewers:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:33 +msgid "No reviewers at the moment." +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:34 +msgid "Files:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:36 +#: IDF/gettexttemplates/idf/source/commit.html.php:24 +#: IDF/gettexttemplates/idf/source/commit.html~.php:23 +msgid "Download the corresponding diff file" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:37 +msgid "General Comments" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:40 +msgid "Submit Code Review" +msgstr "" + +#: IDF/gettexttemplates/idf/source/base.html.php:3 +msgid "Source Tree" +msgstr "" + +#: IDF/gettexttemplates/idf/source/base.html.php:4 +msgid "Change Log" +msgstr "" + +#: IDF/gettexttemplates/idf/source/base.html.php:6 +msgid "How To Get The Code" +msgstr "" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:3 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:8 +#: IDF/Views/Project.php:190 +msgid "Age" +msgstr "" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:4 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:10 +msgid "Message" +msgstr "" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:5 +msgid "Parent:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:6 +#: IDF/gettexttemplates/idf/source/commit.html.php:10 +#: IDF/gettexttemplates/idf/source/commit.html~.php:10 +msgid "View corresponding commit" +msgstr "" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:8 +msgid "by" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:3 +msgid "A new commit has been created:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:8 +msgid "Created by:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:8 +msgid "Created at:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:8 +msgid "Content:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:10 +msgid "Commit details:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:4 +#: IDF/gettexttemplates/idf/source/commit.html~.php:4 +msgid "Date:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:6 +#: IDF/gettexttemplates/idf/source/commit.html~.php:6 +msgid "Branch:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:9 +#: IDF/gettexttemplates/idf/source/commit.html~.php:9 +msgid "Parents:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:11 +#: IDF/gettexttemplates/idf/source/commit.html~.php:11 +msgid "Message:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:12 +#: IDF/gettexttemplates/idf/source/commit.html~.php:12 +#: IDF/gettexttemplates/idf/wiki/feedfragment-page.xml.php:3 +#: IDF/gettexttemplates/idf/wiki/feedfragment-resource.xml.php:3 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:10 +msgid "Changes:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:13 +#: IDF/gettexttemplates/idf/source/commit.html~.php:13 +msgid "deleted" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:14 +#: IDF/gettexttemplates/idf/source/commit.html.php:18 +#: IDF/gettexttemplates/idf/source/commit.html~.php:14 +#: IDF/gettexttemplates/idf/source/commit.html~.php:17 +msgid "full" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:15 +#: IDF/gettexttemplates/idf/source/commit.html~.php:15 +msgid "renamed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:16 +msgid "copied" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:17 +#: IDF/gettexttemplates/idf/source/commit.html~.php:16 +msgid "added" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:19 +#: IDF/gettexttemplates/idf/source/commit.html~.php:18 +msgid "modified" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:20 +msgid "properties changed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:21 +#: IDF/gettexttemplates/idf/source/commit.html~.php:20 +msgid "removed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:22 +#: IDF/gettexttemplates/idf/source/commit.html~.php:21 +msgid "File differences" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html~.php:19 +msgid "properies changed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:3 +#, php-format +msgid "" +"The revision identifier %%commit%% is ambiguous and can be\n" +"expanded to multiple valid revisions - please choose one:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:5 +msgid "Title" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:6 +msgid "Author" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:7 +msgid "Date" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:8 +msgid "Branch" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:9 +msgid "Revision" +msgstr "" + +#: IDF/gettexttemplates/idf/source/feedfragment.xml.php:3 +#, php-format +msgid "%%cproject.name%%: Commit %%c.scm_id%%" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:3 +msgid "Branches" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:4 +msgid "filter branches" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:5 +msgid "Tags" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:6 +msgid "filter tags" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/file.html.php:3 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:4 +#, php-format +msgid "" +"Source at commit %%commit%% created " +"%%cobject.date%%." +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/file.html.php:4 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:5 +#, php-format +msgid "By %%cobject.author%%, %%cobject.title%%" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/file.html.php:5 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:6 +msgid "Root" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the git software to manage the source\n" +"code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:6 +#, php-format +msgid "" +"You may need to provide your SSH key. The " +"synchronization of your SSH key can take a couple of minutes. You can learn " +"more about SSH key authentication." +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:6 +msgid "To make a first commit in the repository, perform the following steps:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:8 +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:7 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:7 +#, php-format +msgid "Find here more details on how to access %%project%% source code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:9 +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:8 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:8 +msgid "Command-Line Access" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:10 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:9 +msgid "First Commit" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:11 +#: IDF/Views/Download.php:66 IDF/Views/Download.php:348 +msgid "Size" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:12 +msgid ":" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:13 +msgid "Download this version" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:13 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:13 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:14 +msgid "or" +msgstr "" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:3 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:3 +#, php-format +msgid "" +"The branch or revision %%commit%% is not valid or does not exist\n" +"in this repository." +msgstr "" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:5 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:5 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:5 +msgid "The following list shows all available branches:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:6 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:6 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:6 +#, php-format +msgid "" +"If this is a new repository, the reason for this error\n" +"could be that you have not committed and / or pushed any change so far.\n" +"In this case please take a look at the Help page\n" +"how to access your repository." +msgstr "" + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the Mercurial software to manage the source\n" +"code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:6 +#, php-format +msgid "" +"To get write access to the repository, you need to use your username and " +"your extra password." +msgstr "" + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:9 +msgid "Write Access Authentication" +msgstr "" + +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:3 +#, php-format +msgid "Property %%prop%% set to %%val%%" +msgstr "" + +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the monotone software to manage the source\n" +"code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/changelog.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/commit.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/commit.html~.php:3 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:14 +msgid "Revision:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/changelog.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/commit.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/commit.html~.php:4 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:10 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:15 +msgid "Switch" +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the subversion software to manage the source\n" +"code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:3 +#, php-format +msgid "" +"The revision %%commit%% is not valid or does not exist\n" +"in this repository." +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:9 +msgid "Rev" +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:16 +msgid "Branches:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:17 +msgid "Tags:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/changeemail-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"To confirm that you want %%email%%\n" +"to be your new email address, just follow this link:\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following verification key:\n" +"\n" +"%%key%%\n" +"\n" +"If you do not want to change your email address, \n" +"just ignore this message.\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/user/changeemail.html.php:4 +msgid "Confirm Your New Email Address" +msgstr "" + +#: IDF/gettexttemplates/idf/user/changeemail.html.php:7 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:7 +msgid "" +"Use your email software to read your emails and open your verification " +"email. Either click directly on the verification link or copy/paste the " +"verification key in the box and submit the form." +msgstr "" + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:3 +#, php-format +msgid "Update your account." +msgstr "" + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:4 +#, php-format +msgid "See your public profile." +msgstr "" + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:5 +#, php-format +msgid "See your forge issue watch list." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:6 +msgid "Key Management" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:7 +msgid "Secondary Emails" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:8 +msgid "Extra password" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:9 +msgid "" +"This password is used to access some of the external systems managed by our " +"infrastructure. It will be regenerated if you change your password." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:10 +msgid "API key" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:11 +msgid "" +"Your API key will be regenerated automatically if you change your password." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:12 +msgid "Update Your Account" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:14 +msgid "Your Current Public Keys" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:15 +msgid "Delete this key" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:16 +msgid "Your additional email addresses" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:17 +msgid "Delete this address" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:18 +msgid "" +"If possible, use your real name. By using your real name, people will have " +"more trust in your comments and remarks." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:19 +msgid "" +"The extra password is used to access some of the external systems and the " +"API key is used to interact with this website using a program." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:20 +msgid "Show API key and extra password" +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:3 +msgid "" +"Oops, please check the provided login or email address to recover your " +"password." +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:4 +msgid "Recover My Password" +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:6 +msgid "" +"Provide either your login or email address, if a corresponding user is found " +"in the database, we will send you an email with the details on how to reset " +"your password." +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"You lost your password and wanted to recover it.\n" +"To provide a new password for your account, you\n" +"just have to follow the provided link. You will\n" +"get a simple form to provide a new password.\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following verification key:\n" +"\n" +"%%key%%\n" +"\n" +"If you are not the one who requested to reset\n" +"your password, simply ignore this email, your\n" +"password will not be changed.\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:4 +msgid "Recover Your Password" +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:8 +msgid "" +"Just after providing the confirmation key, you will be able to reset your " +"password and use this website fully." +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:6 +msgid "Reset Your Password" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:3 +#, php-format +msgid "You are looking at the public profile of %%member%%." +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:5 +msgid "Twitter:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:6 +msgid "Public Email:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:7 +msgid "Website:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:8 +msgid "Last time seen:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:9 +msgid "Member since:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:3 +msgid "List Pages" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:4 +msgid "List Resources" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:5 +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:4 +#: IDF/gettexttemplates/idf/wiki/search.html.php:3 IDF/Views/Wiki.php:211 +msgid "New Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:6 +#: IDF/gettexttemplates/idf/wiki/listResources.html.php:3 +#: IDF/Views/Wiki.php:256 +#, fuzzy +msgid "New Resource" +msgstr "Nový předmět k řešení" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:7 +msgid "Update This Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:8 +msgid "Update This Resource" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:3 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:3 +msgid "Preview of the Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:7 +msgid "The form contains some errors. Please correct them to create the page." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:6 +msgid "Create Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:3 +msgid "" +"\n" +"Wiki resources are later addressed in wiki pages by their title, so ensure " +"that you\n" +"give your resource a unique and an easy to remember name.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:8 +#, fuzzy +msgid "Create Resource" +msgstr "Vytvořte si účet" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:3 +msgid "" +"If you delete this documentation page, it will be removed from the database " +"with all the associated revisions and you will not be able to " +"recover it." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:6 +msgid "Delete Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:14 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:15 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:15 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:17 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:18 +msgid "Old Revisions" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:3 +#, php-format +msgid "" +"You are looking at an old revision (%%oldrev.summary%%) of the " +"page \n" +"%%page.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:5 +msgid "" +"If you delete this old revision, it will be removed from the database and " +"you will not be able to recover it." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:8 +msgid "Delete Revision" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:3 +msgid "" +"If you delete this documentation resource, it will be removed from the " +"database with all the associated revisions \n" +"and you will not be able to recover it. Any documentation " +"pages that reference this resource,\n" +"will no longer be able to render it, but won't be deleted." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:8 +msgid "Delete Resource" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:10 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:8 +#, fuzzy +msgid "File size" +msgstr "velikost souboru" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:9 +#: IDF/Views/Wiki.php:101 +#, fuzzy +msgid "MIME type" +msgstr "typ" + +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:3 +#, php-format +msgid "" +"You are looking at an old revision (%%oldrev.summary%%) of the " +"resource \n" +"%%resource.title%%. This revision was created by " +"%%submitter%%." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/edit-info.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

The content of the page can use the Markdown syntax with the Extra extension.

\n" +"

Website addresses are automatically linked and you can link to another " +"page in the documentation using double square brackets like that " +"[[AnotherPage]].

\n" +"

If you want to embed uploaded resources, use the [[!ResourceName]] syntax for that. This is described more in detail in the FAQ.

\n" +"

To directly include a file content from the repository, embrace its path " +"with triple square brackets: [[[my/file.txt]]].

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/feedfragment-resource.xml.php:4 +msgid "Initial creation" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:3 +#, php-format +msgid "See the deprecated pages." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:5 +msgid "Number of pages:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/listResources.html.php:4 +msgid "Number of resources:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/search.html.php:4 +msgid "Pages found:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:3 +msgid "The form contains some errors. Please correct them to update the page." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:6 +msgid "Update Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:10 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:11 +msgid "Delete this page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:4 +msgid "Update Resource" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:8 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:9 +msgid "Delete this resource" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:3 +msgid "" +"Attention! This page is marked as deprecated, \n" +"use it as reference only if you are sure you need these specific information." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:5 +#, php-format +msgid "" +"You are looking at an old revision of the page \n" +"%%page.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:10 +msgid "Table of Content" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:13 +msgid "Delete this revision" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:3 +#, php-format +msgid "" +"You are looking at an old revision of the resource \n" +"%%resource.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:14 +msgid "Page Usage" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:15 +msgid "This resource is not used on any pages yet." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:3 +msgid "A new documentation page has been created:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:14 +msgid "Documentation page:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:3 +msgid "The following documentation page has been updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:7 +msgid "Updated by:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:13 +msgid "New content:" +msgstr "" + +#: IDF/Issue.php:76 +msgid "owner" +msgstr "vlastník" + +#: IDF/Issue.php:84 IDF/Wiki/Page.php:86 +msgid "interested users" +msgstr "zainteresovaní uživatelé" + +#: IDF/Issue.php:85 +msgid "" +"Interested users will get an email notification when the issue is changed." +msgstr "Zainteresovaní čtenáři dostanou e-mail, pokud se problematika změní." + +#: IDF/Issue.php:92 IDF/Project.php:94 IDF/Review.php:95 IDF/Upload.php:99 +#: IDF/Wiki/Page.php:94 +msgid "labels" +msgstr "nálepky" + +#: IDF/Issue.php:111 IDF/IssueFile.php:102 IDF/Review.php:114 +#: IDF/Upload.php:118 IDF/Wiki/Page.php:106 IDF/Wiki/Resource.php:101 +msgid "modification date" +msgstr "datum změny" + +#: IDF/Issue.php:212 IDF/IssueComment.php:143 +#, php-format +msgid "" +"Issue %3$d, %4$s" +msgstr "" +"předmět " +"k řešení %3$d, %4$s" + +#: IDF/Issue.php:214 +#, fuzzy, php-format +msgid "Creation of issue %3$d, by %4$s" +msgstr "Vytvoření předmět %d, by %s" + +#: IDF/Issue.php:224 +#, fuzzy, php-format +msgid "%1$s: Issue %2$d created - %3$s" +msgstr "%s: Předmět %d vytvořen - %s" + +#: IDF/Issue.php:307 +#, fuzzy, php-format +msgid "Issue %1$s - %2$s (%3$s)" +msgstr "Předmět k řešení %s - %s (%s)" + +#: IDF/Issue.php:311 +#, fuzzy, php-format +msgid "Updated Issue %1$s - %2$s (%3$s)" +msgstr "Předmět aktualizován %s - %s (%s)" + +#: IDF/IssueComment.php:51 IDF/IssueRelation.php:47 +msgid "issue" +msgstr "předmět k řešení" + +#: IDF/IssueComment.php:58 IDF/IssueFile.php:49 IDF/Review/Comment.php:62 +#: IDF/Review/FileComment.php:49 IDF/Review/FileComment.php:69 +msgid "comment" +msgstr "komentář" + +#: IDF/IssueComment.php:72 IDF/Review/Comment.php:75 IDF/Upload.php:63 +#: IDF/Wiki/PageRevision.php:85 +msgid "changes" +msgstr "změny" + +#: IDF/IssueComment.php:73 +msgid "Serialized array of the changes in the issue." +msgstr "Serializované pole změn předmětů k řešení." + +#: IDF/IssueComment.php:180 +#, fuzzy, php-format +msgid "Comment on issue %3$d, by %4$s" +msgstr "" +"Komentář k předmětu k řešení č. %d, %s" + +#: IDF/IssueComment.php:191 +#, fuzzy, php-format +msgid "%1$s: Comment on issue %2$d - %3$s" +msgstr "%s: komentář k předmětu %d - %s" + +#: IDF/IssueFile.php:64 +msgid "file name" +msgstr "jméno souboru" + +#: IDF/IssueFile.php:70 +msgid "the file" +msgstr "soubor" + +#: IDF/IssueFile.php:76 +msgid "file size" +msgstr "velikost souboru" + +#: IDF/IssueFile.php:84 +msgid "type" +msgstr "typ" + +#: IDF/IssueFile.php:86 +msgid "Image" +msgstr "obrázek" + +#: IDF/IssueFile.php:87 +msgid "Other" +msgstr "Ostatní" + +#: IDF/IssueRelation.php:54 +msgid "verb" +msgstr "" + +#: IDF/IssueRelation.php:61 +msgid "other issue" +msgstr "" + +#: IDF/Key.php:55 +msgid "public key" +msgstr "" + +#: IDF/Key.php:90 +msgid "Invalid or unknown key data detected." +msgstr "" + +#: IDF/Plugin/SyncMercurial.php:78 IDF/Plugin/SyncSvn.php:81 +#, php-format +msgid "The repository %s already exists." +msgstr "" + +#: IDF/Plugin/SyncMercurial.php:142 +#, php-format +msgid "%s does not exist or is not writable." +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:107 IDF/Plugin/SyncMonotone.php:492 +msgid "\"mtn_repositories\" must be defined in your configuration file" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:114 IDF/Plugin/SyncMonotone.php:482 +msgid "\"mtn_usher_conf\" does not exist or is not writable" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:121 +#, php-format +msgid "Could not find mtn-post-push script \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:155 +#, php-format +msgid "The configuration file \"%s\" is missing" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:164 +#, php-format +msgid "The project path \"%s\" already exists" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:170 +#, php-format +msgid "The project path \"%s\" could not be created" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:208 +#, php-format +msgid "The key directory \"%s\" could not be created" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:227 +#, php-format +msgid "Could not parse key information: %s" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:265 +#, php-format +msgid "Could not create configuration directory \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:275 +#, php-format +msgid "Could not create symlink for configuration file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:293 +#, php-format +msgid "Could not write configuration file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:309 IDF/Plugin/SyncMonotone.php:525 +#, php-format +msgid "Could not parse usher configuration in \"%1$s\": %2$s" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:320 +#, php-format +msgid "usher configuration already contains a server entry named \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:345 IDF/Plugin/SyncMonotone.php:546 +#, php-format +msgid "Could not write usher configuration file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:395 +#, php-format +msgid "Could not write write-permissions file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:420 +#, php-format +msgid "Could not write read-permissions file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:438 +#, php-format +msgid "Could not remove symlink \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:446 +#, php-format +msgid "Could not create symlink \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:500 +#, php-format +msgid "One or more paths underneath %s could not be deleted" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:512 +#, php-format +msgid "Could not delete client private key \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:599 IDF/Plugin/SyncMonotone.php:718 +#, php-format +msgid "Could not parse read-permissions for project \"%1$s\": %2$s" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:643 IDF/Plugin/SyncMonotone.php:741 +#, php-format +msgid "Could not write read-permissions for project \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:657 IDF/Plugin/SyncMonotone.php:760 +#, php-format +msgid "Could not write write-permissions file for project \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:813 +msgid "\"mtn_repositories\" must be defined in your configuration file." +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:820 +#, php-format +msgid "The project path %s does not exists." +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:838 +#, php-format +msgid "The command \"%s\" could not be executed." +msgstr "" + +#: IDF/Project.php:62 IDF/Tag.php:66 +msgid "name" +msgstr "jméno" + +#: IDF/Project.php:69 +msgid "short name" +msgstr "krátké jméno" + +#: IDF/Project.php:70 +#, fuzzy +msgid "" +"Used in the URL to access the project, must be short with only letters and " +"numbers." +msgstr "" +"Používáné v url k projektu, musí být krátké a obsahovat pouze písmena a " +"čísla." + +#: IDF/Project.php:78 +msgid "short description" +msgstr "krátký popis" + +#: IDF/Project.php:86 IDF/Review/Patch.php:74 +msgid "description" +msgstr "popis" + +#: IDF/Project.php:87 +#, fuzzy +msgid "The description can be extended using the Markdown syntax." +msgstr "Popis může být rozšířen pomocí markdown syntaxe." + +#: IDF/Project.php:100 +msgid "private" +msgstr "soukromé" + +#: IDF/Project.php:108 +msgid "current project activity" +msgstr "" + +#: IDF/Project.php:159 +#, php-format +msgid "Project \"%s\" not found." +msgstr "Projekt \"%s\" nenalezen." + +#: IDF/ProjectActivity.php:56 +msgid "date" +msgstr "" + +#: IDF/Review/Comment.php:55 IDF/Review/Patch.php:80 +msgid "patch" +msgstr "" + +#: IDF/Review/Comment.php:83 +msgid "vote" +msgstr "" + +#: IDF/Review/Comment.php:139 IDF/Review/Patch.php:151 +#, php-format +msgid "" +"Review %3$d, %4$s" +msgstr "" + +#: IDF/Review/Comment.php:141 +#, fuzzy, php-format +msgid "Update of review %3$d, by %4$s" +msgstr "Vytvoření předmět %d, by %s" + +#: IDF/Review/Comment.php:151 +#, php-format +msgid "%1$s: Updated review %2$d - %3$s" +msgstr "" + +#: IDF/Review/Comment.php:222 +#, fuzzy, php-format +msgid "Updated Code Review %1$s - %2$s (%3$s)" +msgstr "Předmět aktualizován %s - %s (%s)" + +#: IDF/Review/Patch.php:52 +msgid "review" +msgstr "" + +#: IDF/Review/Patch.php:67 +msgid "commit" +msgstr "" + +#: IDF/Review/Patch.php:153 +#, fuzzy, php-format +msgid "Creation of review %3$d, by %4$s" +msgstr "Vytvoření předmět %d, by %s" + +#: IDF/Review/Patch.php:163 +#, fuzzy, php-format +msgid "%1$s: Creation of Review %2$d - %3$s" +msgstr "%s: komentář k předmětu %d - %s" + +#: IDF/Review/Patch.php:208 +#, fuzzy, php-format +msgid "New Code Review %1$s - %2$s (%3$s)" +msgstr "Nový commit %s - %s (%s)" + +#: IDF/Scm/Git.php:309 IDF/Scm/Mercurial.php:199 +#, php-format +msgid "Folder %1$s not found in commit %2$s." +msgstr "" + +#: IDF/Scm/Git.php:433 IDF/Scm/Mercurial.php:216 +#, php-format +msgid "Not a valid tree: %s." +msgstr "" + +#: IDF/Scm/Monotone/Stdio.php:81 +msgid "Monotone client key name or hash not in project conf." +msgstr "" + +#: IDF/Scm/Monotone/Stdio.php:89 +#, php-format +msgid "The key directory %s could not be created." +msgstr "" + +#: IDF/Scm/Monotone/Stdio.php:100 +#, php-format +msgid "Could not write client key \"%s\"" +msgstr "" + +#: IDF/Search/Occ.php:33 +msgid "occurrence" +msgstr "" + +#: IDF/Search/Occ.php:49 +msgid "word" +msgstr "" + +#: IDF/Search/Occ.php:75 +msgid "occurrences" +msgstr "" + +#: IDF/Search/Occ.php:81 +msgid "ponderated occurrence" +msgstr "" + +#: IDF/Tag.php:59 +msgid "tag class" +msgstr "třída tagu" + +#: IDF/Tag.php:60 +msgid "The class of the tag." +msgstr "Třída tagu." + +#: IDF/Tag.php:73 +msgid "lcname" +msgstr "lcname" + +#: IDF/Tag.php:74 +msgid "Lower case version of the name for fast searching." +msgstr "Jméno souboru s malými písmenky pro rychlé vyhledávání." + +#: IDF/Template/Markdown.php:84 +msgid "Create this documentation page" +msgstr "Vytvořit tuto dokumentační stránku" + +#: IDF/Template/Markdown.php:97 +msgid "You are not allowed to access the wiki." +msgstr "" + +#: IDF/Template/Markdown.php:106 +msgid "The wiki resource has not been found." +msgstr "" + +#: IDF/Template/Markdown.php:113 +msgid "The wiki resource has not been found. Create it!" +msgstr "" + +#: IDF/Template/Markdown.php:146 +msgid "This revision of the resource is no longer available." +msgstr "" + +#: IDF/Template/ShowUser.php:51 +msgid "Anonymous" +msgstr "Anonym" + +#: IDF/Template/ShowUser.php:54 +msgid "Me" +msgstr "Já" + +#: IDF/Timeline/Paginator.php:49 +msgid "Today" +msgstr "" + +#: IDF/Upload.php:70 +msgid "file" +msgstr "soubor" + +#: IDF/Upload.php:71 +msgid "The path is relative to the upload path." +msgstr "Cesta je relativní k adresáři nahrávaných souborů." + +#: IDF/Upload.php:78 IDF/Wiki/ResourceRevision.php:71 +msgid "file size in bytes" +msgstr "velikost souboru v bytech" + +#: IDF/Upload.php:84 +msgid "MD5" +msgstr "" + +#: IDF/Upload.php:106 +msgid "number of downloads" +msgstr "počet stažení" + +#: IDF/Upload.php:201 +#, php-format +msgid "Download %2$d, %3$s" +msgstr "Stáhnout %2$d, %3$s" + +#: IDF/Upload.php:204 +#, fuzzy, php-format +msgid "Addition of download %2$d, by %3$s" +msgstr "Soubor %d přidán, kým - %s" + +#: IDF/Upload.php:214 +#, fuzzy, php-format +msgid "%1$s: Download %2$d added - %3$s" +msgstr "%s: Soubor %d přidán - %s" + +#: IDF/Upload.php:301 +#, fuzzy, php-format +msgid "New download - %1$s (%2$s)" +msgstr "Nové stažení - %s (%s)" + +#: IDF/Upload.php:305 +#, fuzzy, php-format +msgid "Updated download - %1$s (%2$s)" +msgstr "Nové stažení - %s (%s)" + +#: IDF/Views/Admin.php:47 +#, fuzzy +msgid "The forge configuration has been saved." +msgstr "Následující předmět k řešení byl aktualizován:" + +#: IDF/Views/Admin.php:80 +msgid "This table shows the projects in the forge." +msgstr "" + +#: IDF/Views/Admin.php:85 +msgid "Short Name" +msgstr "" + +#: IDF/Views/Admin.php:87 +msgid "Repository Size" +msgstr "" + +#: IDF/Views/Admin.php:93 +msgid "No projects were found." +msgstr "" + +#: IDF/Views/Admin.php:116 +#, fuzzy +msgid "The label configuration has been saved." +msgstr "Následující předmět k řešení byl aktualizován:" + +#: IDF/Views/Admin.php:147 IDF/Views/Admin.php:314 IDF/Views/Wiki.php:484 +#: IDF/Views/Wiki.php:536 +#, php-format +msgid "Update %s" +msgstr "" + +#: IDF/Views/Admin.php:155 IDF/Views/Project.php:304 +msgid "The project has been updated." +msgstr "" + +#: IDF/Views/Admin.php:192 +msgid "The project has been created." +msgstr "" + +#: IDF/Views/Admin.php:223 +#, php-format +msgid "Delete %s Project" +msgstr "" + +#: IDF/Views/Admin.php:230 +msgid "The project has been deleted." +msgstr "" + +#: IDF/Views/Admin.php:260 +msgid "Not Validated User List" +msgstr "" + +#: IDF/Views/Admin.php:268 +msgid "This table shows the users in the forge." +msgstr "" + +#: IDF/Views/Admin.php:272 +msgid "login" +msgstr "" + +#: IDF/Views/Admin.php:275 +msgid "Admin" +msgstr "" + +#: IDF/Views/Admin.php:277 +msgid "Last Login" +msgstr "" + +#: IDF/Views/Admin.php:284 +msgid "No users were found." +msgstr "" + +#: IDF/Views/Admin.php:321 +msgid "You do not have the rights to update this user." +msgstr "" + +#: IDF/Views/Admin.php:339 +msgid "The user has been updated." +msgstr "" + +#: IDF/Views/Admin.php:372 +#, php-format +msgid "The user %s has been created." +msgstr "" + +#: IDF/Views/Admin.php:379 +msgid "Add User" +msgstr "" + +#: IDF/Views/Admin.php:395 +msgid "Usher management" +msgstr "" + +#: IDF/Views/Admin.php:432 +msgid "Usher configuration has been reloaded" +msgstr "" + +#: IDF/Views/Admin.php:436 +msgid "Usher has been shut down" +msgstr "" + +#: IDF/Views/Admin.php:441 +msgid "Usher has been started up" +msgstr "" + +#: IDF/Views/Admin.php:479 +#, php-format +msgid "The server \"%s\" has been started" +msgstr "" + +#: IDF/Views/Admin.php:483 +#, php-format +msgid "The server \"%s\" has been stopped" +msgstr "" + +#: IDF/Views/Admin.php:488 +#, php-format +msgid "The server \"%s\" has been killed" +msgstr "" + +#: IDF/Views/Admin.php:508 +#, php-format +msgid "Open connections for \"%s\"" +msgstr "" + +#: IDF/Views/Admin.php:513 +#, php-format +msgid "no connections for server \"%s\"" +msgstr "" + +#: IDF/Views/Admin.php:534 +msgid "Yes" +msgstr "Ano" + +#: IDF/Views/Admin.php:534 +msgid "No" +msgstr "" + +#: IDF/Views/Download.php:45 +#, php-format +msgid "%s Downloads" +msgstr "" + +#: IDF/Views/Download.php:51 +msgid "This table shows the files to download." +msgstr "" + +#: IDF/Views/Download.php:67 IDF/Views/Download.php:349 +msgid "Uploaded" +msgstr "" + +#: IDF/Views/Download.php:71 IDF/Views/Download.php:353 +msgid "No downloads were found." +msgstr "" + +#: IDF/Views/Download.php:94 +#, php-format +msgid "Download %s" +msgstr "" + +#: IDF/Views/Download.php:111 +#, php-format +msgid "The file %2$s has been updated." +msgstr "" + +#: IDF/Views/Download.php:144 +#, php-format +msgid "Delete Download %s" +msgstr "" + +#: IDF/Views/Download.php:177 +msgid "The file has been deleted." +msgstr "" + +#: IDF/Views/Download.php:244 +#, php-format +msgid "The file has been uploaded." +msgstr "" + +#: IDF/Views/Download.php:271 +msgid "New Downloads from Archive" +msgstr "" + +#: IDF/Views/Download.php:278 +msgid "The archive has been uploaded and processed." +msgstr "" + +#: IDF/Views/Download.php:331 +#, php-format +msgid "%1$s Downloads with Label %2$s" +msgstr "%1$s soubory ke stažení s nálepkou %2$s" + +#: IDF/Views/Download.php:341 +#, php-format +msgid "This table shows the downloads with label %s." +msgstr "" +"Tato tabulka ukazuje soubory ke stažení s nálepkou problémy k řešení %s." + +#: IDF/Views/Issue.php:41 +#, php-format +msgid "%s Open Issues" +msgstr "%s otevřené problémy k řešení" + +#: IDF/Views/Issue.php:51 IDF/Views/Issue.php:382 IDF/Views/User.php:75 +msgid "This table shows the open issues." +msgstr "" + +#: IDF/Views/Issue.php:61 IDF/Views/Issue.php:220 IDF/Views/Issue.php:301 +#: IDF/Views/Issue.php:390 IDF/Views/Issue.php:542 IDF/Views/Issue.php:765 +#: IDF/Views/Issue.php:824 IDF/Views/Review.php:57 IDF/Views/User.php:81 +msgid "Id" +msgstr "" + +#: IDF/Views/Issue.php:64 IDF/Views/Issue.php:223 IDF/Views/Issue.php:305 +#: IDF/Views/Issue.php:393 IDF/Views/Issue.php:545 IDF/Views/Issue.php:768 +#: IDF/Views/Issue.php:827 IDF/Views/Review.php:60 IDF/Views/User.php:85 +msgid "Last Updated" +msgstr "" + +#: IDF/Views/Issue.php:68 IDF/Views/Issue.php:227 IDF/Views/Issue.php:309 +#: IDF/Views/Issue.php:397 IDF/Views/Issue.php:549 IDF/Views/Issue.php:772 +#: IDF/Views/Issue.php:831 +msgid "No issues were found." +msgstr "Nebyly nalezeny žádné problémy k řešení." + +#: IDF/Views/Issue.php:113 +msgid "Not assigned" +msgstr "" + +#: IDF/Views/Issue.php:149 +#, php-format +msgid "Summary of tracked issues in %s." +msgstr "" + +#: IDF/Views/Issue.php:194 +#, php-format +msgid "Watch List: Closed Issues for %s" +msgstr "" + +#: IDF/Views/Issue.php:195 +#, php-format +msgid "This table shows the closed issues in your watch list for %s project." +msgstr "" + +#: IDF/Views/Issue.php:200 +#, php-format +msgid "Watch List: Open Issues for %s" +msgstr "" + +#: IDF/Views/Issue.php:201 +#, php-format +msgid "This table shows the open issues in your watch list for %s project." +msgstr "" + +#: IDF/Views/Issue.php:277 +msgid "Watch List: Closed Issues" +msgstr "" + +#: IDF/Views/Issue.php:278 +msgid "This table shows the closed issues in your watch list." +msgstr "" + +#: IDF/Views/Issue.php:283 +msgid "Watch List: Open Issues" +msgstr "" + +#: IDF/Views/Issue.php:284 +msgid "This table shows the open issues in your watch list." +msgstr "" + +#: IDF/Views/Issue.php:303 IDF/Views/User.php:82 +msgid "Project" +msgstr "" + +#: IDF/Views/Issue.php:344 +#, fuzzy, php-format +msgid "%1$s %2$s Submitted %3$s Issues" +msgstr "Odeslané předměty k řešení:" + +#: IDF/Views/Issue.php:348 +#, php-format +msgid "%1$s %2$s Closed Submitted %3$s Issues" +msgstr "" + +#: IDF/Views/Issue.php:352 +#, fuzzy, php-format +msgid "%1$s %2$s Closed Working %3$s Issues" +msgstr "%s uzavřený předmět k řešení" + +#: IDF/Views/Issue.php:356 +#, php-format +msgid "%1$s %2$s Working %3$s Issues" +msgstr "" + +#: IDF/Views/Issue.php:417 +msgid "Submit a new issue" +msgstr "Odeslat nový předmět k řešení." + +#: IDF/Views/Issue.php:433 +#, fuzzy, php-format +msgid "Issue %2$d has been created." +msgstr "Předmět k řešení č. %d byl vytvořen." + +#: IDF/Views/Issue.php:490 +#, php-format +msgid "Search issues - %s" +msgstr "" + +#: IDF/Views/Issue.php:492 +#, php-format +msgid "Search closed issues - %s" +msgstr "" + +#: IDF/Views/Issue.php:539 +msgid "This table shows the found issues." +msgstr "Tato tabulka ukazuje nalezené předměty k řešení." + +#: IDF/Views/Issue.php:604 +#, fuzzy, php-format +msgid "Issue %2$d: %3$s" +msgstr "Předmět k řešení č. %d: %s" + +#: IDF/Views/Issue.php:628 +#, fuzzy, php-format +msgid "Issue %2$d has been updated." +msgstr "Předmět k řešení č. %d byl aktualizován." + +#: IDF/Views/Issue.php:718 +#, php-format +msgid "View %s" +msgstr "Zobrazit %s" + +#: IDF/Views/Issue.php:745 +#, php-format +msgid "%s Closed Issues" +msgstr "%s uzavřený předmět k řešení" + +#: IDF/Views/Issue.php:755 +msgid "This table shows the closed issues." +msgstr "Tato tabulka ukazuje uzavřené předměty k řešení." + +#: IDF/Views/Issue.php:798 +#, php-format +msgid "%1$s Issues with Label %2$s" +msgstr "%1$s předmět k řešení s nálepkou %2$s" + +#: IDF/Views/Issue.php:801 +#, php-format +msgid "%1$s Closed Issues with Label %2$s" +msgstr "%1$s uzavřený předmět k řešení s nálepkou %2$s" + +#: IDF/Views/Issue.php:814 +#, php-format +msgid "This table shows the issues with label %s." +msgstr "Tato tabulka ukazuje předměty k řešení s nálepkou %s." + +#: IDF/Views/Issue.php:937 +msgid "The issue has been removed from your watch list." +msgstr "Předmět řešení byl odebrán z vašeho seznamu ke sledování." + +#: IDF/Views/Issue.php:940 +msgid "The issue has been added to your watch list." +msgstr "Předměty k řešení byl přidán do vašeho seznamu ke sledování." + +#: IDF/Views/Issue.php:1037 +msgid "On your watch list." +msgstr "Na vašem sledovacím seznamu." + +#: IDF/Views/Project.php:95 +msgid "Issues and Comments" +msgstr "" + +#: IDF/Views/Project.php:99 +msgid "Documents" +msgstr "" + +#: IDF/Views/Project.php:101 +msgid "Reviews and Patches" +msgstr "" + +#: IDF/Views/Project.php:180 +msgid "This table shows the project updates." +msgstr "" + +#: IDF/Views/Project.php:191 +msgid "Change" +msgstr "" + +#: IDF/Views/Project.php:195 +msgid "No changes were found." +msgstr "" + +#: IDF/Views/Project.php:296 +#, php-format +msgid "%s Project Summary" +msgstr "" + +#: IDF/Views/Project.php:335 +#, php-format +msgid "%s Issue Tracking Configuration" +msgstr "" + +#: IDF/Views/Project.php:344 +msgid "The issue tracking configuration has been saved." +msgstr "" + +#: IDF/Views/Project.php:381 +#, php-format +msgid "%s Downloads Configuration" +msgstr "" + +#: IDF/Views/Project.php:393 +msgid "The downloads configuration has been saved." +msgstr "" + +#: IDF/Views/Project.php:428 +#, php-format +msgid "%s Documentation Configuration" +msgstr "" + +#: IDF/Views/Project.php:437 +msgid "The documentation configuration has been saved." +msgstr "" + +#: IDF/Views/Project.php:471 +#, php-format +msgid "%s Project Members" +msgstr "" + +#: IDF/Views/Project.php:480 +msgid "The project membership has been saved." +msgstr "" + +#: IDF/Views/Project.php:503 +#, php-format +msgid "%s Tabs Access Rights" +msgstr "" + +#: IDF/Views/Project.php:517 +msgid "" +"The project tabs access rights and notification settings have been saved." +msgstr "" + +#: IDF/Views/Project.php:566 +#, php-format +msgid "%s Source" +msgstr "" + +#: IDF/Views/Project.php:580 +msgid "The project source configuration has been saved." +msgstr "" + +#: IDF/Views/Review.php:41 +#, php-format +msgid "%s Code Reviews" +msgstr "" + +#: IDF/Views/Review.php:48 +msgid "This table shows the latest reviews." +msgstr "" + +#: IDF/Views/Review.php:64 +msgid "No reviews were found." +msgstr "" + +#: IDF/Views/Review.php:94 +#, fuzzy, php-format +msgid "The code review %2$d has been created." +msgstr "Předmět k řešení č. %d byl vytvořen." + +#: IDF/Views/Review.php:140 +#, fuzzy, php-format +msgid "Review %2$d: %3$s" +msgstr "Předmět k řešení č. %d: %s" + +#: IDF/Views/Review.php:160 +#, fuzzy, php-format +msgid "Your code review %2$d has been published." +msgstr "Předmět k řešení č. %d byl aktualizován." + +#: IDF/Views/Source.php:40 +#, php-format +msgid "%s Source Help" +msgstr "" + +#: IDF/Views/Source.php:58 +#, php-format +msgid "%s Invalid Revision" +msgstr "" + +#: IDF/Views/Source.php:82 +#, php-format +msgid "%s Ambiguous Revision" +msgstr "" + +#: IDF/Views/Source.php:107 +#, php-format +msgid "%1$s %2$s Change Log" +msgstr "" + +#: IDF/Views/Source.php:153 IDF/Views/Source.php:234 IDF/Views/Source.php:362 +#, php-format +msgid "%1$s %2$s Source Tree" +msgstr "" + +#: IDF/Views/Source.php:310 +#, php-format +msgid "%s Commit Details" +msgstr "" + +#: IDF/Views/Source.php:311 +#, php-format +msgid "%1$s Commit Details - %2$s" +msgstr "" + +#: IDF/Views/User.php:59 +msgid "Your Dashboard - Working Issues" +msgstr "" + +#: IDF/Views/User.php:62 +msgid "Your Dashboard - Submitted Issues" +msgstr "" + +#: IDF/Views/User.php:89 +msgid "No issues are assigned to you, yeah!" +msgstr "" + +#: IDF/Views/User.php:89 +msgid "All the issues you submitted are fixed, yeah!" +msgstr "" + +#: IDF/Views/User.php:121 +msgid "Your personal information has been updated." +msgstr "" + +#: IDF/Views/User.php:133 +msgid "Your Account" +msgstr "" + +#: IDF/Views/User.php:157 +msgid "The public key has been deleted." +msgstr "" + +#: IDF/Views/User.php:177 +msgid "The address has been deleted." +msgstr "" + +#: IDF/Views/User.php:200 +msgid "Confirm The Email Change" +msgstr "" + +#: IDF/Views/User.php:232 +#, php-format +msgid "Your new email address \"%s\" has been validated. Thank you!" +msgstr "" + +#: IDF/Views/Wiki.php:41 +#, php-format +msgid "%s Documentation" +msgstr "" + +#: IDF/Views/Wiki.php:48 +msgid "This table shows the documentation pages." +msgstr "" + +#: IDF/Views/Wiki.php:61 IDF/Views/Wiki.php:144 IDF/Views/Wiki.php:185 +msgid "Page Title" +msgstr "" + +#: IDF/Views/Wiki.php:63 IDF/Views/Wiki.php:103 IDF/Views/Wiki.php:146 +#: IDF/Views/Wiki.php:187 +msgid "Updated" +msgstr "" + +#: IDF/Views/Wiki.php:67 IDF/Views/Wiki.php:191 +msgid "No documentation pages were found." +msgstr "" + +#: IDF/Views/Wiki.php:88 +#, fuzzy, php-format +msgid "%s Documentation Resources" +msgstr "%s: Dokumentační stránka %s aktualizována - %s" + +#: IDF/Views/Wiki.php:94 +#, fuzzy +msgid "This table shows the resources that can be used on documentation pages." +msgstr "Tato tabulka ukazuje předměty k řešení s nálepkou %s." + +#: IDF/Views/Wiki.php:100 +msgid "Resource Title" +msgstr "" + +#: IDF/Views/Wiki.php:107 +#, fuzzy +msgid "No resources were found." +msgstr "Nebyly nalezeny žádné problémy k řešení." + +#: IDF/Views/Wiki.php:128 +#, php-format +msgid "Documentation Search - %s" +msgstr "" + +#: IDF/Views/Wiki.php:139 +msgid "This table shows the pages found." +msgstr "" + +#: IDF/Views/Wiki.php:150 +msgid "No pages were found." +msgstr "" + +#: IDF/Views/Wiki.php:169 +#, php-format +msgid "%1$s Documentation Pages with Label %2$s" +msgstr "" + +#: IDF/Views/Wiki.php:179 +#, php-format +msgid "This table shows the documentation pages with label %s." +msgstr "" + +#: IDF/Views/Wiki.php:222 +#, fuzzy, php-format +msgid "The page %2$s has been created." +msgstr "Předmět k řešení č. %d byl vytvořen." + +#: IDF/Views/Wiki.php:265 +#, fuzzy, php-format +msgid "The resource %2$s has been created." +msgstr "Předmět k řešení č. %d byl vytvořen." + +#: IDF/Views/Wiki.php:409 IDF/Views/Wiki.php:448 +msgid "The old revision has been deleted." +msgstr "" + +#: IDF/Views/Wiki.php:415 IDF/Views/Wiki.php:454 +#, php-format +msgid "Delete Old Revision of %s" +msgstr "" + +#: IDF/Views/Wiki.php:496 +#, fuzzy, php-format +msgid "The page %2$s has been updated." +msgstr "Předmět k řešení č. %d byl aktualizován." + +#: IDF/Views/Wiki.php:548 +#, fuzzy, php-format +msgid "The resource %2$s has been updated." +msgstr "Předmět k řešení č. %d byl aktualizován." + +#: IDF/Views/Wiki.php:583 +msgid "The documentation page has been deleted." +msgstr "" + +#: IDF/Views/Wiki.php:591 +#, php-format +msgid "Delete Page %s" +msgstr "" + +#: IDF/Views/Wiki.php:623 +#, fuzzy +msgid "The documentation resource has been deleted." +msgstr "Následující předmět k řešení byl aktualizován:" + +#: IDF/Views/Wiki.php:631 +#, php-format +msgid "Delete Resource %s" +msgstr "" + +#: IDF/Views.php:173 IDF/Views.php:199 +msgid "Confirm Your Account Creation" +msgstr "Potvrďte vytvoření Vašeho účtu" + +#: IDF/Views.php:219 +msgid "Welcome! You can now participate in the life of your project of choice." +msgstr "Vítejte! Nyní se můžete účastnit života projektu dle vašeho výběru." + +#: IDF/Views.php:245 IDF/Views.php:269 IDF/Views.php:310 +msgid "Password Recovery" +msgstr "Obnova hesla" + +#: IDF/Views.php:289 +msgid "" +"Welcome back! Next time, you can use your broswer options to remember the " +"password." +msgstr "" +"Vítejte zpět! Příště můžete použít nastavení prohlížeče pro zapamatování " +"hesla." + +#: IDF/Views.php:331 +msgid "Here to Help You!" +msgstr "Zde k Vaší pomoci!" + +#: IDF/Views.php:347 +msgid "InDefero Upload Archive Format" +msgstr "" + +#: IDF/Views.php:363 +msgid "InDefero API (Application Programming Interface)" +msgstr "InDefero API (aplikační programátorský interface)" + +#: IDF/Wiki/Page.php:62 IDF/Wiki/Resource.php:64 +msgid "title" +msgstr "nadpis" + +#: IDF/Wiki/Page.php:63 +msgid "" +"The title of the page must only contain letters, digits or the dash " +"character. For example: My-new-Wiki-Page." +msgstr "" +"Nadpis musí obsahovat pouze písmena, čísla nebo pomlčku. Např. Moje-nova-" +"WiKi-Stranka." + +#: IDF/Wiki/Page.php:71 +msgid "A one line description of the page content." +msgstr "Jednořádkový popis obsahu stránky." + +#: IDF/Wiki/Page.php:196 IDF/Wiki/PageRevision.php:196 +#, php-format +msgid "%2$s, %3$s" +msgstr "%2$s, %3$s" + +#: IDF/Wiki/Page.php:198 +#, fuzzy, php-format +msgid "Creation of page %2$s, by %3$s" +msgstr "Stránka %s, vytvořena %s" + +#: IDF/Wiki/Page.php:208 +#, fuzzy, php-format +msgid "%1$s: Documentation page %2$s added - %3$s" +msgstr "%s: Stránka dokumentace %s přidána - %s" + +#: IDF/Wiki/PageRevision.php:48 +msgid "page" +msgstr "stránka" + +#: IDF/Wiki/PageRevision.php:66 IDF/Wiki/ResourceRevision.php:64 +msgid "A one line description of the changes." +msgstr "Jednořádkový popis změn." + +#: IDF/Wiki/PageRevision.php:72 +msgid "content" +msgstr "obsah" + +#: IDF/Wiki/PageRevision.php:218 IDF/Wiki/ResourceRevision.php:311 +#, fuzzy, php-format +msgid "Change of %2$s, by %3$s" +msgstr "Změněno %s, kým %s" + +#: IDF/Wiki/PageRevision.php:231 +#, fuzzy, php-format +msgid "%1$s: Documentation page %2$s updated - %3$s" +msgstr "%s: Dokumentační stránka %s aktualizována - %s" + +#: IDF/Wiki/PageRevision.php:293 +#, fuzzy, php-format +msgid "New Documentation Page %1$s - %2$s (%3$s)" +msgstr "Nová dokumentační stránka %s - %s (%s)" + +#: IDF/Wiki/PageRevision.php:297 +#, fuzzy, php-format +msgid "Documentation Page Changed %1$s - %2$s (%3$s)" +msgstr "Dokumentační stránka změněna %s - %s (%s)" + +#: IDF/Wiki/Resource.php:65 +#, fuzzy +msgid "" +"The title of the resource must only contain letters, digits, dots or the " +"dash character. For example: my-resource.png." +msgstr "" +"Nadpis musí obsahovat pouze písmena, čísla nebo pomlčku. Např. Moje-nova-" +"WiKi-Stranka." + +#: IDF/Wiki/Resource.php:72 +msgid "MIME media type" +msgstr "" + +#: IDF/Wiki/Resource.php:73 +msgid "The MIME media type of the resource." +msgstr "" + +#: IDF/Wiki/Resource.php:81 +#, fuzzy +msgid "A one line description of the resource." +msgstr "Jednořádkový popis projektu." + +#: IDF/Wiki/Resource.php:176 IDF/Wiki/ResourceRevision.php:308 +#, fuzzy, php-format +msgid "%2$s, %3$s" +msgstr "%2$s, %3$s" + +#: IDF/Wiki/Resource.php:178 +#, fuzzy, php-format +msgid "Creation of resource %2$s, by %3$s" +msgstr "Stránka %s, vytvořena %s" + +#: IDF/Wiki/Resource.php:188 +#, fuzzy, php-format +msgid "%1$s: Documentation resource %2$s added - %3$s" +msgstr "%s: Stránka dokumentace %s přidána - %s" + +#: IDF/Wiki/ResourceRevision.php:47 +msgid "resource" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:78 +msgid "File extension" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:79 +msgid "The file extension of the uploaded resource." +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:94 +msgid "page usage" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:116 +#, php-format +msgid "id %d: %s" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:263 +#, fuzzy, php-format +msgid "Download (%s)" +msgstr "Nové stažení - %s (%s)" + +#: IDF/Wiki/ResourceRevision.php:270 +msgid "View resource details" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:324 +#, fuzzy, php-format +msgid "%1$s: Documentation resource %2$s updated - %3$s" +msgstr "%s: Dokumentační stránka %s aktualizována - %s" diff --git a/indefero/src/IDF/locale/de/idf.po b/indefero/src/IDF/locale/de/idf.po new file mode 100644 index 0000000..f35c1b7 --- /dev/null +++ b/indefero/src/IDF/locale/de/idf.po @@ -0,0 +1,6171 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: Indefero\n" +"Report-Msgid-Bugs-To: http://projects.ceondo.com/p/indefero/issues/\n" +"POT-Creation-Date: 2012-03-22 01:16+0100\n" +"PO-Revision-Date: 2011-03-04 18:20+0000\n" +"Last-Translator: tommyd \n" +"Language-Team: German <>\n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Language: de_DE\n" +"X-Source-Language: C\n" + +#: IDF/Commit.php:55 IDF/Conf.php:54 IDF/Issue.php:52 +#: IDF/ProjectActivity.php:49 IDF/Review.php:65 IDF/Search/Occ.php:69 +#: IDF/Tag.php:52 IDF/Upload.php:49 IDF/Wiki/Page.php:54 +#: IDF/Wiki/Resource.php:56 +msgid "project" +msgstr "Projekt" + +#: IDF/Commit.php:63 IDF/Issue.php:67 IDF/IssueComment.php:65 +#: IDF/IssueFile.php:57 IDF/IssueRelation.php:69 IDF/Review/Comment.php:69 +#: IDF/Review.php:80 IDF/Upload.php:91 IDF/Wiki/Page.php:78 +#: IDF/Wiki/PageRevision.php:79 IDF/Wiki/Resource.php:88 +#: IDF/Wiki/ResourceRevision.php:86 +msgid "submitter" +msgstr "Absender" + +#: IDF/Commit.php:87 IDF/Issue.php:60 IDF/Review/Patch.php:60 IDF/Review.php:73 +#: IDF/Upload.php:57 IDF/Wiki/Page.php:70 IDF/Wiki/PageRevision.php:65 +#: IDF/Wiki/Resource.php:80 IDF/Wiki/ResourceRevision.php:63 +msgid "summary" +msgstr "Zusammenfassung" + +#: IDF/Commit.php:93 +msgid "changelog" +msgstr "Änderungen" + +#: IDF/Commit.php:100 IDF/Issue.php:105 IDF/IssueComment.php:79 +#: IDF/IssueFile.php:96 IDF/IssueRelation.php:75 IDF/Review/Comment.php:90 +#: IDF/Review/FileComment.php:75 IDF/Review/Patch.php:87 IDF/Review.php:108 +#: IDF/Upload.php:112 IDF/Wiki/Page.php:100 IDF/Wiki/PageRevision.php:92 +#: IDF/Wiki/Resource.php:95 IDF/Wiki/ResourceRevision.php:101 +msgid "creation date" +msgstr "Erstellt am" + +#: IDF/Commit.php:238 +#, php-format +msgid "Commit %1$s, by %2$s" +msgstr "Revision %1$s, von %2$s" + +#: IDF/Commit.php:337 +#, php-format +msgid "New Commit %1$s - %2$s (%3$s)" +msgstr "Neue Revision %1$s - %2$s (%3$s)" + +#: IDF/Conf.php:61 IDF/Gconf.php:73 +msgid "key" +msgstr "Schlüssel" + +#: IDF/Conf.php:67 IDF/Gconf.php:79 IDF/ProjectActivity.php:62 +msgid "value" +msgstr "Wert" + +#: IDF/Diff.php:460 +msgid "Old" +msgstr "Alt" + +#: IDF/Diff.php:460 +msgid "New" +msgstr "Neu" + +#: IDF/EmailAddress.php:49 IDF/Key.php:49 +msgid "user" +msgstr "Benutzer" + +#: IDF/EmailAddress.php:55 +msgid "email" +msgstr "E-Mail" + +#: IDF/Form/Admin/ForgeConf.php:34 +msgid "Custom forge page enabled" +msgstr "Benutzerdefinierte Forge-Seite aktiviert" + +#: IDF/Form/Admin/ForgeConf.php:39 IDF/Form/WikiPageCreate.php:80 +#: IDF/Form/WikiPageUpdate.php:72 +msgid "Content" +msgstr "Inhalt" + +#: IDF/Form/Admin/LabelConf.php:40 +msgid "Predefined project labels" +msgstr "Vordefinierte Projekt-Marken" + +#: IDF/Form/Admin/LabelConf.php:55 +#, php-format +msgid "" +"The label \"%s\" is invalid: A label must only consist of alphanumeric " +"characters and dashes, and can optionally contain a \":\" with a group " +"prefix." +msgstr "" +"Die Marke \"%s\" ist ungültig. Eine Marke darf nur aus alphanumerischen " +"Zeichen und Bindestrichen bestehen und darf optional einen Doppelpunkt mit " +"einem Gruppen-Präfix beinhalten." + +#: IDF/Form/Admin/ProjectCreate.php:38 IDF/Views/Project.php:600 +msgid "git" +msgstr "git" + +#: IDF/Form/Admin/ProjectCreate.php:39 IDF/Views/Project.php:601 +msgid "Subversion" +msgstr "Subversion" + +#: IDF/Form/Admin/ProjectCreate.php:40 IDF/Views/Project.php:602 +msgid "mercurial" +msgstr "mercurial" + +#: IDF/Form/Admin/ProjectCreate.php:41 IDF/Views/Project.php:603 +msgid "monotone" +msgstr "monotone" + +#: IDF/Form/Admin/ProjectCreate.php:49 IDF/Form/Admin/ProjectUpdate.php:44 +#: IDF/Form/ProjectConf.php:39 IDF/Views/Admin.php:86 IDF/Views/Admin.php:273 +msgid "Name" +msgstr "Name" + +#: IDF/Form/Admin/ProjectCreate.php:55 IDF/Form/TabsConf.php:101 +#: IDF/gettexttemplates/idf/base-full.html.php:5 +#: IDF/gettexttemplates/idf/base-full.html~.php:5 +#: IDF/gettexttemplates/idf/base.html.php:5 +#: IDF/gettexttemplates/idf/base.html~.php:5 +#: IDF/gettexttemplates/idf/main-menu.html.php:9 +#: IDF/gettexttemplates/idf/project-list.html.php:5 +#: IDF/gettexttemplates/idf/project-list.html.php:7 +msgid "Private project" +msgstr "Privates Projekt" + +#: IDF/Form/Admin/ProjectCreate.php:62 +msgid "Shortname" +msgstr "Kurzname" + +#: IDF/Form/Admin/ProjectCreate.php:64 +msgid "" +"It must be unique for each project and composed only of letters, digits and " +"dash (-) like \"my-project\"." +msgstr "" +"Er muss das Projekt eindeutig identifizieren und darf nur aus Buchstaben " +"(ohne Umlaute), Ziffern und dem Bindestrich (-) bestehen, zum Beispiel " +"\"mein-projekt\"." + +#: IDF/Form/Admin/ProjectCreate.php:69 IDF/Form/Admin/ProjectUpdate.php:50 +msgid "Short description" +msgstr "Kurzbeschreibung" + +#: IDF/Form/Admin/ProjectCreate.php:70 IDF/Form/Admin/ProjectUpdate.php:51 +#: IDF/Project.php:79 +msgid "A one line description of the project." +msgstr "Einzeilige Beschreibung des Projektes." + +#: IDF/Form/Admin/ProjectCreate.php:77 IDF/Form/Admin/ProjectUpdate.php:58 +#: IDF/Form/ProjectConf.php:56 +msgid "External URL" +msgstr "Externe URL" + +#: IDF/Form/Admin/ProjectCreate.php:84 +msgid "Repository type" +msgstr "Depot-Typ" + +#: IDF/Form/Admin/ProjectCreate.php:92 +msgid "Remote Subversion repository" +msgstr "Entferntes Subversion-Depot" + +#: IDF/Form/Admin/ProjectCreate.php:99 IDF/Form/SourceConf.php:40 +msgid "Repository username" +msgstr "Depot-Benutzername" + +#: IDF/Form/Admin/ProjectCreate.php:106 IDF/Form/SourceConf.php:47 +msgid "Repository password" +msgstr "Depot-Passwort" + +#: IDF/Form/Admin/ProjectCreate.php:113 IDF/Form/Admin/ProjectUpdate.php:66 +msgid "Master branch" +msgstr "Hauptzweig" + +#: IDF/Form/Admin/ProjectCreate.php:116 IDF/Form/Admin/ProjectUpdate.php:69 +msgid "" +"This should be a world-wide unique identifier for your project. A reverse " +"DNS notation like \"com.my-domain.my-project\" is a good idea." +msgstr "" +"Dies sollte ein weltweit eindeutiger Bezeichner für Dein Projekt sein. Eine " +"umgekehrte DNS-Notation wie \"com.my-domain.my-projekt\" ist eine gute Idee." + +#: IDF/Form/Admin/ProjectCreate.php:121 IDF/Form/Admin/ProjectUpdate.php:95 +#: IDF/Form/MembersConf.php:46 IDF/Form/TabsConf.php:53 IDF/Form/TabsConf.php:72 +msgid "Project owners" +msgstr "Projekt-Eigentümer" + +#: IDF/Form/Admin/ProjectCreate.php:130 IDF/Form/Admin/ProjectUpdate.php:103 +#: IDF/Form/MembersConf.php:54 IDF/Form/TabsConf.php:52 IDF/Form/TabsConf.php:78 +msgid "Project members" +msgstr "Projektmitglieder" + +#: IDF/Form/Admin/ProjectCreate.php:140 IDF/Form/Admin/ProjectUpdate.php:85 +#: IDF/Form/IssueCreate.php:168 IDF/Form/IssueUpdate.php:164 +#: IDF/Form/ProjectConf.php:73 IDF/Form/UpdateUpload.php:71 +#: IDF/Form/Upload.php:70 IDF/Form/WikiPageCreate.php:93 +#: IDF/Form/WikiPageUpdate.php:104 +msgid "Labels" +msgstr "Marken" + +#: IDF/Form/Admin/ProjectCreate.php:155 +msgid "Project template" +msgstr "Projektvorlage" + +#: IDF/Form/Admin/ProjectCreate.php:157 +msgid "" +"Use the given project to initialize the new project. Access rights and " +"general configuration will be taken from the template project." +msgstr "" +"Benutze das vorgegebene Projekt, um ein neues zu initialisieren. " +"Zugriffsrechte und allgemeine Konfiguration werden von der Projektvorlage " +"übernommen." + +#: IDF/Form/Admin/ProjectCreate.php:204 +msgid "" +"Only a remote repository available through HTTP or HTTPS is allowed. For " +"example \"http://somewhere.com/svn/trunk\"." +msgstr "" +"Nur ein entferntes Depot, welches durch HTTP oder HTTPS verfügbar ist, ist " +"erlaubt. Beispiel: \"http://somewhere.com/svn/trunk\"." + +#: IDF/Form/Admin/ProjectCreate.php:220 IDF/Form/Admin/ProjectUpdate.php:117 +msgid "" +"The master branch is empty or contains illegal characters, please use only " +"letters, digits, dashes and dots as separators." +msgstr "" +"Der Hauptzweig ist leer oder enthält ungültige Zeichen. Bitte verwende nur " +"Buchstaben, Ziffern, Bindestriche und Punkte als Trenner." + +#: IDF/Form/Admin/ProjectCreate.php:230 IDF/Form/Admin/ProjectUpdate.php:128 +msgid "This master branch is already used. Please select another one." +msgstr "Der Hauptzweig wird bereits verwendet. Bitte wähle einen anderen." + +#: IDF/Form/Admin/ProjectCreate.php:241 +msgid "" +"This shortname contains illegal characters, please use only letters, digits " +"and dash (-)." +msgstr "" +"Der Kurzname enthält ungültige Zeichen. Bitte verwende nur Buchstaben (ohne " +"Umlaute), Ziffern und den Bindestrich." + +#: IDF/Form/Admin/ProjectCreate.php:244 +msgid "The shortname cannot start with the dash (-) character." +msgstr "Der Kurzname darf nicht mit einem Bindestrich (-) beginnen." + +#: IDF/Form/Admin/ProjectCreate.php:247 +msgid "The shortname cannot end with the dash (-) character." +msgstr "Der Kurzname darf nicht mit einem Bindestrich (-) enden." + +#: IDF/Form/Admin/ProjectCreate.php:252 +msgid "This shortname is already used. Please select another one." +msgstr "" +"Der gewählte Kurzname wird bereits verwendet. Bitte wähle einen anderen." + +#: IDF/Form/Admin/ProjectCreate.php:303 IDF/Form/Admin/ProjectDelete.php:78 +#: IDF/Form/Admin/ProjectUpdate.php:153 IDF/Form/Admin/UserCreate.php:106 +#: IDF/Form/Admin/UserUpdate.php:191 IDF/Form/IssueCreate.php:338 +#: IDF/Form/IssueUpdate.php:329 IDF/Form/MembersConf.php:64 +#: IDF/Form/Password.php:76 IDF/Form/Register.php:112 +#: IDF/Form/ReviewCreate.php:187 IDF/Form/ReviewFileComment.php:143 +#: IDF/Form/TabsConf.php:122 IDF/Form/UpdateUpload.php:126 +#: IDF/Form/Upload.php:149 IDF/Form/UploadArchive.php:137 +#: IDF/Form/UserAccount.php:216 IDF/Form/UserChangeEmail.php:80 +#: IDF/Form/WikiPageCreate.php:167 IDF/Form/WikiPageDelete.php:59 +#: IDF/Form/WikiPageUpdate.php:178 IDF/Form/WikiResourceCreate.php:123 +#: IDF/Form/WikiResourceDelete.php:59 IDF/Form/WikiResourceUpdate.php:124 +msgid "Cannot save the model from an invalid form." +msgstr "Kann kein Modell von einer ungültigen Maske speichern." + +#: IDF/Form/Admin/ProjectCreate.php:341 +msgid "" +"Click on the Project Management tab to set the description of your project." +msgstr "" +"Klicke auf den Projekt-Management-Reiter, um eine Beschreibung Deines " +"Projektes zu setzen." + +#: IDF/Form/Admin/ProjectCreate.php:426 +msgid "This project is not available." +msgstr "Das Projekt ist nicht verfügbar." + +#: IDF/Form/Admin/ProjectDelete.php:41 +msgid "Confirmation code" +msgstr "Bestätigungs-Code" + +#: IDF/Form/Admin/ProjectDelete.php:46 +msgid "I have made a backup of all the important data of this project." +msgstr "" +"Ich habe ein Backup aller wichtiger Informationen dieses Projektes gemacht." + +#: IDF/Form/Admin/ProjectDelete.php:55 +msgid "" +"The confirmation code does not match. Please provide a valid confirmation " +"code to delete the project." +msgstr "" +"Der Bestätigungscode stimmt nicht. Bitte gib einen gültigen Bestätigungscode " +"ein, um das Projekt zu löschen." + +#: IDF/Form/Admin/ProjectDelete.php:63 +msgid "Sorry, you really need to backup your data before deletion." +msgstr "" +"Entschuldigung, Du solltest wirklich Deine Daten vor dem Löschen sichern." + +#: IDF/Form/Admin/UserCreate.php:37 IDF/Form/Admin/UserUpdate.php:38 +#: IDF/Form/RegisterConfirmation.php:50 IDF/Form/UserAccount.php:40 +msgid "First name" +msgstr "Vorname" + +#: IDF/Form/Admin/UserCreate.php:46 IDF/Form/Admin/UserUpdate.php:47 +#: IDF/Form/RegisterConfirmation.php:59 IDF/Form/UserAccount.php:49 +msgid "Last name" +msgstr "Nachname" + +#: IDF/Form/Admin/UserCreate.php:56 +msgid "Login" +msgstr "Anmelde-Name" + +#: IDF/Form/Admin/UserCreate.php:60 +msgid "" +"The login must be between 3 and 15 characters long and contains only letters " +"and digits." +msgstr "" +"Der Anmeldename muss zwischen 3 und 15 Zeichen lang sein und darf nur " +"Buchstaben und Zahlen beinhalten." + +#: IDF/Form/Admin/UserCreate.php:69 IDF/Form/Admin/UserUpdate.php:57 +msgid "Email" +msgstr "E-Mail" + +#: IDF/Form/Admin/UserCreate.php:71 +msgid "" +"Double check the email address as the password is sent directly to the user." +msgstr "" +"Überprüfe nochmals die E-Mail-Adresse, da das Passwort direkt an den " +"Benutzer gesendet wird." + +#: IDF/Form/Admin/UserCreate.php:76 IDF/Form/Admin/UserUpdate.php:67 +#: IDF/Form/UserAccount.php:66 +msgid "Language" +msgstr "Sprache" + +#: IDF/Form/Admin/UserCreate.php:87 IDF/Form/UserAccount.php:161 +msgid "Add a public key" +msgstr "Öffentlichen Schlüssel hinzufügen" + +#: IDF/Form/Admin/UserCreate.php:92 +msgid "" +"Paste a SSH or monotone public key. Be careful to not provide your private " +"key here!" +msgstr "" +"Füge einen öffentlichen SSH- oder monotone-Schlüssel hier ein. Pass auf, " +"dass Du nicht versehentlich Deinen privaten Schlüssel hier hineinkopierst!" + +#: IDF/Form/Admin/UserCreate.php:157 +msgid "Your details to access your forge." +msgstr "Die Informationen, um auf Deine Forge zuzugreifen." + +#: IDF/Form/Admin/UserCreate.php:189 IDF/Form/UserAccount.php:429 +#: IDF/Form/UserAccount.php:438 +#, php-format +msgid "The email \"%s\" is already used." +msgstr "Die E-Mail \"%s\" wird bereits genutzt." + +#: IDF/Form/Admin/UserCreate.php:198 IDF/Form/Register.php:72 +#, php-format +msgid "The login \"%s\" can only contain letters and digits." +msgstr "Der Anmeldename \"%s\" darf nur Buchstaben und Zahlen beinhalten." + +#: IDF/Form/Admin/UserCreate.php:203 IDF/Form/Register.php:77 +#, php-format +msgid "The login \"%s\" is already used, please find another one." +msgstr "" +"Der Anmeldename \"%s\" wird bereits benutzt, bitte finde einen anderen." + +#: IDF/Form/Admin/UserUpdate.php:78 +msgid "Password" +msgstr "Passwort" + +#: IDF/Form/Admin/UserUpdate.php:81 +msgid "Leave blank if you do not want to change the password." +msgstr "Lass das Feld leer, wenn Du das Passwort nicht ändern möchtest." + +#: IDF/Form/Admin/UserUpdate.php:81 +msgid "" +"The password must be hard for other people to guess, but easy for the user " +"to remember." +msgstr "" +"Das Passwort sollte für andere Leute schwer zu erraten, aber für den " +"Benutzer einfach zu erinnern sein." + +#: IDF/Form/Admin/UserUpdate.php:89 +msgid "Confirm password" +msgstr "Passwort bestätigen" + +#: IDF/Form/Admin/UserUpdate.php:100 IDF/Form/IssueCreate.php:66 +#: IDF/Form/ProjectConf.php:48 IDF/Form/ReviewCreate.php:54 +#: IDF/Form/UpdateUpload.php:51 IDF/Form/Upload.php:49 +#: IDF/Form/UserAccount.php:101 IDF/Form/WikiPageCreate.php:70 +#: IDF/Form/WikiPageUpdate.php:60 IDF/Form/WikiResourceCreate.php:54 +#: IDF/Form/WikiResourceUpdate.php:46 IDF/Views/Wiki.php:102 +msgid "Description" +msgstr "Beschreibung" + +#: IDF/Form/Admin/UserUpdate.php:109 IDF/Form/UserAccount.php:110 +msgid "Twitter username" +msgstr "Twitter-Benutzername" + +#: IDF/Form/Admin/UserUpdate.php:119 IDF/Form/UserAccount.php:120 +msgid "Public email address" +msgstr "Öffentlichen E-Mail-Adresse" + +#: IDF/Form/Admin/UserUpdate.php:129 IDF/Form/UserAccount.php:130 +msgid "Website URL" +msgstr "Website-Adresse" + +#: IDF/Form/Admin/UserUpdate.php:139 IDF/Form/UserAccount.php:140 +msgid "Upload custom avatar" +msgstr "Eigenes Benutzerbild hochladen" + +#: IDF/Form/Admin/UserUpdate.php:146 IDF/Form/UserAccount.php:147 +msgid "" +"An image file with a width and height not larger than 60 pixels (bigger " +"images are scaled down)." +msgstr "" +"Eine Bilddatei mit einer Breit und einer Höhe von maximal 60 Pixeln (größere " +"Bilder werden kleiner skaliert)." + +#: IDF/Form/Admin/UserUpdate.php:151 IDF/Form/UserAccount.php:152 +msgid "Remove custom avatar" +msgstr "Eigenes Benutzerbild entfernen" + +#: IDF/Form/Admin/UserUpdate.php:155 IDF/Form/UserAccount.php:156 +msgid "Tick this to delete the custom avatar." +msgstr "Markieren, um das eigene Benutzerbild zu löschen." + +#: IDF/Form/Admin/UserUpdate.php:161 IDF/Views/Admin.php:274 +msgid "Staff" +msgstr "Stab" + +#: IDF/Form/Admin/UserUpdate.php:164 +msgid "If you give staff rights to a user, you really need to trust him." +msgstr "" +"Wenn Du einen Benutzer zum Stab hinzufügst, solltest Du ihm wirklich trauen." + +#: IDF/Form/Admin/UserUpdate.php:172 IDF/Views/Admin.php:276 +msgid "Active" +msgstr "Aktiv" + +#: IDF/Form/Admin/UserUpdate.php:176 +msgid "" +"If the user is not getting the confirmation email or is abusing the system, " +"you can directly enable or disable their account here." +msgstr "" +"Wenn der Benutzer keine Bestätigungs-E-Mail erhält oder das System " +"missbraucht, kannst Du sein Benutzerkonto hier direkt aktivieren oder " +"deaktivieren." + +#: IDF/Form/Admin/UserUpdate.php:274 +msgid "--- is not a valid first name." +msgstr "--- ist kein gültiger Vorname." + +#: IDF/Form/Admin/UserUpdate.php:290 +msgid "" +"A user with this email already exists, please provide another email address." +msgstr "" +"Ein Benutzer mit dieser E-Mail-Adresse existiert bereits, bitte gib eine " +"andere E-Mail-Adresse an." + +#: IDF/Form/Admin/UserUpdate.php:301 IDF/Form/UserAccount.php:398 +msgid "For security reason, you cannot upload a file with this extension." +msgstr "" +"Aus Sicherheitsgründen kannst Du keine Dateien mit dieser Erweiterung " +"hochladen." + +#: IDF/Form/Admin/UserUpdate.php:316 IDF/Form/UserAccount.php:461 +msgid "The passwords do not match. Please give them again." +msgstr "Die Passwörter stimmen nicht überein. Bitte gib sie erneut ein." + +#: IDF/Form/Field/EmailList.php:45 +msgid "Please enter one or more valid email addresses." +msgstr "Bitte gib eine oder mehrere gültige E-Mail-Adressen ein." + +#: IDF/Form/IssueCreate.php:57 IDF/Form/IssueUpdate.php:46 +#: IDF/Form/ReviewCreate.php:45 IDF/Form/ReviewFileComment.php:73 +#: IDF/Form/UpdateUpload.php:42 IDF/Form/Upload.php:40 +#: IDF/gettexttemplates/idf/issues/base.html.php:3 IDF/Views/Download.php:65 +#: IDF/Views/Download.php:347 IDF/Views/Issue.php:62 IDF/Views/Issue.php:221 +#: IDF/Views/Issue.php:302 IDF/Views/Issue.php:391 IDF/Views/Issue.php:543 +#: IDF/Views/Issue.php:766 IDF/Views/Issue.php:825 IDF/Views/Review.php:58 +#: IDF/Views/User.php:83 IDF/Views/Wiki.php:62 IDF/Views/Wiki.php:145 +#: IDF/Views/Wiki.php:186 +msgid "Summary" +msgstr "Zusammenfassung" + +#: IDF/Form/IssueCreate.php:76 IDF/Form/IssueUpdate.php:66 +#: IDF/Form/ReviewCreate.php:83 +msgid "The \"upload_issue_path\" configuration variable was not set." +msgstr "Die Konfigurationsvariable \"upload_issue_path\" ist nicht gesetzt." + +#: IDF/Form/IssueCreate.php:86 IDF/Form/IssueUpdate.php:76 +msgid "Attach a file" +msgstr "Datei anhängen" + +#: IDF/Form/IssueCreate.php:99 IDF/Form/IssueUpdate.php:89 +#: IDF/Form/ReviewCreate.php:103 IDF/Form/ReviewFileComment.php:83 +#: IDF/Views/Issue.php:63 IDF/Views/Issue.php:222 IDF/Views/Issue.php:304 +#: IDF/Views/Issue.php:392 IDF/Views/Issue.php:544 IDF/Views/Issue.php:767 +#: IDF/Views/Issue.php:826 IDF/Views/Review.php:59 IDF/Views/User.php:84 +msgid "Status" +msgstr "Status" + +#: IDF/Form/IssueCreate.php:108 IDF/Form/IssueUpdate.php:99 +msgid "Owner" +msgstr "Eigentümer" + +#: IDF/Form/IssueCreate.php:118 IDF/Form/IssueUpdate.php:112 +#: IDF/Form/IssueUpdate.php:129 +msgid "This issue" +msgstr "Dieses Ticket" + +#: IDF/Form/IssueCreate.php:210 +msgid "You cannot add a label with the \"Status\" prefix to an issue." +msgstr "" +"Du kannst keine Marke mit dem Präfix \"Status\" zu einem Ticket hinzufügen." + +#: IDF/Form/IssueCreate.php:211 IDF/Form/IssueCreate.php:218 +#: IDF/Form/UpdateUpload.php:110 IDF/Form/Upload.php:121 +#: IDF/Form/WikiPageCreate.php:151 IDF/Form/WikiPageUpdate.php:162 +msgid "You provided an invalid label." +msgstr "Du hast eine ungültige Marke angegeben." + +#: IDF/Form/IssueCreate.php:217 IDF/Form/UpdateUpload.php:109 +#, php-format +msgid "You cannot provide more than one label from the %s class to an issue." +msgstr "" +"Du kannst nicht mehr als eine Marke von der %s-Klasse zu einem Ticket " +"hinzufügen." + +#: IDF/Form/IssueCreate.php:228 IDF/Form/IssueUpdate.php:194 +msgid "You need to provide a description of the issue." +msgstr "Bitte füge eine Beschreibung des Problems an." + +#: IDF/Form/IssueCreate.php:251 IDF/Form/ReviewCreate.php:159 +msgid "You provided an invalid status." +msgstr "Du hast einen ungültigen Status angegeben." + +#: IDF/Form/IssueCreate.php:272 +msgid "You provided an invalid relation type." +msgstr "Du hast einen ungültigen Verknüpfungstyp angegeben." + +#: IDF/Form/IssueCreate.php:294 +#, php-format +msgid "The value \"%s\" is not a valid issue id." +msgstr "Der Wert \"%s\" ist keine gültige Ticket-ID." + +#: IDF/Form/IssueCreate.php:300 +#, php-format +msgid "The issue \"%s\" does not exist." +msgstr "Das Ticket \"%s\" existiert nicht." + +#: IDF/Form/IssueTrackingConf.php:86 +msgid "is related to" +msgstr "steht in Verbindung mit" + +#: IDF/Form/IssueTrackingConf.php:87 +msgid "blocks" +msgstr "blockiert" + +#: IDF/Form/IssueTrackingConf.php:88 +msgid "is blocked by" +msgstr "wird blockiert von" + +#: IDF/Form/IssueTrackingConf.php:89 +msgid "duplicates" +msgstr "dupliziert" + +#: IDF/Form/IssueTrackingConf.php:90 +msgid "is duplicated by" +msgstr "wird dupliziert von" + +#: IDF/Form/IssueTrackingConf.php:97 +msgid "" +"Define an issue template to hint the reporter to provide certain information" +msgstr "" +"Definiere eine Ticket-Vorlage, um dem Ersteller Hinweise auf benötigte " +"Informationen zu geben" + +#: IDF/Form/IssueTrackingConf.php:106 +msgid "Open issue status values" +msgstr "Statuswerte für offene Tickets" + +#: IDF/Form/IssueTrackingConf.php:114 +msgid "Closed issue status values" +msgstr "Statuswerte für geschlossene Tickets" + +#: IDF/Form/IssueTrackingConf.php:123 +msgid "Predefined issue labels" +msgstr "Vordefinierte Ticket-Marken" + +#: IDF/Form/IssueTrackingConf.php:125 +msgid "" +"The first \"Type:\" and \"Priority:\" entries found in this list are " +"automatically chosen as defaults for new issues." +msgstr "" +"Die ersten \"Type:\"- und \"Priority:\"-Einträge, die in dieser Liste " +"gefunden werden, werden automatisch als Standardwerte für neue Tickets " +"übernommen." + +#: IDF/Form/IssueTrackingConf.php:133 +msgid "Each issue may have at most one label with each of these classes." +msgstr "Jedes Ticket darf maximal eine Marke von jeder dieser Klassen haben." + +#: IDF/Form/IssueTrackingConf.php:140 +msgid "Issue relations" +msgstr "Ticketverknüpfungen" + +#: IDF/Form/IssueTrackingConf.php:142 +msgid "" +"You can define bidirectional relations like \"is related to\" or \"blocks, " +"is blocked by\". For standard relations pre-configured translations exist, " +"new relations should however be defined in a language that is understood by " +"all project members." +msgstr "" +"Du kannst bidirektionale Beziehungen, wie \"is related to\" oder \"blocks, " +"is blocked by\", definieren. Für Standard-Beziehungen existieren " +"vorkonfigurierte Übersetzungen, neue Beziehungen sollten jedoch in einer " +"Sprache definiert werden, die von allen Projektmitgliedern verstanden wird." + +#: IDF/Form/IssueUpdate.php:56 IDF/Form/ReviewFileComment.php:45 +#: IDF/Form/WikiPageUpdate.php:82 IDF/Form/WikiResourceUpdate.php:66 +msgid "Comment" +msgstr "Kommentar" + +#: IDF/Form/IssueUpdate.php:316 +msgid "No changes were entered." +msgstr "Keine Änderung festgestellt." + +#: IDF/Form/MembersConf.php:104 +#, php-format +msgid "The following login is invalid: %s." +msgid_plural "The following logins are invalid: %s." +msgstr[0] "Der folgende Anmeldename ist ungültig: %s." +msgstr[1] "Die folgenden Anmeldenamen sind ungültig: %s." + +#: IDF/Form/Password.php:34 +msgid "Your login or email" +msgstr "Dein Anmeldename oder E-Mail" + +#: IDF/Form/Password.php:35 +msgid "Provide either your login or your email to recover your password." +msgstr "" +"Gib bitte entweder Deinen Anmeldenamen oder Deine E-Mail an, um Dein " +"Passwort wiederherzustellen." + +#: IDF/Form/Password.php:49 IDF/Form/Password.php:64 +msgid "" +"Sorry, we cannot find a user with this email address or login. Feel free to " +"try again." +msgstr "" +"Entschuldigung, aber wir können keinen Benutzer mit dieser E-Mail-Adresse " +"oder diesen Anmeldenamen finden. Probier es ruhig noch einmal." + +#: IDF/Form/Password.php:100 +msgid "Password Recovery - InDefero" +msgstr "Passwortwiederherstellung - InDefero" + +#: IDF/Form/PasswordInputKey.php:36 IDF/Form/PasswordReset.php:39 +#: IDF/Form/UserChangeEmail.php:36 +msgid "Your verification key" +msgstr "Dein Validierungsschlüssel" + +#: IDF/Form/PasswordInputKey.php:50 IDF/Form/PasswordReset.php:89 +msgid "" +"We are sorry but this validation key is not valid. Maybe you should directly " +"copy/paste it from your validation email." +msgstr "" +"Dieser Validierungsschlüssel ist leider nicht gültig. Du kannst versuchen, " +"ihn aus der E-Mail zu kopieren." + +#: IDF/Form/PasswordInputKey.php:61 IDF/Form/PasswordReset.php:100 +msgid "" +"Sorry, but this verification key has expired, please restart the password " +"recovery sequence. For security reasons, the verification key is only valid " +"24h." +msgstr "" +"Dieser Validierungsschlüssel ist nicht mehr gültig, bitte fordere erneut ein " +"neues Kennwort an. Aus Sicherheitsgründen gilt ein Validierungsschlüssel nur " +"für 24 Stunden." + +#: IDF/Form/PasswordInputKey.php:76 IDF/Form/PasswordReset.php:108 +#: IDF/Form/RegisterConfirmation.php:137 IDF/Form/RegisterInputKey.php:72 +msgid "Cannot save an invalid form." +msgstr "Kann keine ungültige Maske speichern." + +#: IDF/Form/PasswordReset.php:45 IDF/Form/RegisterConfirmation.php:69 +#: IDF/Form/UserAccount.php:77 +msgid "Your password" +msgstr "Dein Passwort" + +#: IDF/Form/PasswordReset.php:48 IDF/Form/UserAccount.php:80 +msgid "" +"Your password must be hard for other people to find it, but easy for you to " +"remember." +msgstr "" +"Dein Passwort muss für andere Leute schwer zu erraten, aber für Dich leicht " +"zu merken sein." + +#: IDF/Form/PasswordReset.php:56 IDF/Form/RegisterConfirmation.php:80 +#: IDF/Form/UserAccount.php:89 +msgid "Confirm your password" +msgstr "Bestätige Dein Passwort" + +#: IDF/Form/PasswordReset.php:74 IDF/Form/RegisterConfirmation.php:122 +msgid "The two passwords must be the same." +msgstr "Beide Passwortangaben müssen identisch sein." + +#: IDF/Form/PasswordReset.php:77 +msgid "" +"This account is not active. Please contact the forge administrator to " +"activate it." +msgstr "" +"Das Benutzerkonto ist nicht aktiv. Bitte kontaktiere den Administrator für " +"die Freischaltung." + +#: IDF/Form/ProjectConf.php:43 +msgid "Short Description" +msgstr "Kurzbeschreibung" + +#: IDF/Form/ProjectConf.php:85 +msgid "The \"upload_path\" configuration variable was not set." +msgstr "Die Konfigurationsvariable \"upload_path\" ist nicht gesetzt." + +#: IDF/Form/ProjectConf.php:90 +msgid "Update the logo" +msgstr "Aktualisiere das Logo" + +#: IDF/Form/ProjectConf.php:92 +msgid "The logo must be a picture with a size of 32 by 32." +msgstr "Das Logo muss ein Bild der Größe 32 x 32 sein." + +#: IDF/Form/ProjectConf.php:103 +msgid "Remove the current logo" +msgstr "Entferne das derzeitige Logo" + +#: IDF/Form/ProjectConf.php:139 +msgid "Could not determine the size of the uploaded picture." +msgstr "Konnte die Größe des hochgeladenen Bildes nicht bestimmen." + +#: IDF/Form/ProjectConf.php:143 +msgid "The picture must have a size of 32 by 32." +msgstr "Das Bild muss eine Größe von 32 x 32 haben." + +#: IDF/Form/ProjectConf.php:164 +msgid "The entered URL is invalid. Only http and https URLs are allowed." +msgstr "" +"Die eingegebene URL ist ungültig. Nur http- und https-URLs sind erlaubt." + +#: IDF/Form/Register.php:41 +msgid "Your login" +msgstr "Dein Anmeldename" + +#: IDF/Form/Register.php:45 +msgid "" +"The login must be between 3 and 15 characters long and contain only letters " +"and digits." +msgstr "" +"Der Anmeldename muss zwischen 3 und 15 Zeichen lang sein und darf nur " +"Buchstaben und Zahlen beinhalten." + +#: IDF/Form/Register.php:53 IDF/Form/UserAccount.php:59 +msgid "Your email" +msgstr "Deine E-Mail-Adresse" + +#: IDF/Form/Register.php:55 +msgid "We will never send you any unsolicited emails. We hate spam too!" +msgstr "" +"Wir werden Ihnen nie unangeforderte E-Mails zusenden. Wir hassen Spam " +"ebenfalls." + +#: IDF/Form/Register.php:60 +msgid "I agree to the terms and conditions." +msgstr "Ich stimme den Nutzungbedingungen zu." + +#: IDF/Form/Register.php:88 +msgid "" +"We know, this is boring, but you need to agree with the terms and conditions." +msgstr "Ja, es ist nervig, aber Du musst den Nutzungsbedingungen zustimmen." + +#: IDF/Form/Register.php:97 +#, php-format +msgid "" +"The email \"%1$s\" is already used. If you need to, you can recover your password." +msgstr "" +"Die E-Mail-Adresse \"%1$s\" wird bereits genutzt. Wenn Du musst, kannst Du " +"hier das Passwort zurückzusetzen." + +#: IDF/Form/Register.php:148 +msgid "Confirm the creation of your account." +msgstr "Bestätige die Erstellung Deines Benutzerkontos." + +#: IDF/Form/RegisterConfirmation.php:40 IDF/Form/RegisterInputKey.php:36 +msgid "Your confirmation key" +msgstr "Dein Bestätigungs-Schlüssel" + +#: IDF/Form/RegisterConfirmation.php:72 +msgid "" +"Your password must be hard for other people to guess, but easy for you to " +"remember." +msgstr "" +"Dein Passwort muss für andere Leute schwer zu erraten, aber für Dich leicht " +"zu merken sein." + +#: IDF/Form/RegisterConfirmation.php:99 IDF/Form/RegisterInputKey.php:50 +msgid "" +"We are sorry but this confirmation key is not valid. Maybe you should " +"directly copy/paste it from your confirmation email." +msgstr "" +"Dieser Validierungsschlüssel ist leider nicht gültig. Du kannst versuchen, " +"ihn aus der E-Mail zu kopieren." + +#: IDF/Form/RegisterConfirmation.php:110 +#, php-format +msgid "" +"This account has already been confirmed. Maybe should you try to recover your password." +msgstr "" +"Dieses Benutzerkonto wurde bereits bestätigt. Vielleicht möchtest Du " +"versuchen, Dein Passwort hier wiederherzustellen?" + +#: IDF/Form/ReviewCreate.php:74 IDF/gettexttemplates/idf/source/base.html.php:5 +#: IDF/gettexttemplates/idf/source/changelog.html.php:7 +msgid "Commit" +msgstr "Revision" + +#: IDF/Form/ReviewCreate.php:92 +msgid "Patch" +msgstr "Patch" + +#: IDF/Form/ReviewCreate.php:119 +msgid "We were not able to parse your patch. Please provide a valid patch." +msgstr "" +"Dein Patch konnte nicht analysiert werden. Bitte gib ein gültiges Patch an." + +#: IDF/Form/ReviewCreate.php:128 +msgid "You provided an invalid commit." +msgstr "Du hast eine ungültige Revision angegeben." + +#: IDF/Form/ReviewCreate.php:202 +msgid "Initial patch to be reviewed." +msgstr "Initiales, zu begutachtendes Patch." + +#: IDF/Form/ReviewFileComment.php:56 +msgid "General comment" +msgstr "Allgemeiner Kommentar" + +#: IDF/Form/ReviewFileComment.php:113 +msgid "" +"You need to provide your general comment about the proposal, or comments on " +"at least one file." +msgstr "" +"Du musst einen allgemeinen Kommentar zu dem Vorschlag angeben oder " +"mindestens eine Datei kommentieren." + +#: IDF/Form/ReviewFileComment.php:124 +msgid "The status have been updated." +msgstr "Der Status wurde aktualisiert." + +#: IDF/Form/ReviewFileComment.php:130 +msgid "This field is required." +msgstr "Dieses Feld wird benötigt." + +#: IDF/Form/SourceConf.php:54 IDF/Form/UploadConf.php:70 +msgid "Webhook URL" +msgstr "Web-Hook-URL" + +#: IDF/Form/TabsConf.php:38 IDF/gettexttemplates/idf/admin/base.html.php:4 +#: IDF/gettexttemplates/idf/base-full.html.php:8 +#: IDF/gettexttemplates/idf/base-full.html~.php:7 +#: IDF/gettexttemplates/idf/base.html.php:8 +#: IDF/gettexttemplates/idf/base.html~.php:7 +#: IDF/gettexttemplates/idf/downloads/base.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:14 +#: IDF/Views/Project.php:97 +msgid "Downloads" +msgstr "Downloads" + +#: IDF/Form/TabsConf.php:39 IDF/gettexttemplates/idf/base-full.html.php:12 +#: IDF/gettexttemplates/idf/base-full.html~.php:11 +#: IDF/gettexttemplates/idf/base.html.php:12 +#: IDF/gettexttemplates/idf/base.html~.php:11 +msgid "Code Review" +msgstr "Code-Besprechung" + +#: IDF/Form/TabsConf.php:40 IDF/gettexttemplates/idf/admin/base.html.php:5 +#: IDF/gettexttemplates/idf/base-full.html.php:9 +#: IDF/gettexttemplates/idf/base-full.html~.php:8 +#: IDF/gettexttemplates/idf/base.html.php:9 +#: IDF/gettexttemplates/idf/base.html~.php:8 +msgid "Documentation" +msgstr "Dokumentation" + +#: IDF/Form/TabsConf.php:41 IDF/gettexttemplates/idf/admin/base.html.php:7 +#: IDF/gettexttemplates/idf/base-full.html.php:11 +#: IDF/gettexttemplates/idf/base-full.html~.php:10 +#: IDF/gettexttemplates/idf/base.html.php:11 +#: IDF/gettexttemplates/idf/base.html~.php:10 +msgid "Source" +msgstr "Quellcode" + +#: IDF/Form/TabsConf.php:42 IDF/gettexttemplates/idf/base-full.html.php:10 +#: IDF/gettexttemplates/idf/base-full.html~.php:9 +#: IDF/gettexttemplates/idf/base.html.php:10 +#: IDF/gettexttemplates/idf/base.html~.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:17 +msgid "Issues" +msgstr "Tickets" + +#: IDF/Form/TabsConf.php:50 +msgid "Open to all" +msgstr "Für alle offen" + +#: IDF/Form/TabsConf.php:51 +msgid "Signed in users" +msgstr "Angemeldete Benutzer" + +#: IDF/Form/TabsConf.php:54 +msgid "Closed" +msgstr "Geschlossen" + +#: IDF/Form/TabsConf.php:84 +msgid "Others" +msgstr "Andere" + +#: IDF/Form/TabsConf.php:107 +msgid "Extra authorized users" +msgstr "Weitere autorisierte Benutzer" + +#: IDF/Form/Upload.php:59 IDF/Form/WikiResourceCreate.php:65 +#: IDF/Form/WikiResourceUpdate.php:56 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:7 +#: IDF/Views/Download.php:64 IDF/Views/Download.php:346 +msgid "File" +msgstr "Datei" + +#: IDF/Form/Upload.php:87 IDF/Form/WikiResourceCreate.php:96 +#: IDF/Form/WikiResourceUpdate.php:83 +msgid "For security reasons, you cannot upload a file with this extension." +msgstr "" +"Aus Sicherheitsgründen kannst Du keine Dateien mit dieser Erweiterung " +"hochladen." + +#: IDF/Form/Upload.php:120 +#, php-format +msgid "You cannot provide more than one label from the %s class to a download." +msgstr "" +"Du darfst nicht mehr als eine Marke von der %s-Klasse zu einem Download " +"hinzufügen." + +#: IDF/Form/UploadArchive.php:41 +msgid "Archive file" +msgstr "Archiv-Datei" + +#: IDF/Form/UploadArchive.php:67 +#, php-format +msgid "" +"For security reasons, you cannot upload a file (%s) with this extension." +msgstr "" +"Aus Sicherheitsgründen kannst Du keine Datei (%s) mit dieser Erweiterung " +"hochladen." + +#: IDF/Form/UploadArchive.php:98 +#, php-format +msgid "" +"You cannot provide more than label from the %1$s class to a download (%2$s)." +msgstr "" +"Du kannst nicht mehr als eine Marke von der %1$s-Klasse zu einem Download " +"hinzufügen (%2$s)." + +#: IDF/Form/UploadArchive.php:109 +#, php-format +msgid "" +"A file with the name \"%s\" has already been uploaded and is not marked to " +"be replaced." +msgstr "" +"Eine Datei mit dem Namen \"%s\" wurde bereits hochgeladen und wurde nicht " +"zum Ersetzen markiert." + +#: IDF/Form/UploadArchiveHelper.php:41 +msgid "The archive does not exist." +msgstr "Das Archiv existiert nicht." + +#: IDF/Form/UploadArchiveHelper.php:48 +#, php-format +msgid "The archive could not be read (code %d)." +msgstr "Das Archiv konnte nicht gelesen werden (Code %d)." + +#: IDF/Form/UploadArchiveHelper.php:53 +msgid "The archive does not contain a manifest.xml." +msgstr "Das Archiv beinhaltet keine manifest.xml." + +#: IDF/Form/UploadArchiveHelper.php:61 +#, php-format +msgid "The archive's manifest is invalid: %s" +msgstr "Das manifest des Archivs ist ungültig: %s" + +#: IDF/Form/UploadArchiveHelper.php:77 +#, php-format +msgid "The entry %d in the manifest is missing a file name." +msgstr "Dem Eintrag %d im Manifest fehlt ein Dateiname." + +#: IDF/Form/UploadArchiveHelper.php:82 +#, php-format +msgid "The entry %d in the manifest is missing a summary." +msgstr "Dem Eintrag %d im Manifest fehlt eine Zusammenfassung." + +#: IDF/Form/UploadArchiveHelper.php:86 +msgid "The manifest must not reference itself." +msgstr "Das Manifest darf sich nicht selbst referenzieren." + +#: IDF/Form/UploadArchiveHelper.php:91 +#, php-format +msgid "The entry %s in the manifest does not exist in the archive." +msgstr "Der Eintrag %s im Manifest existiert nicht im Archiv." + +#: IDF/Form/UploadArchiveHelper.php:96 +#, php-format +msgid "The entry %s in the manifest is referenced more than once." +msgstr "Der Eintrag %s im Manifest wird mehr als einmal referenziert." + +#: IDF/Form/UploadArchiveHelper.php:108 +#, php-format +msgid "The entry %s in the manifest has more than the six allowed labels set." +msgstr "" +"Der Eintrag %s im Manifest hat mehr als die erlaubten sechs Marken gesetzt." + +#: IDF/Form/UploadConf.php:53 +msgid "Predefined download labels" +msgstr "Vordefinierte Marken für Downloads" + +#: IDF/Form/UploadConf.php:62 +msgid "Each download may have at most one label with each of these classes" +msgstr "Jeder Download darf maximal eine Marke von jeder dieser Klassen haben" + +#: IDF/Form/UserAccount.php:61 +msgid "" +"If you change your email address, an email will be sent to the new address " +"to confirm it." +msgstr "" +"Falls Du Deine E-Mail-Adresse änderst, wird eine E-Mail zur Bestätigung an " +"die neue Adresse versandt." + +#: IDF/Form/UserAccount.php:80 +msgid "Leave blank if you do not want to change your password." +msgstr "Leer lassen, falls Du Dein Passwort nicht ändern willst." + +#: IDF/Form/UserAccount.php:166 +msgid "" +"Paste an SSH or monotone public key. Be careful to not provide your private " +"key here!" +msgstr "" +"Füge einen öffentlichen SSH- oder monotone-Schlüssel hier ein. Pass auf, " +"dass Du nicht versehentlich Deinen privaten Schlüssel hier hineinkopierst!" + +#: IDF/Form/UserAccount.php:171 +msgid "Add a secondary email address" +msgstr "Füge eine sekundäre E-Mail-Adresse hinzu" + +#: IDF/Form/UserAccount.php:173 +msgid "You will get an email to confirm that you own the address you specify." +msgstr "" +"Du erhälst eine E-Mail, um zu bestätigen, das die angegebene Adresse Dir " +"gehört." + +#: IDF/Form/UserAccount.php:200 +msgid "Confirm your new email address." +msgstr "Bestätigung der neuen E-Mail-Adresse" + +#: IDF/Form/UserAccount.php:203 +#, php-format +msgid "" +"A validation email has been sent to \"%s\" to validate the email address " +"change." +msgstr "" +"Eine Validierungs-E-Mail wurde an \"%s\" versandt, um die Adressänderung zu " +"überprüfen." + +#: IDF/Form/UserAccount.php:341 +msgid "" +"Please check the key as it does not appear to be a valid SSH public key." +msgstr "" +"Bitte überprüfe den Schlüssel, er scheint kein gültiger öffentlicher " +"SSH-Schlüssel zu sein." + +#: IDF/Form/UserAccount.php:363 +msgid "" +"Please check the key as it does not appear to be a valid monotone public key." +msgstr "" +"Bitte überprüfe den Schlüssel, er scheint kein gültiger öffentlicher " +"monotone-Schlüssel zu sein." + +#: IDF/Form/UserAccount.php:371 +msgid "Public key looks like neither an SSH nor monotone public key." +msgstr "" +"Der öffentliche Schlüssel sieht weder wie ein öffentlicher SSH- noch ein " +"öffentlicher monotone-Schlüssel aus." + +#: IDF/Form/UserAccount.php:383 +msgid "You already have uploaded this key." +msgstr "Du hast diesen Schlüssel bereits hochgeladen." + +#: IDF/Form/UserChangeEmail.php:63 +msgid "" +"The validation key is not valid. Please copy/paste it from your confirmation " +"email." +msgstr "" +"Der Validierungsschlüssel ist ungültig. Bitte kopiere ihn von Deiner " +"Bestätigungs-E-Mail hier hinein." + +#: IDF/Form/WikiConf.php:49 +msgid "Predefined documentation page labels" +msgstr "Vordefinierte Marken für Dokumentations-Seiten" + +#: IDF/Form/WikiConf.php:58 +msgid "" +"Each documentation page may have at most one label with each of these classes" +msgstr "" +"Jede Dokumentations-Seite darf maximal eine Marke von jeder dieser Klassen " +"haben" + +#: IDF/Form/WikiPageCreate.php:38 +msgid "" +"# Introduction\n" +"\n" +"Add your content here.\n" +"\n" +"\n" +"# Details\n" +"\n" +"Add your content here. Format your content with:\n" +"\n" +"* Text in **bold** or *italic*.\n" +"* Headings, paragraphs, and lists.\n" +"* Links to other [[WikiPage]].\n" +msgstr "" +"# Einführung\n" +"\n" +"Füge Deinen Inhalt hier ein.\n" +"\n" +"\n" +"# Details\n" +"\n" +"Füge Deinen Inhalt hier ein. Formatiere Deinen Inhalt mit:\n" +"\n" +"* Text in **Fettschrift** oder *kursiv*.\n" +"* Überschriften, Absätzen und Listen.\n" +"* Links auf andere [[WikiSeiten]].\n" + +#: IDF/Form/WikiPageCreate.php:57 +msgid "PageName" +msgstr "Seitenname" + +#: IDF/Form/WikiPageCreate.php:60 IDF/Form/WikiPageUpdate.php:50 +msgid "Page title" +msgstr "Seitentitel" + +#: IDF/Form/WikiPageCreate.php:66 IDF/Form/WikiPageUpdate.php:56 +msgid "" +"The page name must contains only letters, digits and the dash (-) character." +msgstr "" +"Der Seitenname darf nur aus Buchstaben, Ziffern und dem Bindestrich bestehen." + +#: IDF/Form/WikiPageCreate.php:71 IDF/Form/WikiPageUpdate.php:61 +msgid "This one line description is displayed in the list of pages." +msgstr "Diese einzeilige Beschreibung wird in der Seitenübersicht angezeigt." + +#: IDF/Form/WikiPageCreate.php:108 IDF/Form/WikiPageUpdate.php:119 +#: IDF/Form/WikiResourceCreate.php:78 +msgid "The title contains invalid characters." +msgstr "Der Titel beinhaltet ungültige Zeichen." + +#: IDF/Form/WikiPageCreate.php:114 IDF/Form/WikiPageUpdate.php:125 +msgid "A page with this title already exists." +msgstr "Eine Seite mit diesem Titel existiert bereits." + +#: IDF/Form/WikiPageCreate.php:150 IDF/Form/WikiPageUpdate.php:161 +#, php-format +msgid "You cannot provide more than one label from the %s class to a page." +msgstr "" +"Du darfst nicht mehr als eine Marke von der %s-Klasse zu einer Seite " +"hinzufügen." + +#: IDF/Form/WikiPageCreate.php:200 +msgid "Initial page creation" +msgstr "Initiale Seiten-Erzeugung" + +#: IDF/Form/WikiPageDelete.php:39 +msgid "Yes, I understand that the page and all its revisions will be deleted." +msgstr "" +"Ja, ich habe verstanden, dass die Seite und all ihre Versionen gelöscht " +"werden." + +#: IDF/Form/WikiPageDelete.php:50 IDF/Form/WikiResourceDelete.php:50 +msgid "You need to confirm the deletion." +msgstr "Du musst die Löschung bestätigen." + +#: IDF/Form/WikiPageUpdate.php:83 IDF/Form/WikiResourceUpdate.php:67 +msgid "One line to describe the changes you made." +msgstr "Einzeilige Beschreibung der durchgeführten Änderungen." + +#: IDF/Form/WikiResourceCreate.php:40 +msgid "ResourceName" +msgstr "NameDerRessource" + +#: IDF/Form/WikiResourceCreate.php:44 +msgid "Resource title" +msgstr "Titel der Ressource" + +#: IDF/Form/WikiResourceCreate.php:50 +msgid "" +"The resource name must contains only letters, digits and the dash (-) " +"character." +msgstr "" +"Der Ressourcenname darf nur aus Buchstaben, Ziffern und dem Bindestrich " +"bestehen." + +#: IDF/Form/WikiResourceCreate.php:55 IDF/Form/WikiResourceUpdate.php:47 +msgid "This one line description is displayed in the list of resources." +msgstr "" +"Diese einzeilige Beschreibung wird in der Ressourcenübersicht angezeigt." + +#: IDF/Form/WikiResourceCreate.php:84 +msgid "A resource with this title already exists." +msgstr "Eine Ressource mit diesem Titel existiert bereits." + +#: IDF/Form/WikiResourceCreate.php:142 +msgid "Initial resource creation" +msgstr "Initiale Ressourcen-Erstellung" + +#: IDF/Form/WikiResourceDelete.php:39 +msgid "" +"Yes, I understand that the resource and all its revisions will be deleted." +msgstr "" +"Ja, ich habe verstanden, dass die Ressource und all ihre Versionen gelöscht " +"werden." + +#: IDF/Form/WikiResourceUpdate.php:89 +#, php-format +msgid "" +"The mime type of the uploaded file \"%1$s\" does not match the mime type of " +"this resource \"%2$s\"" +msgstr "" +"Der MIME-Typ der hochgeladenen Datei \"%1$s\" passt nicht auf dem MIME-Typ " +"dieser Ressource, \"%2$s\"." + +#: IDF/Form/WikiResourceUpdate.php:97 +msgid "The current version of the resource and the uploaded file are equal." +msgstr "" +"Die derzeitige Version der Ressource und die hochgeladene Datei sind gleich." + +#: IDF/Gconf.php:60 IDF/Search/Occ.php:56 +msgid "model class" +msgstr "Modell-Klasse" + +#: IDF/Gconf.php:66 IDF/Search/Occ.php:62 +msgid "model id" +msgstr "Modell-ID" + +#: IDF/gettexttemplates/idf/admin/base.html.php:3 +msgid "Project Summary" +msgstr "Projekt-Zusammenfassung" + +#: IDF/gettexttemplates/idf/admin/base.html.php:6 +msgid "Issue Tracking" +msgstr "Ticketverfolgung" + +#: IDF/gettexttemplates/idf/admin/base.html.php:8 +msgid "Project Members" +msgstr "Projektmitglieder" + +#: IDF/gettexttemplates/idf/admin/base.html.php:9 +msgid "Tabs Access and Notifications" +msgstr "Zugriffsrechte und Benachrichtigungen" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:3 +#: IDF/gettexttemplates/idf/admin/issue-tracking.html.php:3 +#: IDF/gettexttemplates/idf/admin/wiki.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/labels.html.php:3 +msgid "" +"\n" +"

Instructions:

\n" +"

List one status value per line in desired sort-order.

\n" +"

Optionally, use an equals-sign to document the meaning of each status " +"value.

\n" +msgstr "" +"\n" +"

Anleitung:

\n" +"

Füge einen Statuswert pro Zeile in der gewünschten Reihenfolge " +"hinzu.

\n" +"

Füge optional nach einem Istgleich-Zeichen (=) eine kurze Beschreibung " +"ein, um die Bedeutung des Statuswerts zu beschreiben.

\n" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:8 +#, qt-format +msgid "" +"

The webhook URL setting specifies an URL to which a HTTP " +"PUT\n" +"request is sent after a new download has been added or to which a HTTP " +"POST\n" +"request is sent after an existing download has been updated.\n" +"If this field is empty, notifications are disabled.

\n" +"\n" +"

Only properly-escaped HTTP URLs are supported, for " +"example:

\n" +"\n" +"
    \n" +"
  • http://domain.com/upload
  • \n" +"
  • http://domain.com/upload?my%20param
  • \n" +"
\n" +"\n" +"

In addition, the URL may contain the following \"%\" notation, which\n" +"will be replaced with specific project values for each download:

\n" +"\n" +"
    \n" +"
  • %p - project name
  • \n" +"
  • %d - download id
  • \n" +"
\n" +"\n" +"

For example, updating download 123 of project 'my-project' with\n" +"web hook URL http://mydomain.com/%p/%d would send a POST " +"request to\n" +"http://mydomain.com/my-project/123.

" +msgstr "" +"

Die Web-Hook-Adresse gibt eine URL an, zu welcher eine HTTP " +"PUT-\n" +"Anfrage nach jedem neu hinzugefügten Download oder zu welcher eine HTTP " +"POST-\n" +"Anfrage nach jeder Aktualisierung eines existierenden Downloads ausgelöst " +"wird.\n" +"Wenn dieses Feld leer ist, sind diese Art von Benachrichtigungen\n" +"deaktiviert.

\n" +"\n" +"

Nur korrekt maskierte HTTP-URLs werden unterstützt, zum " +"Beispiel:

\n" +"\n" +"
    \n" +"
  • http://domain.com/upload
  • \n" +"
  • http://domain.com/upload?my%20param
  • \n" +"
\n" +"\n" +"

Zusätzlich darf die URL die folgenden Platzhalter beinhalten, welche\n" +"für jeden Download mit den spezifischen Projektwerten ersetzt werden:

\n" +"\n" +"
    \n" +"
  • %p - Projektname
  • \n" +"
  • %d - Downloadnummer
  • \n" +"
\n" +"\n" +"

Beispiel: Wenn der Download 123 des Projekts 'mein-projekt' aktualisiert " +"werden würde und die Web-Hook-Adresse URL " +"http://meine-domain.com/%p/%d konfiguriert wäre, dann würde " +"eine POST-Anfrage an http://meine-domain.com/mein-projekt/123 " +"gesendet.

" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:31 +#: IDF/gettexttemplates/idf/admin/source.html.php:30 +msgid "Web-Hook authentication key:" +msgstr "Web-Hook-Authentifizierungs-Schlüssel:" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:32 +#: IDF/gettexttemplates/idf/admin/issue-tracking.html.php:8 +#: IDF/gettexttemplates/idf/admin/members.html.php:13 +#: IDF/gettexttemplates/idf/admin/source.html.php:31 +#: IDF/gettexttemplates/idf/admin/summary.html.php:11 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:12 +#: IDF/gettexttemplates/idf/admin/wiki.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/forge/index.html.php:13 +#: IDF/gettexttemplates/idf/gadmin/projects/labels.html.php:8 +msgid "Save Changes" +msgstr "Änderungen speichern" + +#: IDF/gettexttemplates/idf/admin/members.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:3 +msgid "" +"\n" +"

Instructions:

\n" +"

Specify each person by its login. Each person must have already " +"registered with the given login.

\n" +"

Separate the logins with commas and/or new lines.

\n" +msgstr "" +"\n" +"

Anleitung:

\n" +"

Gib jede Person mit ihrem Anmeldenamen ein. Jede Person muss sich bereits " +"mit dem angegebenen Namen registriert haben.

\n" +"

Trenne die Anmeldenamen durch Kommas und / oder neue Zeilen.

\n" + +#: IDF/gettexttemplates/idf/admin/members.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:8 +msgid "" +"\n" +"

Notes:

\n" +"

A project owner may make any change to this project, including removing " +"other project owners. You need to be carefull when you give owner " +"rights.

\n" +"

A project member will not have access to the administration area but will " +"have more options available in the use of the project.

\n" +msgstr "" +"\n" +"

Hinweise:

\n" +"

Ein Projekteigentümer kann jedwede Änderung an diesem Projekt vornehmen, " +"inklusive dem Enfernen von anderen Projekteigentümern. Deshalb solltest Du " +"mit der Vergabe von Eigentumsrechten vorsichtig sein.

\n" +"

Ein Projektmitglied hat keinen Zugriff auf die Administrationsebene, aber " +"hat bei der Benutzung des Projektes mehr verfügbare Optionen.

\n" + +#: IDF/gettexttemplates/idf/admin/source.html.php:3 +msgid "You can find here the current repository configuration of your project." +msgstr "Hier findest Du die derzeitige Depot-Konfiguration Deines Projektes." + +#: IDF/gettexttemplates/idf/admin/source.html.php:4 +#, qt-format +msgid "" +"

The webhook URL setting specifies an URL to which a HTTP \n" +"%%hook_request_method%% request is sent after each " +"repository\n" +"commit. If this field is empty, notifications are disabled.

\n" +"\n" +"

Only properly-escaped HTTP URLs are supported, for " +"example:

\n" +"\n" +"
    \n" +"
  • http://domain.com/commit
  • \n" +"
  • http://domain.com/commit?my%20param
  • \n" +"
\n" +"\n" +"

In addition, the URL may contain the following \"%\" notation, which\n" +"will be replaced with specific project values for each commit:

\n" +"\n" +"
    \n" +"
  • %p - project name
  • \n" +"
  • %r - revision number
  • \n" +"
\n" +"\n" +"

For example, committing revision 123 to project 'my-project' with\n" +"post-commit URL http://mydomain.com/%p/%r would send a request " +"to\n" +"http://mydomain.com/my-project/123.

" +msgstr "" +"

Die Web-Hook-Adresse gibt eine URL an, zu welcher eine HTTP " +"%%hook_request_method%%-\n" +"Anfrage nach jeder neuen Revision eines Depot ausgelöst wird.\n" +"Wenn dieses Feld leer ist, sind diese Art von Benachrichtigungen\n" +"deaktiviert.

\n" +"\n" +"

Nur korrekt maskierte HTTP-URLs werden unterstützt, zum " +"Beispiel:

\n" +"\n" +"
    \n" +"
  • http://domain.com/commit
  • \n" +"
  • http://domain.com/commit?my%20param
  • \n" +"
\n" +"\n" +"

Zusätzlich darf die URL die folgenden Platzhalter beinhalten, welche\n" +"für jede Revision mit den spezifischen Projektwerten ersetzt werden:

\n" +"\n" +"
    \n" +"
  • %p - Projektname
  • \n" +"
  • %r - Revisionsnummer
  • \n" +"
\n" +"\n" +"

Beispiel: Wenn die Revision 123 für das Projekt 'mein-projekt' zum Depot\n" +"gesandt wird und als post-commit-URL " +"http://meine-domain.com/%p/%r eingestellt\n" +"ist, würde eine Anfrage an " +"http://meine-domain.com/mein-projekt/123 gesendet.

" + +#: IDF/gettexttemplates/idf/admin/source.html.php:26 +msgid "" +"The form contains some errors. Please correct them to update the source " +"configuration." +msgstr "" +"Die Eingabemaske enthält einige Fehler. Bitte korrigiere diese, um die " +"Quellcode-Konfiguration zu aktualisieren." + +#: IDF/gettexttemplates/idf/admin/source.html.php:27 +msgid "Repository type:" +msgstr "Depot-Typ:" + +#: IDF/gettexttemplates/idf/admin/source.html.php:28 +msgid "Repository access:" +msgstr "Depot-Zugriff:" + +#: IDF/gettexttemplates/idf/admin/source.html.php:29 +msgid "Repository size:" +msgstr "Depot-Größe:" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

The description of the project can be improved using the Markdown syntax.

\n" +msgstr "" +"\n" +"

Anleitung:

\n" +"

Die Beschreibung des Projektes kann durch die Benutzung der Markdown-Syntax vereinfacht werden.

\n" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:7 +msgid "" +"The form contains some errors. Please correct them to update the summary." +msgstr "" +"Die Eingabemaske enthält einige Fehler. Bitte korrigiere diese, um die " +"Projektzusammenfassung zu aktualisieren." + +#: IDF/gettexttemplates/idf/admin/summary.html.php:8 +msgid "Current logo" +msgstr "Derzeitiges Logo" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:9 +#: IDF/gettexttemplates/idf/base-full.html.php:4 +#: IDF/gettexttemplates/idf/base-full.html~.php:4 +#: IDF/gettexttemplates/idf/base.html.php:4 +#: IDF/gettexttemplates/idf/base.html~.php:4 +#: IDF/gettexttemplates/idf/main-menu.html.php:8 +#: IDF/gettexttemplates/idf/project-list.html.php:4 +msgid "Project logo" +msgstr "Projekt-Logo" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:10 +msgid "Your project does not have a logo configured yet." +msgstr "Für Dein Projekt wurde noch kein Logo konfiguriert." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:3 +msgid "" +"This section allows you to configure project tabs access rights and " +"notifications." +msgstr "" +"Hier kannst Du den Zugriff auf die Projektfunktionen und Benachrichtungen " +"konfigurieren." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:4 +msgid "" +"Tab access controls whether a single user can navigate into a particular " +"section of your project via the main menu or automatically generated object " +"links." +msgstr "" +"Zugriffsberechtigungen bestimmen, ob ein bestimmter Nutzer in eine bestimmte " +"Sektion Deines Projekts über das Hauptmenü oder über automatisch generierte " +"Inhaltslinks gelangen kann." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:5 +msgid "" +"If you mark a project as private, only the project members and " +"administrators, together with the extra authorized users you provide will " +"have access to the project as a whole. You will still be able to define " +"further access rights for the different tabs but the \"Open to all\" and " +"\"Signed in users\" will default to authorized users only." +msgstr "" +"Wenn Du ein Projekt als privat markierst, haben nur Projektmitglieder und " +"Administratoren zusammen mit den von Dir extra authorisierten Benutzern " +"Zugriff darauf. Du kannst weiterhin zusätzliche Zugriffsrechte für bestimmte " +"Projektfunktionen vergeben, aber die Einstellungen \"Für alle offen\" und " +"\"Angemeldete Benutzer\" werden standardmäßig nur authorisierte Benutzer " +"berücksichtigen." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:6 +msgid "" +"For the extra authorized user list, specify each person by its login. Each " +"person must have already registered with the given login. Separate the " +"logins with commas and/or new lines." +msgstr "" +"Gib in der Liste der zusätzlich zu authorisierenden Nutzer für jede Person " +"ihren Anmeldenamen ein. Jede Person muss sich bereits mit diesem Namen " +"angemeldet haben. Trenne die Anmeldenamen durch Kommas und / oder neue " +"Zeilen." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:7 +msgid "" +"Only project members and admins have write access to the source. If you " +"restrict the access to the source, anonymous access is not provided and the " +"users must authenticate themselves with their password or SSH key." +msgstr "" +"Nur Projektmitglieder und Administratoren haben Schreibzugriff auf den " +"Quellcode. Wenn Du den Zugriff auf den Quellcode beschränkst, wird kein " +"anonymer Zugriff angeboten und die Benutzer müssen sich mit ihrem Passwort " +"oder öffentlichen Schlüssel authentifizieren." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:8 +#, php-format +msgid "" +"Here you can configure who should be notified about changes in a particular " +"section. You can also configure additional addresses, like the one of a " +"mailing list, that should be notified. (Keep in mind that you might have to " +"register the sender address %%from_email%% to let the " +"mailing list actually accept notification emails.) Multiple email addresses " +"must be separated through commas (',')." +msgstr "" +"Hier kannst Du konfigurieren, wer über Änderungen in einer bestimmten " +"Sektion benachrichtigt werden soll. Du kannst auch weitere E-Mail-Adressen, " +"wie etwa die einer Mailingliste, hier hinterlegen. (Vergiss nicht, dass Du " +"unter Umständen die Absender-Adresse %%from_email%% vorher " +"erst registrieren musst, bevor die Mailingliste Benachrichtigungs-E-Mails " +"akzeptiert.) Mehrere E-Mail-Adressen müssen durch Kommas (',') voneinander " +"getrennt werden." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:9 +msgid "" +"The form contains some errors. Please correct them to update the access " +"rights." +msgstr "" +"Die Eingabemaske enthält einige Fehler. Bitte korrigiere diese, um die " +"Zugriffsberechtigungen zu aktualisieren." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:10 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:13 +msgid "Access Rights" +msgstr "Zugriffsberechtigungen" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:11 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:14 +msgid "Notifications" +msgstr "Benachrichtigungen" + +#: IDF/gettexttemplates/idf/base-full.html.php:3 +#: IDF/gettexttemplates/idf/base-full.html~.php:3 +#: IDF/gettexttemplates/idf/base.html.php:3 +#: IDF/gettexttemplates/idf/base.html~.php:3 +#, php-format +msgid "" +"Sign in or create your account to create issues or " +"add comments" +msgstr "" +"Melde Dich an oder lege ein Benutzerkonto an, um " +"Tickets oder Kommentare hinzuzufügen" + +#: IDF/gettexttemplates/idf/base-full.html.php:6 +#: IDF/gettexttemplates/idf/base.html.php:6 +#: IDF/gettexttemplates/idf/project-list.html.php:6 +msgid "External link to project" +msgstr "Externer Link zum Projekt" + +#: IDF/gettexttemplates/idf/base-full.html.php:7 +#: IDF/gettexttemplates/idf/base-full.html~.php:6 +#: IDF/gettexttemplates/idf/base.html.php:7 +#: IDF/gettexttemplates/idf/base.html~.php:6 +msgid "Project Home" +msgstr "Projekt-Startseite" + +#: IDF/gettexttemplates/idf/base-full.html.php:13 +#: IDF/gettexttemplates/idf/base-full.html~.php:12 +#: IDF/gettexttemplates/idf/base.html.php:13 +#: IDF/gettexttemplates/idf/base.html~.php:12 +msgid "Project Management" +msgstr "Projekt-Management" + +#: IDF/gettexttemplates/idf/downloads/base.html.php:4 +#: IDF/gettexttemplates/idf/downloads/index.html.php:4 +#: IDF/Views/Download.php:235 +msgid "New Download" +msgstr "Neuer Download" + +#: IDF/gettexttemplates/idf/downloads/base.html.php:5 +msgid "Upload Archive" +msgstr "Archiv hochladen" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:3 +msgid "" +"Each file must have a distinct name and file contents\n" +"cannot be changed, so be sure to include release numbers in each file\n" +"name." +msgstr "" +"Jede Datei muss einen unterscheidbaren Namen haben und Dateiinhalte\n" +"können nicht geändert werden, also stelle sicher, dass Du Versionsnummern\n" +"in jedem Dateinamen verwendest." + +#: IDF/gettexttemplates/idf/downloads/create.html.php:6 +#, php-format +msgid "" +"You can use the Markdown syntax for the description." +msgstr "" +"Du kannst die Markdown-Syntax für die Beschreibung " +"nutzen." + +#: IDF/gettexttemplates/idf/downloads/create.html.php:7 +msgid "The form contains some errors. Please correct them to submit the file." +msgstr "" +"Die Eingabemaske enthält einige Fehler. Bitte korrigiere diese, um die Datei " +"einzusenden." + +#: IDF/gettexttemplates/idf/downloads/create.html.php:8 +msgid "Submit File" +msgstr "Datei einsenden" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:9 +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:8 +#: IDF/gettexttemplates/idf/downloads/delete.html.php:7 +#: IDF/gettexttemplates/idf/downloads/view.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:21 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:14 +#: IDF/gettexttemplates/idf/issues/create.html.php:14 +#: IDF/gettexttemplates/idf/issues/view.html.php:27 +#: IDF/gettexttemplates/idf/register/confirmation.html.php:7 +#: IDF/gettexttemplates/idf/register/index.html.php:8 +#: IDF/gettexttemplates/idf/register/inputkey.html.php:5 +#: IDF/gettexttemplates/idf/review/create.html.php:12 +#: IDF/gettexttemplates/idf/review/view.html.php:41 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:5 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:13 +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:7 +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:9 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:5 +msgid "Cancel" +msgstr "Abbrechen" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:10 +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:9 +#: IDF/gettexttemplates/idf/register/inputkey.html.php:6 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:6 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:6 +msgid "Instructions" +msgstr "Anleitung" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:3 +msgid "" +"The archive must include a manifest.xml file with meta " +"information about the\n" +"files to process inside the archive. All processed files must be unique or " +"replace existing files explicitely." +msgstr "" +"Das Archiv muss eine manifest.xml-Datei mit Meta-Informationen " +"bezüglich\n" +"der in diesem Archiv zu verarbeitenden Dateien beinhalten. Alle Dateien " +"müssen eindeutig sein\n" +"oder bestehende Dateien explizit ersetzen." + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:5 +#, php-format +msgid "" +"You can learn more about the archive format here." +msgstr "" +"Hier kannst mehr über das Archiv-Format lernen." + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:6 +msgid "" +"The form contains some errors. Please correct them to submit the archive." +msgstr "" +"Die Eingabemaske enthält einige Fehler. Bitte korrigiere diese, um das " +"Archiv einzusenden." + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:7 +msgid "Submit Archive" +msgstr "Archiv einsenden" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:3 +msgid "" +"Attention! If you want to delete a specific version of your " +"software, maybe, someone is depending on this specific version to run his " +"systems. Are you sure, you will not affect anybody when removing this file?" +msgstr "" +"Achtung! Möglicherweise benötigt noch jemand diese Version " +"und kann nicht mehr darauf zugreifen, wenn sie gelöscht wird. Bist Du " +"sicher, dass niemand durch die Löschung beeinträchtigt wird?" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:4 +#, php-format +msgid "" +"Instead of deleting the file, you could mark it as " +"deprecated." +msgstr "" +"Statt die Datei zu löschen, könntest Du sie als veraltet " +"markieren." + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:5 +#: IDF/gettexttemplates/idf/downloads/view.html.php:4 +#: IDF/gettexttemplates/idf/issues/attachment.html.php:4 +#: IDF/gettexttemplates/idf/issues/view.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:5 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:7 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:7 +#, php-format +msgid "by %%submitter%%" +msgstr "von %%submitter%%" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:6 +msgid "Delete File" +msgstr "Lösche Datei" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:8 +#: IDF/gettexttemplates/idf/downloads/view.html.php:14 +msgid "Uploaded:" +msgstr "Hochgeladen:" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:9 +#: IDF/gettexttemplates/idf/downloads/view.html.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:29 +#: IDF/gettexttemplates/idf/review/view.html.php:27 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:12 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:14 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:14 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:15 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:17 +msgid "Updated:" +msgstr "Aktualisiert:" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:10 +#: IDF/gettexttemplates/idf/downloads/view.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:6 +#: IDF/gettexttemplates/idf/listProjects.html.php:17 +msgid "Downloads:" +msgstr "Downloads:" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:11 +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:7 +#: IDF/gettexttemplates/idf/downloads/view.html.php:17 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:6 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:6 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:11 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:16 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:10 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:21 +#: IDF/gettexttemplates/idf/issues/view.html.php:33 +#: IDF/gettexttemplates/idf/project-list.html.php:8 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:6 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:13 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:16 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:12 +#: IDF/IssueComment.php:157 IDF/Wiki/PageRevision.php:204 +msgid "Labels:" +msgstr "Labels:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:3 +msgid "A new file is available for download:" +msgstr "Eine neue Datei ist bereit zum Herunterladen:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:4 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:6 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:5 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:8 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:4 +msgid "Hello," +msgstr "Hallo," + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:6 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:5 +msgid "Project:" +msgstr "Projekt:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:6 +msgid "Submitted by:" +msgstr "Eingesandt von:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:8 +msgid "Download:" +msgstr "Download:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/view.html.php:31 +#: IDF/gettexttemplates/idf/user/public.html.php:4 +msgid "Description:" +msgstr "Beschreibung:" + +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:3 +msgid "A file download was updated:" +msgstr "Ein Dateidownload wurde aktualisiert:" + +#: IDF/gettexttemplates/idf/downloads/feedfragment.xml.php:3 +msgid "Details" +msgstr "Details" + +#: IDF/gettexttemplates/idf/downloads/index.html.php:3 +#, php-format +msgid "See the deprecated files." +msgstr "Zeige die veralteten Dateien." + +#: IDF/gettexttemplates/idf/downloads/index.html.php:5 +msgid "Number of files:" +msgstr "Anzahl der Dateien:" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:3 +msgid "" +"Attention! This file is marked as deprecated, download it " +"only if you are sure you need this specific version." +msgstr "" +"Achtung! Diese Datei ist als veraltet markiert. Lade sie " +"nur herunter, falls Du genau diese Version benötigst." + +#: IDF/gettexttemplates/idf/downloads/view.html.php:5 +msgid "md5:" +msgstr "MD5:" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:6 +msgid "Changes" +msgstr "Änderungen" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:7 +msgid "The form contains some errors. Please correct them to update the file." +msgstr "" +"Die Eingabemaske enthält einige Fehler. Bitte korrigiere diese, um die Datei " +"zu aktualisieren." + +#: IDF/gettexttemplates/idf/downloads/view.html.php:8 +msgid "Update File" +msgstr "Datei aktualisieren" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:10 +#: IDF/gettexttemplates/idf/downloads/view.html.php:12 +msgid "Remove this file" +msgstr "Entferne diese Datei" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:11 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:18 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:7 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:12 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:12 +msgid "Trash" +msgstr "Mülleimer" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:13 +msgid "Delete this file" +msgstr "Lösche diese Datei" + +#: IDF/gettexttemplates/idf/faq-api.html.php:3 +#: IDF/gettexttemplates/idf/faq-archive-format.html.php:3 +#: IDF/gettexttemplates/idf/faq.html.php:65 +msgid "Here we are, just to help you." +msgstr "Wir sind hier, um Dir zu helfen." + +#: IDF/gettexttemplates/idf/faq-api.html.php:4 +#: IDF/gettexttemplates/idf/faq-archive-format.html.php:4 +#: IDF/gettexttemplates/idf/faq.html.php:66 +#: IDF/gettexttemplates/idf/gadmin/base.html.php:4 +#: IDF/gettexttemplates/idf/index.html.php:4 IDF/Views/Admin.php:77 +#: IDF/Views.php:91 +msgid "Projects" +msgstr "Projekte" + +#: IDF/gettexttemplates/idf/faq.html.php:3 +msgid "" +"

This is simple:

\n" +"
    \n" +"
  1. Write in the comments \"This is a duplicate of issue 123\" or - if you " +"are a member of the crew -\n" +"directly add the \"duplicates\" relation with the value \"123\" below the " +"comment field. Change \"123\"\n" +"with the corresponding issue number.
  2. \n" +"
  3. Change the status of the current issue to Duplicate.
  4. \n" +"
  5. Submit the changes.
  6. \n" +"
" +msgstr "" +"

Ganz einfach:

\n" +"
    \n" +"
  1. Schreibe in das Kommentarfeld \"Dies ist ein Duplikat von issue 123\" " +"oder - wenn Du ein Mitglied des Teams bist - füge direkt eine " +"\"duplicates\"-Verknüpfung mit dem Wert \"123\" hinzu. Ändere 123 in die " +"dazugehörige Ticketnummer.
  2. \n" +"
  3. Ändere den Status des aktuellen Tickets auf Duplicate.
  4. \n" +"
  5. Speichere die Änderungen.
  6. \n" +"
" + +#: IDF/gettexttemplates/idf/faq.html.php:11 +msgid "" +"You need to create an account on Gravatar, this takes about 5 minutes " +"and is free." +msgstr "" +"Du musst Dir ein Benutzerkonto auf Gravatar.com erstellen, es dauert nur 5 " +"Minuten und ist kostenfrei." + +#: IDF/gettexttemplates/idf/faq.html.php:12 +msgid "" +"\n" +"

To embed any previously uploaded resource into your wiki page, you can " +"use the [[!ResourceName]] syntax.

\n" +"\n" +"

The rendering of the resource can then be further fine-tuned:\n" +"

    \n" +"
  • [[!ImageResource, align=right, width=200]] renders " +"\"ImageResource\" right-aligned and scale its width to 200
  • \n" +"
  • [[!TextResource, align=center, width=300, height=300]] " +"renders \"TextResource\" in a centered, 300 by 300 px iframe
  • \n" +"
  • [[!AnyResource, preview=no]] does not render a preview of " +"the resource, but only provides a download link (default for binary " +"resources)
  • \n" +"
  • [[!BinaryResource, title=Download]] renders the download " +"link of \"BinaryResource\" with an alternative title
  • \n" +"
\n" +"

\n" +"\n" +"Resources are versioned, just like wiki pages. If you update a resource, old " +"wiki pages still show the state of the resource\n" +"at the time when the wiki page was edited. If you specifically want to " +"update a resource on a page, you therefor need to update\n" +"the resource at first and then also the page where it is referenced, " +"otherwise the change won't be visible until the next regular edit. \n" +msgstr "" +"\n" +"

Um eine vorher hochgeladene Ressource in Deine Wiki-Seite einzubetten, " +"kannst Du die [[!RessourcenName]]-Syntax verwenden.

\n" +"\n" +"

Die Darstellung der Ressource kann dann weiter angepasst werden:\n" +"

    \n" +"
  • [[!BildRessource, align=right, width=200]] stellt " +"\"BildResource\" rechts ausgerichtet und in der Breite auf 200 Pixel Größe " +"skaliert dar
  • \n" +"
  • [[!TextRessource, align=center, width=300, height=300]] " +"stellt \"TextResource\" in einem zentrierten, 300 x 300 Pixel großen IFRAME " +"dar
  • \n" +"
  • [[!JedeRessource, preview=no]] stellt keine Vorschau der " +"Ressource dar, sondern zeigt lediglich einen Download-Link an (Standard für " +"Binär-Ressourcen)
  • \n" +"
  • [[!BinärRessource, title=Download]] stellt den " +"Download-Link von \"BinärResource\" mit einem alternativen Titel dar
  • \n" +"
\n" +"

\n" +"\n" +"Ressourcen werden, wie Wiki-Seiten auch, versionisiert. Wenn Du eine " +"Ressource aktualisierst, zeigen alte Wikiseiten weiterhin\n" +"die Version der Ressource an, die aktuell war, als die Wiki-Seite bearbeitet " +"wurde. Wenn Du eine Ressource auf einer bestimmten\n" +"Seite aktualisieren möchtest, aktualisiere zunächst die Ressource und danach " +"auch die Seite, auf welcher die Ressource referenziert\n" +"ist, andernfalls werden die Änderungen an der Ressourcen bis zur nächsten " +"regulären Inhaltsänderung der Seite nicht sichtbar.\n" + +#: IDF/gettexttemplates/idf/faq.html.php:28 +msgid "" +"

If you have to publish many files at once for a new release, it is a very " +"tedious task\n" +"to upload them one after another and enter meta information like a summary, " +"a description or additional\n" +"labels for each of them.

\n" +"

InDefero therefore supports a special archive format that is basically a " +"standard zip file which comes with\n" +"some meta information. These meta information are kept in a special manifest " +"file, which is distinctly kept from\n" +"the rest of the files in the archive that should be published.

\n" +"

Once this archive has been uploaded, InDefero reads in the meta " +"information, unpacks the other files from\n" +"the archive and creates new individual downloads for each of them.

" +msgstr "" +"

Wenn Du viele Dateien auf einmal für ein Release veröffentlichen musst, " +"ist es eine sehr langwierige Aufgabe,\n" +"jede Datei einzeln hochzuladen und Meta-Informationen wie Zusammenfasssung, " +"Beschreibung oder zusätzliche\n" +"Marken in die Eingabefelder einzugeben.

\n" +"

InDefero unterstützt daher ein spezielles Archiv-Format, welches im " +"Grunde genommen eine normale\n" +"ZIP-Datei ist, die weitere Meta-Informationen enthält. Diese " +"Meta-Informationen werden in einer speziellen\n" +"Manifest-Datei beschrieben, die getrennt von den anderen Dateien des Archivs " +"behandelt wird.

\n" +"

Sobald das Archiv hochgeladen wurde, liest InDefero die " +"Meta-Informationen aus, entpackt die anderen Dateien\n" +"vom Archiv und erzeugt für jede von ihnen individuelle Downloads.

" + +#: IDF/gettexttemplates/idf/faq.html.php:36 +#, php-format +msgid "Learn more about the archive format." +msgstr "Weitere Informationen über das Archiv-Format." + +#: IDF/gettexttemplates/idf/faq.html.php:37 +msgid "" +"The API (Application Programming Interface) is used to interact with " +"InDefero with another program. For example, this can be used to create a " +"desktop program to submit new tickets easily." +msgstr "" +"Die API (Application Programming Interface) ermöglicht es anderen Programme, " +"sich mit InDefero zu verbinden. Beispielsweise könnte eine Desktop-Anwendung " +"geschrieben werden, die einfach neue Tickets in InDefero erstellt." + +#: IDF/gettexttemplates/idf/faq.html.php:38 +#, php-format +msgid "Learn more about the API." +msgstr "Weitere Informationen über die API." + +#: IDF/gettexttemplates/idf/faq.html.php:39 +#: IDF/gettexttemplates/idf/faq.html.php:45 +msgid "What are the keyboard shortcuts?" +msgstr "Welche Tastaturkürzel gibt es?" + +#: IDF/gettexttemplates/idf/faq.html.php:40 +#: IDF/gettexttemplates/idf/faq.html.php:60 +msgid "How to mark an issue as duplicate?" +msgstr "Wie markiert man ein Ticket als Duplikat?" + +#: IDF/gettexttemplates/idf/faq.html.php:41 +#: IDF/gettexttemplates/idf/faq.html.php:61 +msgid "How can I display my head next to my comments?" +msgstr "Wie kann ich meinen Kommentaren ein Foto von mir hinzufügen?" + +#: IDF/gettexttemplates/idf/faq.html.php:42 +#: IDF/gettexttemplates/idf/faq.html.php:62 +msgid "How can I embed images and other resources in my documentation pages?" +msgstr "" +"Wie kann ich Bilder oder andere Ressourcen in meine Dokumentationsseiten " +"einbetten?" + +#: IDF/gettexttemplates/idf/faq.html.php:43 +#: IDF/gettexttemplates/idf/faq.html.php:63 +msgid "What is this \"Upload Archive\" functionality about?" +msgstr "Um was geht es bei der Funktion \"Archiv hochladen\"?" + +#: IDF/gettexttemplates/idf/faq.html.php:44 +#: IDF/gettexttemplates/idf/faq.html.php:64 +msgid "What is the API and how is it used?" +msgstr "Was ist die API und wie wird sie verwendet?" + +#: IDF/gettexttemplates/idf/faq.html.php:46 +msgid "Shift+h: This help page." +msgstr "Umschalt+h: Diese Hilfeseite." + +#: IDF/gettexttemplates/idf/faq.html.php:47 +msgid "If you are in a project, you have the following shortcuts:" +msgstr "" +"Befindest Du Dich in einem Projekt, kannst Du die folgenden Tastaturkürzel " +"benutzen:" + +#: IDF/gettexttemplates/idf/faq.html.php:48 +msgid "Shift+u: Project updates." +msgstr "Umschalt+u: Projekt aktualisieren." + +#: IDF/gettexttemplates/idf/faq.html.php:49 +msgid "Shift+d: Downloads." +msgstr "Umschalt+d: Downloads." + +#: IDF/gettexttemplates/idf/faq.html.php:50 +msgid "Shift+o: Documentation." +msgstr "Umschalt+o: Dokumentation." + +#: IDF/gettexttemplates/idf/faq.html.php:51 +msgid "Shift+a: Create a new issue." +msgstr "Umschalt+a: Erstelle ein neues Ticket." + +#: IDF/gettexttemplates/idf/faq.html.php:52 +msgid "Shift+i: List of open issues." +msgstr "Umschalt+i: Zeige eine Liste offener Tickets." + +#: IDF/gettexttemplates/idf/faq.html.php:53 +msgid "Shift+m: The issues you submitted." +msgstr "Umschalt+m: Die von Dir übermittelten Tickets." + +#: IDF/gettexttemplates/idf/faq.html.php:54 +msgid "Shift+w: The issues assigned to you." +msgstr "Umschalt+w: Die Dir zugewiesenen Tickets." + +#: IDF/gettexttemplates/idf/faq.html.php:55 +msgid "Shift+s: Source." +msgstr "Umschalt+s: Quellcode." + +#: IDF/gettexttemplates/idf/faq.html.php:56 +msgid "You also have the standard access keys:" +msgstr "Du kannst auch die folgenden Standardzugriffstasten nutzen:" + +#: IDF/gettexttemplates/idf/faq.html.php:57 +msgid "Alt+1: Home." +msgstr "Alt+1: Start." + +#: IDF/gettexttemplates/idf/faq.html.php:58 +msgid "Alt+2: Skip the menus." +msgstr "Alt+2: Die Menüs übergehen." + +#: IDF/gettexttemplates/idf/faq.html.php:59 +msgid "Alt+4: Search (when available)." +msgstr "Alt+4: Suche (wenn verfügbar)." + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:3 +msgid "Forge" +msgstr "Forge" + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:5 +msgid "People" +msgstr "Personen" + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:6 +msgid "Usher" +msgstr "Usher" + +#: IDF/gettexttemplates/idf/gadmin/forge/base.html.php:3 +msgid "Frontpage" +msgstr "Startseite" + +#: IDF/gettexttemplates/idf/gadmin/forge/index.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

You can set up a custom forge page that is used as entry page for the " +"forge instead of the plain project listing. This page is then also " +"accessible via the 'Home' link in main menu bar.

\n" +"

The content of the page can use the Markdown " +"syntax with the Extra extension.

\n" +"

Additionally, the following macros are available:
\n" +"

    \n" +"
  • {projectlist, label=..., order=(name|activity), " +"limit=...} - Renders a project list that can optionally be filtered " +"by label, ordered by 'name' or 'activity' and / or limited to a specific " +"number of projects.
  • \n" +"
\n" +"

\n" +msgstr "" +"\n" +"

Anweisungen:

\n" +"

Du kannst eine eigene Forge-Startseite einrichtem, die anstatt der " +"einfachen Projektliste angezeigt wird. Diese Seite ist dann auch über den " +"'Startseite'-Link im Hauptmenü zu erreichen.

\n" +"

Für den Inhalt der Seite kann die Markdown-Syntax mit der Extra-Erweiterung verwendet werden.

\n" +"

Zusätzlich sind die folgenden Makros verfügbar:
\n" +"

    \n" +"
  • {projectlist, label=..., order=(name|activity), " +"limit=...} -Zeigt eine Projektliste an, die optional nach Marke " +"gefiltert und nach Name oder Aktivität sortiert und / oder auf eine " +"bestimmte Anzahl von Projekten beschränkt werden kann.
  • \n" +"
\n" +"

\n" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:3 +#: IDF/gettexttemplates/idf/main-menu.html.php:7 +msgid "Project List" +msgstr "Projektliste" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:4 +#: IDF/Views/Admin.php:110 +msgid "Project Labels" +msgstr "Projekt-Marken" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:16 +#: IDF/gettexttemplates/idf/listProjects.html.php:6 IDF/Views/Admin.php:186 +msgid "Create Project" +msgstr "Projekt anlegen" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:6 +msgid "Change Project Details" +msgstr "Projektdetails ändern" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:3 +msgid "" +"You can select the type of repository you want. In the case of subversion, " +"you can use optionally a remote repository instead of the local one." +msgstr "" +"Du kannst den Typ des Depots auswählen, den Du verwenden möchtest. Im Falle " +"von Subversion kannst Du optional neben einem lokalen auch ein entferntes " +"Depot benutzen." + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:4 +msgid "" +"Once you have defined the repository type, you cannot change " +"it." +msgstr "" +"Wurde der Typ des Depots einmal festgelegt, kann dieser nicht " +"nachträglich geändert werden.." + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:5 +msgid "" +"\n" +"

Specify each person by its login. Each person must have already " +"registered with the given login.

\n" +"

Separate the logins with commas and/or new lines.

\n" +msgstr "" +"\n" +"

Gib den Anmeldenamen jeder Person an. Jede Person muss sich vorher " +"bereits mit diesen Namen angemeldet haben.

\n" +"

Trenne die Anmeldenamen durch Kommas und / oder neue Zeilen.

\n" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:14 +msgid "" +"The form contains some errors. Please correct them to create the project." +msgstr "" +"Die Eingabemaske enthält einige Fehler. Bitte korrigiere diese, um das " +"Projekt anzulegen." + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:15 +msgid "Provide at least one owner for the project or use a template." +msgstr "" +"Gib mindestens einen Eigentümer für das Projekt ein oder benutze eine " +"Projektvorlage." + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:15 +msgid "Instructions:" +msgstr "Anweisungen:" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:3 +#, php-format +msgid "" +"Confirmation code to confirm the deletion of the project: \n" +"%%code%%." +msgstr "" +"Kennwort zur Bestätigung der Projektlöschung: \n" +"%%code%%." + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:5 +msgid "" +"\n" +"Attention! Deleting a project is a one second operation\n" +"with the consequences that all the data related to the \n" +"project will be deleted.\n" +msgstr "" +"\n" +"Achtung! Das Löschen eines Projekts ist eine sehr\n" +"rasch beendete Operation, die in der Konsequenz alle Daten\n" +"in Bezug auf das Projekt löscht.\n" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:10 +msgid "" +"The form contains some errors. Please correct them to delete the project." +msgstr "" +"Die Eingabemaske enthält einige Fehler. Bitte korrigiere diese, um das " +"Projekt zu löschen." + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:11 +msgid "Project Statistics" +msgstr "Projektstatistiken" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:12 +msgid "Tab" +msgstr "Bereich" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:13 +msgid "Number" +msgstr "Zahl" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:15 +msgid "Code reviews" +msgstr "Code-Besprechungen" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:16 +#: IDF/Views/Project.php:93 +msgid "Commits" +msgstr "Revisionen" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:18 +msgid "Documentation pages" +msgstr "Dokumentations-Seiten" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:19 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:20 +msgid "Delete Project" +msgstr "Projekt löschen" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:22 +msgid "" +"For large projects, the suppression can take a while, please be patient." +msgstr "Das Löschen großer Projekte kann etwas dauern, bitte habe Geduld." + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:3 +msgid "Space Usage Statistics" +msgstr "Speicherplatz-Statistiken" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:4 +msgid "Repositories:" +msgstr "Depots:" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:5 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:11 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:18 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:16 +msgid "Attachments:" +msgstr "Anhänge:" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:7 +msgid "Database:" +msgstr "Datenbank:" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:8 +msgid "Total Forge:" +msgstr "Forge insgesamt:" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:13 +msgid "" +"The form contains some errors. Please correct them to update the project." +msgstr "" +"Die Eingabemaske enthält einige Fehler. Bitte korrigiere diese, um das " +"Projekt zu aktualisieren." + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:14 +msgid "Provide at least one owner for the project." +msgstr "Bestimme wenigstens einen Projekteigentümer." + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:15 +msgid "Update Project" +msgstr "Projekt aktualisieren" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:19 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:20 +msgid "Delete this project" +msgstr "Lösche dieses Projekt" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:21 +msgid "You will be asked to confirm." +msgstr "Es wird eine Bestätigung verlangt." + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:3 IDF/Views/Admin.php:264 +msgid "User List" +msgstr "Benutzerliste" + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:13 +msgid "Update User" +msgstr "Benutzer aktualisieren" + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:4 +msgid "Create User" +msgstr "Benutzer anlegen" + +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:3 +msgid "The form contains some errors. Please correct them to create the user." +msgstr "" +"Die Eingabemaske enthält einige Fehler. Bitte korrigiere diese, um den " +"Benutzer zu erstellen." + +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:6 +msgid "The user password will be sent by email to the user." +msgstr "" +"Das Passwort des Benutzers wird an die E-Mail-Adresse des Benutzers versandt." + +#: IDF/gettexttemplates/idf/gadmin/users/createuser-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"An account on the forge has been created for you by\n" +"the administrator %%admin%%.\n" +"\n" +"Please find here your details to access the forge:\n" +"\n" +" Address: %%url%%\n" +" Login: %%user.login%%\n" +" Password: %%password%%\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" +"Hallo %%user%%,\n" +"\n" +"Der Administrator %%admin%% hat ein neues Benutzerkonto\n" +"für Dich auf der Forge angelegt.\n" +"\n" +"Hier sind die Zugangsdaten, mit denen Du auf Dein Benutzerkonto\n" +"zugreifen kannst:\n" +"\n" +" Adresse: %%url%%\n" +" Anmeldename: %%user.login%%\n" +" Passwort: %%password%%\n" +"\n" +"Mit freundlichen Grüßen,\n" +"Das Entwickler-Team.\n" + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:3 +#, php-format +msgid "See not validated users." +msgstr "Zeige nicht validierte Benutzer." + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:4 +msgid "

You have here an overview of the users registered in the forge.

" +msgstr "" +"

Hier siehst Du eine Übersicht der Benutzer, die sich in der Forge " +"registriert haben." + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:5 +msgid "Number of users:" +msgstr "Anzahl der Benutzer:" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:3 +msgid "" +"If you are changing the email address of the user, you\n" +"need to ensure that you are providing a valid email\n" +"address" +msgstr "" +"Wenn Du die E-Mail-Adresse eines Benutzers änderst,\n" +"musst Du sicherstellen, eine gültige, neue E-Mail-Adresse\n" +"als Ersatz bereitzustellen." + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:6 +msgid "" +"If you give the user staff rights, the user will be\n" +"able to create new projects and update other non staff users.\n" +msgstr "" +"Wenn Du dem Benutzer Stab-Rechte erteilst, kann er\n" +"neue Projekte anlegen und andere Benutzer, die nicht zum Stab\n" +"gehören, aktualisieren.\n" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:9 +msgid "The form contains some errors. Please correct them to update the user." +msgstr "" +"Die Eingabemaske enthält einige Fehler. Bitte korrigiere diese, um den " +"Benutzer zu aktualisieren." + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:10 +#: IDF/gettexttemplates/idf/register/confirmation.html.php:4 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:4 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:4 +msgid "Login:" +msgstr "Benutzername:" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:11 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:5 +msgid "Public Profile" +msgstr "Öffentliches Profil" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:12 +msgid "Administrative" +msgstr "Administratives" + +#: IDF/gettexttemplates/idf/gadmin/usher/base.html.php:3 +msgid "Configured servers" +msgstr "Konfigurierte Server" + +#: IDF/gettexttemplates/idf/gadmin/usher/base.html.php:4 IDF/Views/Admin.php:421 +msgid "Usher control" +msgstr "Usher-Kontrolle" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html~.php:3 +msgid "address" +msgstr "Adresse" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html~.php:4 +msgid "port" +msgstr "Port" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:5 +msgid "No connections found." +msgstr "Keine Verbindungen gefunden." + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:3 +msgid "current server status:" +msgstr "Derzeitiger Serverstatus:" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:4 +msgid "startup" +msgstr "hochfahren" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:5 +msgid "shutdown" +msgstr "herunterfahren" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:6 +msgid "reload server configuration:" +msgstr "Serverkonfiguration einlesen:" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:7 +msgid "reload" +msgstr "neu laden" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:11 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:11 +msgid "Status explanation" +msgstr "Statuserklärung" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:9 +msgid "active with n total open connections" +msgstr "aktiv mit n offenen Verbindungen insgesamt" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:10 +msgid "waiting for new connections" +msgstr "warte auf neue Verbindungen" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:11 +msgid "usher is being shut down, not accepting connections" +msgstr "Usher wird heruntergefahren und akzeptiert keine Verbindungen" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:12 +msgid "" +"usher is shut down, all local servers are stopped and not accepting " +"connections" +msgstr "" +"Usher ist heruntergefahren, alle lokalen Server sind gestoppt und keine " +"Verbindungen werden akzeptiert" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:3 +msgid "server name" +msgstr "Servername" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:4 IDF/Issue.php:99 +#: IDF/Review.php:102 +msgid "status" +msgstr "Status" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:5 +msgid "action" +msgstr "Aktion" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:6 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:6 +msgid "No monotone servers configured." +msgstr "Keine monotone-Server konfiguriert." + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:7 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:7 +msgid "stop" +msgstr "stoppen" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:8 +msgid "start" +msgstr "starten" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:9 +msgid "kill" +msgstr "töten" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:10 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:10 +msgid "active connections" +msgstr "aktive Verbindungen" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:12 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:12 +msgid "remote server without open connections" +msgstr "entfernter Server ohne offene Verbindungen" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:13 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:13 +msgid "server with n open connections" +msgstr "Server mit n offenen Verbindungen" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:14 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:14 +msgid "local server running, without open connections" +msgstr "lokaler Server läuft ohne offene Verbindungen" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:15 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:15 +msgid "local server not running, waiting for connections" +msgstr "lokaler Server läuft nicht und wartet auf Verbindungen" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:16 +msgid "local server is about to stop, n connections still open" +msgstr "lokaler Server stoppt gerade, n Verbindungen sind noch offen" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:17 +msgid "local server not running, not accepting connections" +msgstr "lokaler Server läuft nicht und akzeptiert keine Verbindungen" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:18 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:18 +msgid "usher is shut down, not running and not accepting connections" +msgstr "" +"Usher ist heruntergefahren, läuft nicht und akzeptiert keine Verbindungen" + +#: IDF/gettexttemplates/idf/index.atom.php:3 +#, php-format +msgid "Personal project feed for %%user%%." +msgstr "Persönlicher Projekt-Feed für %%user%%." + +#: IDF/gettexttemplates/idf/index.html.php:3 +#: IDF/gettexttemplates/idf/main-menu.html.php:6 +msgid "Home" +msgstr "Startseite" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:3 +#, php-format +msgid "Attachment to issue %%issue.id%%" +msgstr "Anhang zum Ticket %%issue.id%%" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:5 +#: IDF/gettexttemplates/idf/review/view.html.php:35 +#: IDF/gettexttemplates/idf/source/commit.html.php:23 +#: IDF/gettexttemplates/idf/source/commit.html~.php:22 +#: IDF/gettexttemplates/idf/source/git/file.html.php:6 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:7 +msgid "Archive" +msgstr "Archiv" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:6 +#: IDF/gettexttemplates/idf/source/git/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:12 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:12 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:10 +msgid "Download this file" +msgstr "Lade diese Datei herunter" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:7 +#: IDF/gettexttemplates/idf/issues/view.html.php:28 +#: IDF/gettexttemplates/idf/review/view.html.php:26 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:13 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:14 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:16 +msgid "Created:" +msgstr "Erstellt:" + +#: IDF/gettexttemplates/idf/issues/base.html.php:4 +msgid "All Issues" +msgstr "Alle Tickets" + +#: IDF/gettexttemplates/idf/issues/base.html.php:5 +msgid "My Issues" +msgstr "Meine Tickets" + +#: IDF/gettexttemplates/idf/issues/base.html.php:6 +msgid "My watch list" +msgstr "Meine Beobachtungsliste" + +#: IDF/gettexttemplates/idf/issues/base.html.php:7 +#: IDF/gettexttemplates/idf/issues/by-label.html.php:6 +#: IDF/gettexttemplates/idf/issues/index.html.php:5 +#: IDF/gettexttemplates/idf/issues/project-watchlist.html.php:5 +#: IDF/gettexttemplates/idf/issues/search.html.php:8 +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:5 +msgid "New Issue" +msgstr "Neues Ticket" + +#: IDF/gettexttemplates/idf/issues/base.html.php:8 +#: IDF/gettexttemplates/idf/wiki/base.html.php:9 +msgid "Search" +msgstr "Suche" + +#: IDF/gettexttemplates/idf/issues/base.html.php:9 +msgid "Back to the issue" +msgstr "Zurück zum Ticket" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:3 +#, php-format +msgid "" +"

Open issues: %%open%%

\n" +"

Closed issues: %%closed%%

\n" +msgstr "" +"

Offene Tickets: %%open%%

\n" +"

Geschlossene Tickets: %%closed%%

\n" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:7 +msgid "Label:" +msgstr "Label:" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:8 +msgid "Completion:" +msgstr "Fertigstellung:" + +#: IDF/gettexttemplates/idf/issues/create.html.php:3 +msgid "" +"

When you submit the issue do not forget to provide the following " +"information:

\n" +"
    \n" +"
  • The steps to reproduce the problem.
  • \n" +"
  • The version of the software and your operating system.
  • \n" +"
  • Any information that can help the developers to solve the issue.
  • \n" +"
  • Do not provide any password or confidential " +"information!
  • \n" +"
" +msgstr "" +"

Wenn Du ein Ticket erstellst, vergesse nicht die folgenden Angaben zu " +"machen:

\n" +"
    \n" +"
  • Die erfolgten Schritte, um das Problem zu reproduzieren.
  • \n" +"
  • Die Version der Software und Deines Betriebssystems.
  • \n" +"
  • Jede Information, die dem Entwickler helfen könnte, das Problem zu " +"lösen.
  • \n" +"
  • Füge dem Ticket keine Passwörter oder vertrauliche Angaben " +"hinzu!
  • \n" +"
" + +#: IDF/gettexttemplates/idf/issues/create.html.php:10 +msgid "The form contains some errors. Please correct them to submit the issue." +msgstr "" +"Die Eingabemaske enthält einige Fehler. Bitte korrigiere diese, um das " +"Ticket einzureichen." + +#: IDF/gettexttemplates/idf/issues/create.html.php:11 +#: IDF/gettexttemplates/idf/issues/create.html.php:13 +#: IDF/gettexttemplates/idf/issues/view.html.php:24 +#: IDF/gettexttemplates/idf/issues/view.html.php:26 +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:5 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:5 +msgid "Preview" +msgstr "Vorschau" + +#: IDF/gettexttemplates/idf/issues/create.html.php:12 +msgid "Submit Issue" +msgstr "Ticket einreichen" + +#: IDF/gettexttemplates/idf/issues/create.html.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:34 +msgid "Attach file" +msgstr "Datei anhängen" + +#: IDF/gettexttemplates/idf/issues/create.html.php:16 +#: IDF/gettexttemplates/idf/issues/create.html.php:17 +#: IDF/gettexttemplates/idf/issues/view.html.php:35 +#: IDF/gettexttemplates/idf/issues/view.html.php:36 +msgid "Attach another file" +msgstr "Eine andere Datei anhängen" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:3 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:3 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:13 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:12 +#: IDF/gettexttemplates/idf/issues/view.html.php:18 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:3 +#: IDF/gettexttemplates/idf/review/view.html.php:38 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:11 +#: IDF/IssueComment.php:151 +msgid "Summary:" +msgstr "Zusammenfassung:" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:4 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:4 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:8 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:14 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:13 +#: IDF/gettexttemplates/idf/issues/view.html.php:19 +#: IDF/gettexttemplates/idf/issues/view.html.php:30 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:4 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/view.html.php:39 IDF/IssueComment.php:153 +msgid "Status:" +msgstr "Status:" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:5 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:15 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:14 +#: IDF/gettexttemplates/idf/issues/view.html.php:20 +#: IDF/gettexttemplates/idf/issues/view.html.php:31 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:5 +#: IDF/IssueComment.php:155 +msgid "Owner:" +msgstr "Besitzer:" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:17 +#: IDF/gettexttemplates/idf/issues/view.html.php:22 IDF/IssueComment.php:159 +msgid "Relations:" +msgstr "Verknüpfungen:" + +#: IDF/gettexttemplates/idf/issues/forge-watchlist.html.php:3 +#: IDF/gettexttemplates/idf/issues/index.html.php:3 +#: IDF/gettexttemplates/idf/issues/project-watchlist.html.php:3 +#, php-format +msgid "" +"

Open issues: %%open%%

\n" +"

Closed issues: %%closed%%

" +msgstr "" +"

Offene Tickets: %%open%%

\n" +"

Geschlossene Tickets: %%closed%%

" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:3 +msgid "A new issue has been created and assigned to you:" +msgstr "Ein neues Ticket wurde erstellt und Dir zugeordnet:" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:4 +msgid "A new issue has been created:" +msgstr "Ein neues Ticket wurde erstellt:" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:8 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:11 +msgid "Reported by:" +msgstr "Gemeldet von:" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:12 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:19 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:17 +msgid "Issue:" +msgstr "Ticket:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:3 +msgid "The following issue you are owning has been updated:" +msgstr "Das folgende Ticket, welches Dir gehört, wurde aktualisiert:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:4 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:3 +msgid "The following issue has been updated:" +msgstr "Das folgende Ticket wurde aktualisiert:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:4 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:4 +#, php-format +msgid "By %%who%%, %%c.creation_dtime%%:" +msgstr "Von %%who%%, %%c.creation_dtime%%:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:10 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:9 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:12 +msgid "URL:" +msgstr "URL:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:12 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:11 +msgid "Comments (last first):" +msgstr "Kommentare (neueste zuerst):" + +#: IDF/gettexttemplates/idf/issues/search.html.php:3 +#, php-format +msgid "" +"\n" +"

Found open issues: %%open%%

\n" +"

Found closed issues: %%closed%%

" +msgstr "" +"\n" +"

Gefundene offene Tickets: %%open%%

\n" +"

Gefundene geschlossene Tickets: %%closed%%

" + +#: IDF/gettexttemplates/idf/issues/search.html.php:6 +#, php-format +msgid "" +"

Label:\n" +"%%tag.class%%:%%tag.name%%

" +msgstr "" +"

Label:\n" +"%%tag.class%%:%%tag.name%%

" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:3 +msgid "View all open issues." +msgstr "Zeige alle offenen Tickets." + +#: IDF/gettexttemplates/idf/issues/summary.html.php:4 +msgid "Create an issue." +msgstr "Lege ein Ticket an." + +#: IDF/gettexttemplates/idf/issues/summary.html.php:5 +#, php-format +msgid "" +"The issue tracker is empty.
Create your " +"first issue." +msgstr "" +"Es gibt noch keine Tickets.
Erstelle Dein " +"erstes Ticket hier." + +#: IDF/gettexttemplates/idf/issues/summary.html.php:6 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:4 +#, php-format +msgid "Unresolved: By %%key%%" +msgstr "Ungelöst: Nach %%key%%" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:7 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:5 +msgid "Status Summary" +msgstr "Status-Zusammenfassung" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:8 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:6 +msgid "Unresolved: By Assignee" +msgstr "Ungelöst: Nach Zugeordneten" + +#: IDF/gettexttemplates/idf/issues/summary.html~.php:3 +#, php-format +msgid "" +"The issue tracker is empty.
You can create your first issue here." +msgstr "" +"Es gibt noch keine Tickets.
Du kannst Dein erstes Ticket hier erstellen." + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:3 +#, php-format +msgid "" +"See the %%nb_submit_closed%% closed." +msgid_plural "" +"See the %%nb_submit_closed%% closed." +msgstr[0] "" +"Siehe das %%nb_submit_closed%% " +"geschlossene." +msgstr[1] "" +"Siehe die %%nb_submit_closed%% " +"geschlossenen." + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:4 +#, php-format +msgid "" +"See the %%nb_owner_closed%% closed." +msgid_plural "" +"See the %%nb_owner_closed%% closed." +msgstr[0] "" +"Siehe das %%nb_owner_closed%% " +"geschlossene." +msgstr[1] "" +"Siehe die %%nb_owner_closed%% " +"geschlossenen." + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:6 +#: IDF/gettexttemplates/idf/user/dashboard.html.php:7 +msgid "Submitted issues:" +msgstr "Eingereichte Tickets:" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:7 +#: IDF/gettexttemplates/idf/user/dashboard.html.php:6 +msgid "Working issues:" +msgstr "Tickets in Bearbeitung:" + +#: IDF/gettexttemplates/idf/issues/view.html.php:3 +#, php-format +msgid "Reported by %%submitter%%, %%c.creation_dtime%%" +msgstr "Eingesandt von %%submitter%%, %%c.creation_dtime%%" + +#: IDF/gettexttemplates/idf/issues/view.html.php:4 +#: IDF/gettexttemplates/idf/review/view.html.php:22 +#, php-format +msgid "" +"Comment %%i%% by %%submitter%%, %%c.creation_dtime%%" +msgstr "" +"Kommentar %%i%% von %%submitter%%, " +"%%c.creation_dtime%%" + +#: IDF/gettexttemplates/idf/issues/view.html.php:5 +#, php-format +msgid "Sign in to reply to this comment." +msgstr "" +"Melde Dich an, um auf diesen Kommentar zu antworten." + +#: IDF/gettexttemplates/idf/issues/view.html.php:6 +msgid "" +"This issue is marked as closed, add a comment only if you think this issue " +"is still valid and more work is needed to fully fix it." +msgstr "" +"Dieses Ticket wurde als geschlossen markiert. Füge nur dann einen Kommentar " +"hinzu, wenn Du denkst, dass das geschilderte Problem noch nicht ganz " +"beseitigt wurde." + +#: IDF/gettexttemplates/idf/issues/view.html.php:8 +#, php-format +msgid "%%interested%% person" +msgid_plural "%%interested%% persons" +msgstr[0] "%%interested%% Person" +msgstr[1] "%%interested%% Personen" + +#: IDF/gettexttemplates/idf/issues/view.html.php:9 +#, php-format +msgid "This issue %%verb%%" +msgstr "Dieses Ticket %%verb%%" + +#: IDF/gettexttemplates/idf/issues/view.html.php:10 +msgid "Remove this issue from your watch list" +msgstr "Entferne dieses Ticket von Deiner Beobachtungsliste" + +#: IDF/gettexttemplates/idf/issues/view.html.php:11 +msgid "Add this issue to your watch list" +msgstr "Füge dieses Ticket zu Deiner Beobachtungsliste hinzu" + +#: IDF/gettexttemplates/idf/issues/view.html.php:12 +msgid "View the previous closed issue" +msgstr "Zeige das vorherige geschlossene Ticket" + +#: IDF/gettexttemplates/idf/issues/view.html.php:13 +msgid "View the previous open issue" +msgstr "Zeige das vorherige offene Ticket" + +#: IDF/gettexttemplates/idf/issues/view.html.php:14 +msgid "View the next closed issue" +msgstr "Zeige das nächte geschlossene Ticket" + +#: IDF/gettexttemplates/idf/issues/view.html.php:15 +msgid "View the next open issue" +msgstr "Zeige das nächste offene Ticket" + +#: IDF/gettexttemplates/idf/issues/view.html.php:16 +msgid "download" +msgstr "herunterladen" + +#: IDF/gettexttemplates/idf/issues/view.html.php:17 +msgid "view" +msgstr "anzeigen" + +#: IDF/gettexttemplates/idf/issues/view.html.php:23 +msgid "The form contains some errors. Please correct them to change the issue." +msgstr "" +"Die Eingabemaske enthält einige Fehler. Bitte korrigiere diese, um das " +"Ticket zu ändern." + +#: IDF/gettexttemplates/idf/issues/view.html.php:25 +msgid "Submit Changes" +msgstr "Sende Änderungen" + +#: IDF/gettexttemplates/idf/issues/view.html.php:32 +msgid "Followed by:" +msgstr "Beobachtet von:" + +#: IDF/gettexttemplates/idf/listProjects.html.php:3 +#, php-format +msgid "1 project" +msgid_plural "%%label.project_count%% projects" +msgstr[0] "1 Projekt" +msgstr[1] "%%label.project_count%% Projekte" + +#: IDF/gettexttemplates/idf/listProjects.html.php:4 +#, php-format +msgid "Remove filter for %%tag%%" +msgstr "Entferne Filter für %%tag%%" + +#: IDF/gettexttemplates/idf/listProjects.html.php:5 +msgid "No projects managed with InDefero were found." +msgstr "Es wurden keine verwalteten Projekte gefunden." + +#: IDF/gettexttemplates/idf/listProjects.html.php:7 +msgid "Filter projects by label" +msgstr "Filtere Projekte nach Marke" + +#: IDF/gettexttemplates/idf/listProjects.html.php:8 +msgid "No projects with labels found." +msgstr "Keine Projekte mit Marken gefunden." + +#: IDF/gettexttemplates/idf/listProjects.html.php:9 +msgid "Order" +msgstr "Sortierung" + +#: IDF/gettexttemplates/idf/listProjects.html.php:10 +msgid "By name" +msgstr "Nach Name" + +#: IDF/gettexttemplates/idf/listProjects.html.php:11 +msgid "By activity" +msgstr "Nach Aktivität" + +#: IDF/gettexttemplates/idf/listProjects.html.php:12 +msgid "Filtered project stats" +msgstr "Statistiken der gefilterten Projekte" + +#: IDF/gettexttemplates/idf/listProjects.html.php:13 +msgid "Members:" +msgstr "Mitglieder:" + +#: IDF/gettexttemplates/idf/listProjects.html.php:14 +msgid "Issues:" +msgstr "Tickets:" + +#: IDF/gettexttemplates/idf/listProjects.html.php:15 +msgid "Commits:" +msgstr "Revisionen:" + +#: IDF/gettexttemplates/idf/listProjects.html.php:16 +msgid "Documentations:" +msgstr "Dokumentationsseiten:" + +#: IDF/gettexttemplates/idf/listProjects.html.php:18 +msgid "Code reviews:" +msgstr "Code-Besprechungen:" + +#: IDF/gettexttemplates/idf/login_form.html.php:3 +#, php-format +msgid "" +"You can create an account if you don't have one yet." +msgstr "" +"Du kannst ein Konto erstellen, wenn Du noch keins " +"hast." + +#: IDF/gettexttemplates/idf/login_form.html.php:4 +msgid "What is your account information?" +msgstr "Wie lauten Deine Kontoinformationen?" + +#: IDF/gettexttemplates/idf/login_form.html.php:5 +msgid "My login is" +msgstr "Mein Anmeldename ist" + +#: IDF/gettexttemplates/idf/login_form.html.php:6 +msgid "My password is" +msgstr "Mein Passwort ist" + +#: IDF/gettexttemplates/idf/login_form.html.php:7 +msgid "Sign in" +msgstr "Anmelden" + +#: IDF/gettexttemplates/idf/login_form.html.php:8 +msgid "I lost my password!" +msgstr "Ich habe mein Passwort vergessen!" + +#: IDF/gettexttemplates/idf/login_form.html.php:9 +msgid "Welcome." +msgstr "Willkommen." + +#: IDF/gettexttemplates/idf/login_form.html.php:10 +msgid "It takes less than a minute to create your account." +msgstr "Es dauert weniger als eine Minute, um Dein Benutzerkonto zu erstellen." + +#: IDF/gettexttemplates/idf/main-menu.html.php:3 +#, php-format +msgid "" +"Welcome, %%user%%." +msgstr "" +"Willkommen, %%user%%." + +#: IDF/gettexttemplates/idf/main-menu.html.php:4 +msgid "Sign Out" +msgstr "Abmelden" + +#: IDF/gettexttemplates/idf/main-menu.html.php:5 +msgid "Sign in or create your account" +msgstr "Anmelden oder Benutzerkonto erstellen" + +#: IDF/gettexttemplates/idf/main-menu.html.php:10 IDF/Views/Admin.php:40 +msgid "Forge Management" +msgstr "Administration" + +#: IDF/gettexttemplates/idf/main-menu.html.php:11 +msgid "Help and accessibility features" +msgstr "Hilfe und Barrierefreiheit" + +#: IDF/gettexttemplates/idf/main-menu.html.php:12 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:14 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:14 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:15 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:13 +msgid "Help" +msgstr "Hilfe" + +#: IDF/gettexttemplates/idf/project/home.html.php:3 +#: IDF/gettexttemplates/idf/project/timeline.html.php:4 IDF/Views.php:46 +msgid "Welcome" +msgstr "Willkommen" + +#: IDF/gettexttemplates/idf/project/home.html.php:4 +#: IDF/gettexttemplates/idf/project/timeline.html.php:5 +msgid "Latest Updates" +msgstr "Letzte Änderungen" + +#: IDF/gettexttemplates/idf/project/home.html.php:5 +msgid "Featured Downloads" +msgstr "Empfohlene Downloads" + +#: IDF/gettexttemplates/idf/project/home.html.php:6 +msgid "Show more featured downloads" +msgstr "Zeige mehr empfohlene Downloads" + +#: IDF/gettexttemplates/idf/project/home.html.php:7 +#: IDF/gettexttemplates/idf/project/home.html.php:10 +msgid "show more..." +msgstr "zeige mehr..." + +#: IDF/gettexttemplates/idf/project/home.html.php:8 +msgid "Featured Documentation" +msgstr "Empfohlene Dokumentation" + +#: IDF/gettexttemplates/idf/project/home.html.php:9 +msgid "Show more featured documentation" +msgstr "Zeige mehr empfohlene Dokumentation" + +#: IDF/gettexttemplates/idf/project/home.html.php:11 +msgid "Development Team" +msgstr "Entwickler-Team" + +#: IDF/gettexttemplates/idf/project/home.html.php:12 +msgid "Admins" +msgstr "Administratoren" + +#: IDF/gettexttemplates/idf/project/home.html.php:13 +msgid "Happy Crew" +msgstr "Glückliche Mannschaft" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:3 +msgid "Latest updates" +msgstr "Letzte Änderungen" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:6 IDF/Views/Project.php:90 +msgid "All Updates" +msgstr "Alle Aktualisierungen" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:7 +msgid "Filter by type" +msgstr "Nach Typ filtern" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:8 +msgid "Subscribe to this timeline" +msgstr "Abonniere diese Zeitleiste" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:9 +msgid "RSS" +msgstr "RSS" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:10 +msgid "Atom feed" +msgstr "Atom-Feed" + +#: IDF/gettexttemplates/idf/project-list.html.php:3 +msgid "Project activity: %%activity%%%" +msgstr "Projekt-Aktivität: %%activity%%%" + +#: IDF/gettexttemplates/idf/project-list.html.php:9 +msgid "n/a" +msgstr "n.v." + +#: IDF/gettexttemplates/idf/register/confirmation-email.txt.php:3 +#, php-format +msgid "" +"Hello,\n" +"\n" +"You have requested the creation of an account to\n" +"participate in the life of a software project.\n" +"\n" +"To confirm the account please follow this link:\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following confirmation key:\n" +"\n" +"%%key%%\n" +"\n" +"If you are not interested any longer in taking\n" +"part in the life of the software project or if\n" +"you can't remember having requested the creation\n" +"of an account, please excuse us and simply ignore\n" +"this email. \n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" +"Hallo,\n" +"\n" +"Du hast die Anlage eines Benutzerkontos angefordert, um an dem Leben\n" +"eines Softwareprojektes teilhaben zu können.\n" +"\n" +"Um Dein Konto zu bestätigen, folge bitte dem folgenden Link:\n" +"\n" +"%%url%%\n" +"\n" +"Alternativ gehe zu dieser Seite:\n" +"\n" +"%%urlik%%\n" +"\n" +"und gib den folgenden Validierungs-Schlüssel ein:\n" +"\n" +"%%key%%\n" +"\n" +"Wenn Du nicht mehr länger an diesem Software-Projekt\n" +"interessiert bist oder wenn Du Dich nicht daran erinnern\n" +"kannst, dieses Benutzerkonto erstellen zu wollen, entschuldige\n" +"und ignoriere einfach diese E-Mail.\n" +"\n" +"Mit freundlichen Grüßen,\n" +"Das Entwickler-Team.\n" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:3 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:3 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:3 +msgid "Oops, please check the form for errors." +msgstr "Bitte überprüfe die Maske auf Fehler." + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:5 +msgid "Email:" +msgstr "E-Mail:" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:6 +msgid "Enable Your Account" +msgstr "Aktiviere Dein Konto" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:8 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:8 +msgid "" +"This is the last step, but just be sure to have the cookies " +"enabled to log in afterwards." +msgstr "" +"Dies ist der letzte Schritt, aber bitte stelle sicher, dass Du " +"Cookies aktiviert hast, um Dich im Folgenden anzumelden." + +#: IDF/gettexttemplates/idf/register/index.html.php:3 +msgid "" +"Read the terms and conditions – " +"basically \"Please be nice, we respect you\"." +msgstr "" +"Lies die Geschäftsbedingungen - " +"kurz zusammengefast \"Bitte sei nett, wir respektieren Dich\"." + +#: IDF/gettexttemplates/idf/register/index.html.php:4 +#, php-format +msgid "" +"If you have just forgotten your login information, then there is no need to " +"create a new account. You can just recover your login " +"name and password." +msgstr "" +"Wenn Du einfach nur Deine Anmeldedaten vergessen hast, gibt es keinen Grund, " +"ein neues Benutzerkonto zu erstellen. Du kannst einfach Deinen Anmeldenamen und Dein Passwort wiederherstellen." + +#: IDF/gettexttemplates/idf/register/index.html.php:5 +#, php-format +msgid "" +"With your account, you will able to participate in the life of all the " +"projects hosted here. Participating in a software project must be fun, so if " +"you have troubles, you can let us know about your issues " +"at anytime!" +msgstr "" +"Durch Dein Benutzerkonto bist Du in der Lage, an dem Leben aller " +"Softwareprojekte, die hierüber verwaltet werden, teilzuhaben. Das Teilnehmen " +"an einem Softwareprojekt muss Spass machen, deshalb lass " +"uns jederzeit von Deinen Problemen wissen, solltest Du welche haben." + +#: IDF/gettexttemplates/idf/register/index.html.php:6 +msgid "Oops, please check the provided login and email address to register." +msgstr "" +"Bitte überprüfe den angegebenen Anmeldenamen und die E-Mail-Adresse zum " +"registrieren." + +#: IDF/gettexttemplates/idf/register/index.html.php:7 IDF/Views.php:137 +msgid "Create Your Account" +msgstr "Erstelle Deinen Account" + +#: IDF/gettexttemplates/idf/register/index.html.php:9 +msgid "" +"Be sure to provide a valid email address, as we are sending a validation " +"link by email." +msgstr "" +"Bitte gib eine gültige E-Mail-Adresse an, da wir einen Bestätigungs-Link an " +"diese Adresse versenden." + +#: IDF/gettexttemplates/idf/register/index.html.php:10 +msgid "Did you know?" +msgstr "Wusstest Du?" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:3 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:3 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:3 +msgid "Oops, we found an error in the form." +msgstr "Wir haben einen Fehler in der Maske gefunden." + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:4 +msgid "Confirm Your Account" +msgstr "Bestätige Dein Konto" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:7 +msgid "" +"Use your email software to read your emails and open your confirmation " +"email. Either click directly on the confirmation link or copy/paste the " +"confirmation key in the box and submit the form." +msgstr "" +"Benutze Deine E-Mail-Software, um Deine E-Mails zu lesen und öffne die " +"Bestätigungs-E-Mail. Klicke dann entweder direkt auf den Bestätigungs-Link " +"oder kopiere den Bestätigungsschlüssel direkt in das Eingabefeld hinein und " +"sende das Formular ab." + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:8 +msgid "" +"Just after providing the confirmation key, you will be able to set your " +"password and start using this website fully." +msgstr "" +"Direkt nachdem Du den Bestätigungsschlüssel angegeben hast, bist Du in der " +"Lage, Dein Passwort zu setzen und diese Webseite voll zu nutzen." + +#: IDF/gettexttemplates/idf/review/base-full.html.php:3 +#: IDF/gettexttemplates/idf/review/base.html.php:3 +msgid "Open Reviews" +msgstr "Offene Code-Besprechungen" + +#: IDF/gettexttemplates/idf/review/base.html.php:4 +#: IDF/gettexttemplates/idf/review/create.html.php:11 +#: IDF/gettexttemplates/idf/review/index.html.php:3 IDF/Views/Review.php:83 +msgid "Start Code Review" +msgstr "Neue Code-Besprechung starten" + +#: IDF/gettexttemplates/idf/review/create.html.php:3 +msgid "" +"

To start a code review, you need to provide:

\n" +"
    \n" +"
  • A commit or revision of the current code in the repository from which " +"you started your work.
  • \n" +"
  • A patch describing your changes with respect to the reference " +"commit.
  • \n" +"
  • Check your patch does not provide any password or confidential " +"information!
  • \n" +"
" +msgstr "" +"

Wenn Du eine Code-Besprechung erstellst, musst Du folgende Angaben " +"machen:

\n" +"
    \n" +"
  • Eine Revision Deines derzeitigen Codes im Depot, von der aus Du Deine " +"Arbeit begonnen hast.
  • \n" +"
  • Ein Patch, welches die Änderungen ausgehend von der Referenz-Revision " +"beschreibt.
  • \n" +"
  • Überprüfe, dass Dein Patch keine Passwörter oder vertraulichen " +"Angaben enthält!
  • \n" +"
" + +#: IDF/gettexttemplates/idf/review/create.html.php:9 +msgid "" +"The form contains some errors. Please correct them to submit the code review." +msgstr "" +"Die Eingabemaske enthält einige Fehler. Bitte korrigiere diese, um die " +"Code-Besprechung einzusenden." + +#: IDF/gettexttemplates/idf/review/create.html.php:10 +msgid "" +"Select the commit against which you created your patch to be sure it applies " +"correctly." +msgstr "" +"Wähle die Revision aus, gegen welche Du Dein Patch erstellt hast und stelle " +"sicher, dass das Patch auf diese Revision korrekt angewandt werden kann." + +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:3 +msgid "The following review has been created:" +msgstr "Die folgende Code-Besprechung wurde erstellt:" + +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:16 +msgid "Review:" +msgstr "Code-Besprechung:" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:3 +msgid "The following review has been updated:" +msgstr "Die folgende Code-Besprechung wurde aktualisiert:" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:5 +#, php-format +msgid "" +"By %%who%%, %%c.creation_dtime%%, on file:\n" +"%%c.cfile%%\n" +msgstr "" +"Von %%who%%, %%c.creation_dtime%%, für Datei:\n" +"%%c.cfile%%\n" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:14 +msgid "General comments (last first):" +msgstr "Allgemeine Kommentare (neueste zuerst):" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:15 +msgid "Detailed file comments (last first):" +msgstr "Detaillierte Dateikommentare (neueste zuerst):" + +#: IDF/gettexttemplates/idf/review/view.html.php:3 +msgid "" +"Code review is a process in which\n" +"after or before changes are commited into the code repository,\n" +"different people discuss the code changes. The goal is\n" +"to improve the quality of the code and the\n" +"contributions, as such, you must be pragmatic when writing\n" +"your review. Correctly mention the line numbers (in the old or in the\n" +"new file) and try to keep a good balance between seriousness and fun.\n" +msgstr "" +"Eine Code-Besprechung ist ein Prozess, in welchem bevor oder nachdem\n" +"Änderungen in das Quellcode-Depot eingepflegt wurden, verschiedene\n" +"Personen über diese Änderungen diskutieren. Das Ziel ist die\n" +"Qualität des Codes und des Beitrages zu verbessern,\n" +"und deshalb solltest Du beim Schreiben Deiner Code-Besprechung pragmatisch\n" +"sein. Benenne die korrekten Zeilennummern für Deine Kommentare (in der\n" +"alten oder der neuen Datei) und versuche, eine gute Balance zwischen\n" +"Ernsthaftigkeit und Spass zu bewahren.\n" + +#: IDF/gettexttemplates/idf/review/view.html.php:11 +msgid "" +"\n" +"Proposing code for review is intimidating, you know\n" +"you will receive critics, so please, as a reviewer, keep this\n" +"process fun, use it to help your contributor learn your\n" +"coding standards and the structure of the code and make them want\n" +"to propose more contributions.\n" +msgstr "" +"\n" +"Eine Code-Besprechung kann einschüchternd wirken.\n" +"Du als Rezensent weißt, dass Du Kritik erhalten wirst, deshalb\n" +"versuche, dem Prozess nicht den Spass zu nehmen, sondern\n" +"nutze ihn, um Deinen Aspiranten Deine Coding-Standards und die Struktur\n" +"Deines Codes zu lehren und bring sie dazu, mehr " +"beizutragen.\n" + +#: IDF/gettexttemplates/idf/review/view.html.php:18 +#: IDF/gettexttemplates/idf/source/commit.html.php:3 +#: IDF/gettexttemplates/idf/source/commit.html~.php:3 +#, php-format +msgid "%%ndiff%% diff" +msgid_plural "%%ndiff%% diffs" +msgstr[0] "%%ndiff%% Änderung" +msgstr[1] "%%ndiff%% Änderungen" + +#: IDF/gettexttemplates/idf/review/view.html.php:19 +#, php-format +msgid "%%nc%% comment" +msgid_plural "%%nc%% comments" +msgstr[0] "%%nc%% Kommentar" +msgstr[1] "%%nc%% Kommentare" + +#: IDF/gettexttemplates/idf/review/view.html.php:20 +#, php-format +msgid "" +"Comment %%i%% by %%who%%, " +"%%c.creation_dtime%%" +msgstr "" +"Kommentar %%i%% von %%who%%, %%c.creation_dtime%%" + +#: IDF/gettexttemplates/idf/review/view.html.php:21 +#, php-format +msgid "Your comments on the changes in file %%file%%:" +msgstr "Deine Kommentare der Änderungen in der Datei %%file%%:" + +#: IDF/gettexttemplates/idf/review/view.html.php:23 +#, php-format +msgid "Sign in to participate in the review." +msgstr "" +"Melde Dich an, um an der Code-Besprechung " +"teilzunehmen." + +#: IDF/gettexttemplates/idf/review/view.html.php:24 +msgid "" +"The form contains some errors. Please correct them to submit your review." +msgstr "" +"Die Eingabemaske enthält einige Fehler. Bitte korrigiere diese, um die " +"Code-Besprechung einzusenden." + +#: IDF/gettexttemplates/idf/review/view.html.php:25 +msgid "How to Participate in a Code Review" +msgstr "Wie man an einer Code-Besprechung teilnimmt" + +#: IDF/gettexttemplates/idf/review/view.html.php:28 +#: IDF/gettexttemplates/idf/source/commit.html.php:5 +#: IDF/gettexttemplates/idf/source/commit.html~.php:5 +msgid "Author:" +msgstr "Autor:" + +#: IDF/gettexttemplates/idf/review/view.html.php:29 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/source/commit.html.php:7 +#: IDF/gettexttemplates/idf/source/commit.html~.php:7 +msgid "Commit:" +msgstr "Revision" + +#: IDF/gettexttemplates/idf/review/view.html.php:30 +#: IDF/gettexttemplates/idf/source/commit.html.php:8 +#: IDF/gettexttemplates/idf/source/commit.html~.php:8 +msgid "View corresponding source tree" +msgstr "Zeige den dazugehörigen Quellcode-Baum" + +#: IDF/gettexttemplates/idf/review/view.html.php:32 +msgid "Reviewers:" +msgstr "Rezensenten:" + +#: IDF/gettexttemplates/idf/review/view.html.php:33 +msgid "No reviewers at the moment." +msgstr "Derzeit gibt es keine Rezensenten." + +#: IDF/gettexttemplates/idf/review/view.html.php:34 +msgid "Files:" +msgstr "Dateien:" + +#: IDF/gettexttemplates/idf/review/view.html.php:36 +#: IDF/gettexttemplates/idf/source/commit.html.php:24 +#: IDF/gettexttemplates/idf/source/commit.html~.php:23 +msgid "Download the corresponding diff file" +msgstr "Dazugehörige Unterschiedsdatei herunterladen" + +#: IDF/gettexttemplates/idf/review/view.html.php:37 +msgid "General Comments" +msgstr "Allgemeine Kommentare" + +#: IDF/gettexttemplates/idf/review/view.html.php:40 +msgid "Submit Code Review" +msgstr "Code-Besprechung einsenden" + +#: IDF/gettexttemplates/idf/source/base.html.php:3 +msgid "Source Tree" +msgstr "Quellcode-Baum" + +#: IDF/gettexttemplates/idf/source/base.html.php:4 +msgid "Change Log" +msgstr "Änderungsliste" + +#: IDF/gettexttemplates/idf/source/base.html.php:6 +msgid "How To Get The Code" +msgstr "Wie man den Code bekommt" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:3 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:8 IDF/Views/Project.php:190 +msgid "Age" +msgstr "Alter" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:4 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:10 +msgid "Message" +msgstr "Logmeldung" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:5 +msgid "Parent:" +msgstr "Eltern:" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:6 +#: IDF/gettexttemplates/idf/source/commit.html.php:10 +#: IDF/gettexttemplates/idf/source/commit.html~.php:10 +msgid "View corresponding commit" +msgstr "Zeige dazugehörige Revision" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:8 +msgid "by" +msgstr "von" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:3 +msgid "A new commit has been created:" +msgstr "Eine neue Revision wurde erzeugt:" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:8 +msgid "Created by:" +msgstr "Erstellt von:" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:8 +msgid "Created at:" +msgstr "Erstellt am:" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:8 +msgid "Content:" +msgstr "Inhalt:" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:10 +msgid "Commit details:" +msgstr "Revision-Details:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:4 +#: IDF/gettexttemplates/idf/source/commit.html~.php:4 +msgid "Date:" +msgstr "Datum:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:6 +#: IDF/gettexttemplates/idf/source/commit.html~.php:6 +msgid "Branch:" +msgstr "Zweig:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:9 +#: IDF/gettexttemplates/idf/source/commit.html~.php:9 +msgid "Parents:" +msgstr "Eltern:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:11 +#: IDF/gettexttemplates/idf/source/commit.html~.php:11 +msgid "Message:" +msgstr "Logmeldung:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:12 +#: IDF/gettexttemplates/idf/source/commit.html~.php:12 +#: IDF/gettexttemplates/idf/wiki/feedfragment-page.xml.php:3 +#: IDF/gettexttemplates/idf/wiki/feedfragment-resource.xml.php:3 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:10 +msgid "Changes:" +msgstr "Änderungen:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:13 +#: IDF/gettexttemplates/idf/source/commit.html~.php:13 +msgid "deleted" +msgstr "gelöscht" + +#: IDF/gettexttemplates/idf/source/commit.html.php:14 +#: IDF/gettexttemplates/idf/source/commit.html.php:18 +#: IDF/gettexttemplates/idf/source/commit.html~.php:14 +#: IDF/gettexttemplates/idf/source/commit.html~.php:17 +msgid "full" +msgstr "voll" + +#: IDF/gettexttemplates/idf/source/commit.html.php:15 +#: IDF/gettexttemplates/idf/source/commit.html~.php:15 +msgid "renamed" +msgstr "umbenannt" + +#: IDF/gettexttemplates/idf/source/commit.html.php:16 +msgid "copied" +msgstr "kopiert" + +#: IDF/gettexttemplates/idf/source/commit.html.php:17 +#: IDF/gettexttemplates/idf/source/commit.html~.php:16 +msgid "added" +msgstr "hinzugefügt" + +#: IDF/gettexttemplates/idf/source/commit.html.php:19 +#: IDF/gettexttemplates/idf/source/commit.html~.php:18 +msgid "modified" +msgstr "verändert" + +#: IDF/gettexttemplates/idf/source/commit.html.php:20 +msgid "properties changed" +msgstr "Eigenschaften geändert" + +#: IDF/gettexttemplates/idf/source/commit.html.php:21 +#: IDF/gettexttemplates/idf/source/commit.html~.php:20 +msgid "removed" +msgstr "entfernt" + +#: IDF/gettexttemplates/idf/source/commit.html.php:22 +#: IDF/gettexttemplates/idf/source/commit.html~.php:21 +msgid "File differences" +msgstr "Dateiunterschiede" + +#: IDF/gettexttemplates/idf/source/commit.html~.php:19 +msgid "properies changed" +msgstr "Eigenschaften geändert" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:3 +#, php-format +msgid "" +"The revision identifier %%commit%% is ambiguous and can be\n" +"expanded to multiple valid revisions - please choose one:" +msgstr "" +"Die Revisionskennung %%commit%% ist mehrdeutig und kann\n" +"zu mehreren gültigen Revisionen erweitert werden - bitte wähle eine:" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:5 +msgid "Title" +msgstr "Titel" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:6 +msgid "Author" +msgstr "Autor" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:7 +msgid "Date" +msgstr "Datum" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:8 +msgid "Branch" +msgstr "Zweig" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:9 +msgid "Revision" +msgstr "Revision" + +#: IDF/gettexttemplates/idf/source/feedfragment.xml.php:3 +#, php-format +msgid "%%cproject.name%%: Commit %%c.scm_id%%" +msgstr "%%cproject.name%%: Revision %%c.scm_id%%" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:3 +msgid "Branches" +msgstr "Zweige" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:4 +msgid "filter branches" +msgstr "Zweige filtern" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:5 +msgid "Tags" +msgstr "Tags" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:6 +msgid "filter tags" +msgstr "Tags filtern" + +#: IDF/gettexttemplates/idf/source/git/file.html.php:3 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:4 +#, php-format +msgid "" +"Source at commit %%commit%% created " +"%%cobject.date%%." +msgstr "" +"Quellcode bei Revision %%commit%% " +"erzeugt %%cobject.date%%." + +#: IDF/gettexttemplates/idf/source/git/file.html.php:4 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:5 +#, php-format +msgid "By %%cobject.author%%, %%cobject.title%%" +msgstr "Von %%cobject.author%%, %%cobject.title%%" + +#: IDF/gettexttemplates/idf/source/git/file.html.php:5 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:6 +msgid "Root" +msgstr "Wurzel" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the git software to manage the source\n" +"code." +msgstr "" +"Das Team von %%project%% nutzt git\n" +"als Software zur Versionsverwaltung." + +#: IDF/gettexttemplates/idf/source/git/help.html.php:6 +#, php-format +msgid "" +"You may need to provide your SSH key. The " +"synchronization of your SSH key can take a couple of minutes. You can learn " +"more about SSH " +"key authentication." +msgstr "" +"Eventuell musst Du Deinen SSH-Schlüssel hochladen. " +"Die Synchronizierung Deines SSH-Schlüssels kann einige Minuten dauern. Du " +"kannst hier " +"mehr über SSH-Schlüssel-Authentifizierung erfahren." + +#: IDF/gettexttemplates/idf/source/git/help.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:6 +msgid "To make a first commit in the repository, perform the following steps:" +msgstr "" +"Um eine erste Revision ins Depot einzupflegen, führe die folgenden Schritte " +"aus:" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:8 +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:7 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:7 +#, php-format +msgid "Find here more details on how to access %%project%% source code." +msgstr "" +"Hier findest Du mehr Information, wie Du auf den Quellcode von %%project%% " +"zugreifst." + +#: IDF/gettexttemplates/idf/source/git/help.html.php:9 +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:8 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:8 +msgid "Command-Line Access" +msgstr "Zugriff über die Kommandozeile" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:10 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:9 +msgid "First Commit" +msgstr "Erste Revision" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:11 +#: IDF/Views/Download.php:66 IDF/Views/Download.php:348 +msgid "Size" +msgstr "Größe" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:12 +msgid ":" +msgstr ":" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:13 +msgid "Download this version" +msgstr "Diese Version herunterladen" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:13 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:13 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:14 +msgid "or" +msgstr "oder" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:3 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:3 +#, php-format +msgid "" +"The branch or revision %%commit%% is not valid or does not exist\n" +"in this repository." +msgstr "" +"Der Zweig oder die Revision %%commit%% ist ungültig oder existiert " +"nicht\n" +"in diesem Depot." + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:5 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:5 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:5 +msgid "The following list shows all available branches:" +msgstr "Die folgende Liste führt alle verfügbaren Zweige auf:" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:6 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:6 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:6 +#, php-format +msgid "" +"If this is a new repository, the reason for this error\n" +"could be that you have not committed and / or pushed any change so far.\n" +"In this case please take a look at the Help page\n" +"how to access your repository." +msgstr "" +"Falls dies ein neues Depot ist, könnte der Grund für diesen Fehler sein,\n" +"dass Du bislang noch keine Änderungen eingepflegt oder zum Server " +"übertragen\n" +"hast. In diesem Fall sieh bitte auf der Hilfe-Seite\n" +"nach, wie Du auf Dein Depot zugreifen kannst." + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the Mercurial software to manage the source\n" +"code." +msgstr "" +"Das Team von %%project%% nutzt Mercurial\n" +"als Software zur Versionsverwaltung." + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:6 +#, php-format +msgid "" +"To get write access to the repository, you need to use your username and " +"your extra password." +msgstr "" +"Um Schreibberechtigungen auf das Depot zu erhalten, benötigst Du Deinen " +"Anmeldenamen und Dein zusätzliches Passwort." + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:9 +msgid "Write Access Authentication" +msgstr "Authentifizierung für Schreibberechtigung" + +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:3 +#, php-format +msgid "Property %%prop%% set to %%val%%" +msgstr "Eigenschaft %%prop%% auf %%val%% gesetzt" + +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the monotone software to manage the source\n" +"code." +msgstr "" +"Das Team von %%project%% nutzt monotone\n" +"als Software zur Versionsverwaltung." + +#: IDF/gettexttemplates/idf/source/svn/changelog.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/commit.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/commit.html~.php:3 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:14 +msgid "Revision:" +msgstr "Revision:" + +#: IDF/gettexttemplates/idf/source/svn/changelog.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/commit.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/commit.html~.php:4 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:10 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:15 +msgid "Switch" +msgstr "Wechseln" + +#: IDF/gettexttemplates/idf/source/svn/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the subversion software to manage the source\n" +"code." +msgstr "" +"Das Team von %%project%% nutzt subversion\n" +"als Software zur Versionsverwaltung." + +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:3 +#, php-format +msgid "" +"The revision %%commit%% is not valid or does not exist\n" +"in this repository." +msgstr "" +"Die Revision %%commit%% ist ungültig oder existiert nicht\n" +"in diesem Depot." + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:9 +msgid "Rev" +msgstr "Revision" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:16 +msgid "Branches:" +msgstr "Zweige:" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:17 +msgid "Tags:" +msgstr "Tags:" + +#: IDF/gettexttemplates/idf/user/changeemail-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"To confirm that you want %%email%%\n" +"to be your new email address, just follow this link:\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following verification key:\n" +"\n" +"%%key%%\n" +"\n" +"If you do not want to change your email address, \n" +"just ignore this message.\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" +"Hallo %%user%%,\n" +"\n" +"Um zu bestätigen, dass %%email%% Deine neue E-Mail-Adresse\n" +"sein soll, folge bitte einfach diesem Link:\n" +"\n" +"%%url%%\n" +"\n" +"Alternativ gehe zu dieser Seite:\n" +"\n" +"%%urlik%%\n" +"\n" +"und gib den folgenden Validierungs-Schlüssel ein:\n" +"\n" +"%%key%%\n" +"\n" +"Wenn Du Deine E-Mail-Adresse nicht ändern möchtest,\n" +"ignoriere diese E-Mail einfach.\n" +"\n" +"Mit freundlichen Grüßen,\n" +"Das Entwickler-Team.\n" + +#: IDF/gettexttemplates/idf/user/changeemail.html.php:4 +msgid "Confirm Your New Email Address" +msgstr "Bestätige Deine neue Email-Adresse" + +#: IDF/gettexttemplates/idf/user/changeemail.html.php:7 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:7 +msgid "" +"Use your email software to read your emails and open your verification " +"email. Either click directly on the verification link or copy/paste the " +"verification key in the box and submit the form." +msgstr "" +"Benutze Deine E-Mail-Software um Deine E-Mails zu lesen und Deine " +"Validierungs-E-Mail zu öffnen. Klicke dann entweder direkt auf den " +"Validierungs-Link oder kopiere den Validierungsschlüssel aus der E-Mail in " +"das Eingabefeld und sende das Formular ab." + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:3 +#, php-format +msgid "Update your account." +msgstr "Aktualisiere Dein Benutzerkonto." + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:4 +#, php-format +msgid "See your public profile." +msgstr "Zeige Dein öffentliches Profil." + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:5 +#, php-format +msgid "See your forge issue watch list." +msgstr "" +"Zeige Deine Forge-weite Ticket-Beobachtungliste." + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:6 +msgid "Key Management" +msgstr "Schlüsselverwaltung" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:7 +msgid "Secondary Emails" +msgstr "Sekundäre E-Mails" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:8 +msgid "Extra password" +msgstr "Extra-Passwort" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:9 +msgid "" +"This password is used to access some of the external systems managed by our " +"infrastructure. It will be regenerated if you change your password." +msgstr "" +"Dieses Passwort wird genutzt, um auf einige externe Systeme unserer " +"Infrastruktur zuzugreifen. Es wird neu erzeugt, wenn Du Dein Passwort " +"änderst." + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:10 +msgid "API key" +msgstr "API-Schlüssel" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:11 +msgid "" +"Your API key will be regenerated automatically if you change your password." +msgstr "" +"Dein API-Schlüssel wird automatisch neu erzeugt, wenn Du Dein Passwort " +"änderst." + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:12 +msgid "Update Your Account" +msgstr "Aktualisiere Deinen Account" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:14 +msgid "Your Current Public Keys" +msgstr "Deine derzeitigen öffentlichen Schlüssel" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:15 +msgid "Delete this key" +msgstr "Lösche diesen Schlüssel" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:16 +msgid "Your additional email addresses" +msgstr "Deine zusätzlichen E-Mail-Adressen" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:17 +msgid "Delete this address" +msgstr "Lösche diese Adresse" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:18 +msgid "" +"If possible, use your real name. By using your real name, people will have " +"more trust in your comments and remarks." +msgstr "" +"Wenn möglich, nutze Deinen realen Namen. Dadurch wird Deinen Kommentaren und " +"Bemerkungen mehr Vertrauen geschenkt." + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:19 +msgid "" +"The extra password is used to access some of the external systems and the " +"API key is used to interact with this website using a program." +msgstr "" +"Das Extra-Passwort wird genutzt, um auf einige externe Systeme zuzugreifen. " +"Der API-Schlüssel wird benötigt, damit andere Programme mit dieser Webseite " +"interagieren können." + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:20 +msgid "Show API key and extra password" +msgstr "Zeige API-Schlüssel und Extra-Passwort" + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:3 +msgid "" +"Oops, please check the provided login or email address to recover your " +"password." +msgstr "" +"Bitte überprüfe den angegebenen Anmeldenamen oder E-Mail-Adresse, um Dein " +"Passwort zurückzusetzen." + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:4 +msgid "Recover My Password" +msgstr "Mein Passwort wiederherstellen" + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:6 +msgid "" +"Provide either your login or email address, if a corresponding user is found " +"in the database, we will send you an email with the details on how to reset " +"your password." +msgstr "" +"Gib entweder Deinen Anmeldenamen oder Deine E-Mail-Adresse an. Wenn ein " +"entsprechender Benutzer in der Datenbank gefunden wird, schicken wir Dir " +"eine E-Mail mit Informationen, wie Du Dein Passwort zurücksetzen kannst." + +#: IDF/gettexttemplates/idf/user/passrecovery-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"You lost your password and wanted to recover it.\n" +"To provide a new password for your account, you\n" +"just have to follow the provided link. You will\n" +"get a simple form to provide a new password.\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following verification key:\n" +"\n" +"%%key%%\n" +"\n" +"If you are not the one who requested to reset\n" +"your password, simply ignore this email, your\n" +"password will not be changed.\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" +"Hallo %%user%%,\n" +"\n" +"Du hast Dein Passwort verloren und möchtest es wiederherstellen.\n" +"Um ein neues Passwort für Dein Benutzerkonto anzugeben, musst Du lediglich\n" +"dem folgenden Link folgen. Sie führt zu einer einfachen Eingabemaske,\n" +"mit der Du ein neues Passwort setzen kannst.\n" +"\n" +"%%url%%\n" +"\n" +"Alternativ gehe zu dieser Seite:\n" +"\n" +"%%urlik%%\n" +"\n" +"und gib den folgenden Validierungs-Schlüssel ein:\n" +"\n" +"%%key%%\n" +"\n" +"Wenn Du nicht derjenige bist, der das Zurücksetzen des Passworts\n" +"angefragt hat, ignoriere einfach diese E-Mail. Dein Passwort wird\n" +"in diesem Fall nicht geändert.\n" +"\n" +"Mit freundlichen Grüßen,\n" +"Das Entwickler-Team.\n" + +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:4 +msgid "Recover Your Password" +msgstr "Passwort wiederherstellen" + +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:8 +msgid "" +"Just after providing the confirmation key, you will be able to reset your " +"password and use this website fully." +msgstr "" +"Kurz nachdem Du den Bestätigungscode eingegeben hast, wirst Du Dein Passwort " +"zurücksetzen und diese Webseite voll nutzen können." + +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:6 +msgid "Reset Your Password" +msgstr "Passwort zurücksetzen" + +#: IDF/gettexttemplates/idf/user/public.html.php:3 +#, php-format +msgid "You are looking at the public profile of %%member%%." +msgstr "Du siehst Dir das öffentliche Profil von %%member%% an." + +#: IDF/gettexttemplates/idf/user/public.html.php:5 +msgid "Twitter:" +msgstr "Twitter:" + +#: IDF/gettexttemplates/idf/user/public.html.php:6 +msgid "Public Email:" +msgstr "Öffentliche E-Mail:" + +#: IDF/gettexttemplates/idf/user/public.html.php:7 +msgid "Website:" +msgstr "Webseite:" + +#: IDF/gettexttemplates/idf/user/public.html.php:8 +msgid "Last time seen:" +msgstr "Zuletzt gesehen:" + +#: IDF/gettexttemplates/idf/user/public.html.php:9 +msgid "Member since:" +msgstr "Mitglied seit:" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:3 +msgid "List Pages" +msgstr "Seiten anzeigen" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:4 +msgid "List Resources" +msgstr "Ressourcen anzeigen" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:5 +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:4 +#: IDF/gettexttemplates/idf/wiki/search.html.php:3 IDF/Views/Wiki.php:211 +msgid "New Page" +msgstr "Neue Seite" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:6 +#: IDF/gettexttemplates/idf/wiki/listResources.html.php:3 IDF/Views/Wiki.php:256 +msgid "New Resource" +msgstr "Neue Ressource" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:7 +msgid "Update This Page" +msgstr "Diese Seite aktualisieren" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:8 +msgid "Update This Resource" +msgstr "Diese Ressource aktualisieren" + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:3 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:3 +msgid "Preview of the Page" +msgstr "Vorschau der Seite" + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:7 +msgid "The form contains some errors. Please correct them to create the page." +msgstr "" +"Die Eingabemaske enthält einige Fehler. Bitte korrigiere diese, um die Seite " +"anzulegen." + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:6 +msgid "Create Page" +msgstr "Seite anlegen" + +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:3 +msgid "" +"\n" +"Wiki resources are later addressed in wiki pages by their title, so ensure " +"that you\n" +"give your resource a unique and an easy to remember name.\n" +msgstr "" +"\n" +"Wiki-Ressourcen werden später in Wiki-Seiten über ihren Titel referenziert,\n" +"stelle also sicher, dass Du Deiner Ressource einen eindeutigen und einfach\n" +"zu merkenden Namen gibst.\n" + +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:8 +msgid "Create Resource" +msgstr "Ressource anlegen" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:3 +msgid "" +"If you delete this documentation page, it will be removed from the database " +"with all the associated revisions and you will not be able to " +"recover it." +msgstr "" +"Wenn Du diese Dokumentations-Seite löscht, wird sie mit all ihren Versionen " +"aus der Datenbank gelöscht und Du wirst nicht in der Lage sein, sie " +"wiederherzustellen." + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:6 +msgid "Delete Page" +msgstr "Lösche Seite" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:14 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:15 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:15 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:17 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:18 +msgid "Old Revisions" +msgstr "Alte Versionen" + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:3 +#, php-format +msgid "" +"You are looking at an old revision (%%oldrev.summary%%) of the page " +"\n" +"%%page.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" +"Du schaust Dir gerade eine alte Version (%%oldrev.summary%%) der " +"Seite \n" +"%%page.title%% an. Diese Version wurde von\n" +"%%submitter%% angelegt." + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:5 +msgid "" +"If you delete this old revision, it will be removed from the database and " +"you will not be able to recover it." +msgstr "" +"Wenn Du diese alte Version löscht, wird sie von der Datenbank entfernt und " +"kann nicht wiederhergestellt werden." + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:8 +msgid "Delete Revision" +msgstr "Version löschen" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:3 +msgid "" +"If you delete this documentation resource, it will be removed from the " +"database with all the associated revisions \n" +"and you will not be able to recover it. Any documentation " +"pages that reference this resource,\n" +"will no longer be able to render it, but won't be deleted." +msgstr "" +"Wenn Du diese Dokumentations-Ressource löscht, wird sie mit all ihren " +"Versionen aus der Datenbank gelöscht und Du wirst nicht in der Lage " +"sein, sie wiederherzustellen. Jede Dokumentations-Seite, die auf " +"diese Ressource verweist, wird nicht mehr in der Lage sein, die Ressource " +"anzuzeigen, wird aber selbst nicht gelöscht." + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:8 +msgid "Delete Resource" +msgstr "Ressource löschen" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:10 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:8 +msgid "File size" +msgstr "Dateigröße" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:9 IDF/Views/Wiki.php:101 +msgid "MIME type" +msgstr "MIME-Typ" + +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:3 +#, php-format +msgid "" +"You are looking at an old revision (%%oldrev.summary%%) of the " +"resource \n" +"%%resource.title%%. This revision was created by " +"%%submitter%%." +msgstr "" +"Du schaust Dir gerade eine alte Version (%%oldrev.summary%%) der " +"Ressource \n" +"%%resource.title%% an. Diese Version wurde von\n" +"%%submitter%% angelegt." + +#: IDF/gettexttemplates/idf/wiki/edit-info.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

The content of the page can use the Markdown " +"syntax with the Extra extension.

\n" +"

Website addresses are automatically linked and you can link to another " +"page in the documentation using double square brackets like that " +"[[AnotherPage]].

\n" +"

If you want to embed uploaded resources, use the " +"[[!ResourceName]] syntax for that. This is described more in " +"detail in the FAQ.

\n" +"

To directly include a file content from the repository, embrace its path " +"with triple square brackets: [[[my/file.txt]]].

\n" +msgstr "" +"\n" +"

Anleitung:

\n" +"

Für den Inhalt der Seite kann die Markdown-Syntax mit der Extra-Erweiterung verwendet werden.

\n" +"

Website-Adresses werden automatisch verlinkt und Du kannst außerdem zu " +"anderen Dokumentations-Seiten durch die Benutzung von doppelten, eckigen " +"Klammern verlinken, etwa so: [[AndereSeite]].

\n" +"

Wenn Du hochgeladene Ressourcen einbetten möchtest, verwende die " +"[[!RessourcenName]]-Syntax dafür. Dies wird in der FAQ näher beschrieben.

\n" +"

Um direkt die Inhalte einer Datei aus dem Depot einzubinden, umklammere " +"den Pfad zur Datei mit dreifachen, eckigen Klammern: " +"[[[Pfad/zu/Datei.txt]]].

\n" + +#: IDF/gettexttemplates/idf/wiki/feedfragment-resource.xml.php:4 +msgid "Initial creation" +msgstr "Initiale Erzeugung" + +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:3 +#, php-format +msgid "See the deprecated pages." +msgstr "Zeige die veralteten Seiten." + +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:5 +msgid "Number of pages:" +msgstr "Anzahl der Seiten:" + +#: IDF/gettexttemplates/idf/wiki/listResources.html.php:4 +msgid "Number of resources:" +msgstr "Anzahl der Ressourcen:" + +#: IDF/gettexttemplates/idf/wiki/search.html.php:4 +msgid "Pages found:" +msgstr "Gefundene Seiten:" + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:3 +msgid "The form contains some errors. Please correct them to update the page." +msgstr "" +"Die Eingabemaske enthält einige Fehler. Bitte korrigiere diese, um die Seite " +"zu aktualisieren." + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:6 +msgid "Update Page" +msgstr "Seite aktualisieren" + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:10 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:11 +msgid "Delete this page" +msgstr "Lösche diese Seite" + +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:4 +msgid "Update Resource" +msgstr "Ressource aktualisieren" + +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:8 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:9 +msgid "Delete this resource" +msgstr "Lösche diese Ressource" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:3 +msgid "" +"Attention! This page is marked as deprecated, \n" +"use it as reference only if you are sure you need these specific information." +msgstr "" +"Achtung! Diese Seite ist als veraltet markiert. Nutze sie " +"nur als Referenz, wenn Du diese spezifischen Informationen benötigst." + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:5 +#, php-format +msgid "" +"You are looking at an old revision of the page \n" +"%%page.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" +"Du siehst gerade eine alte Version der Seite \n" +"%%page.title%%. Diese Version wurde\n" +"von %%submitter%% erzeugt." + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:10 +msgid "Table of Content" +msgstr "Inhaltsverzeichnis" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:13 +msgid "Delete this revision" +msgstr "Lösche diese Version" + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:3 +#, php-format +msgid "" +"You are looking at an old revision of the resource \n" +"%%resource.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" +"Du siehst Dir gerade eine alte Version der Ressource \n" +"%%resource.title%% an. Diese Version wurde\n" +"von %%submitter%% erzeugt." + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:14 +msgid "Page Usage" +msgstr "Seitennutzung" + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:15 +msgid "This resource is not used on any pages yet." +msgstr "Diese Ressource wird noch auf keiner Seite benutzt." + +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:3 +msgid "A new documentation page has been created:" +msgstr "Eine neue Dokumentations-Seite wurde angelegt:" + +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:14 +msgid "Documentation page:" +msgstr "Dokumentations-Seite:" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:3 +msgid "The following documentation page has been updated:" +msgstr "Die folgende Dokumentations-Seite wurde aktualisiert:" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:7 +msgid "Updated by:" +msgstr "Aktualisiert von:" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:13 +msgid "New content:" +msgstr "Neuer Inhalt:" + +#: IDF/Issue.php:76 +msgid "owner" +msgstr "Besitzer" + +#: IDF/Issue.php:84 IDF/Wiki/Page.php:86 +msgid "interested users" +msgstr "interessierte Benutzer" + +#: IDF/Issue.php:85 +msgid "" +"Interested users will get an email notification when the issue is changed." +msgstr "" +"Interessierte Benutzer werden eine E-Mail erhalten, wenn das Ticket geändert " +"wird." + +#: IDF/Issue.php:92 IDF/Project.php:94 IDF/Review.php:95 IDF/Upload.php:99 +#: IDF/Wiki/Page.php:94 +msgid "labels" +msgstr "Labels" + +#: IDF/Issue.php:111 IDF/IssueFile.php:102 IDF/Review.php:114 +#: IDF/Upload.php:118 IDF/Wiki/Page.php:106 IDF/Wiki/Resource.php:101 +msgid "modification date" +msgstr "Änderungsdatum" + +#: IDF/Issue.php:212 IDF/IssueComment.php:143 +#, php-format +msgid "" +"Issue %3$d, %4$s" +msgstr "" +"Ticket %3$d, " +"%4$s" + +#: IDF/Issue.php:214 +#, php-format +msgid "Creation of issue %3$d, by %4$s" +msgstr "" +"Erstellung von Ticket %3$d, von %4$s" + +#: IDF/Issue.php:224 +#, php-format +msgid "%1$s: Issue %2$d created - %3$s" +msgstr "%1$s: Ticket %2$d angelegt - %3$s" + +#: IDF/Issue.php:307 +#, php-format +msgid "Issue %1$s - %2$s (%3$s)" +msgstr "Ticket %1$s - %2$s (%3$s)" + +#: IDF/Issue.php:311 +#, php-format +msgid "Updated Issue %1$s - %2$s (%3$s)" +msgstr "Ticket %1$s aktualisiert - %2$s (%3$s)" + +#: IDF/IssueComment.php:51 IDF/IssueRelation.php:47 +msgid "issue" +msgstr "Ticket" + +#: IDF/IssueComment.php:58 IDF/IssueFile.php:49 IDF/Review/Comment.php:62 +#: IDF/Review/FileComment.php:49 IDF/Review/FileComment.php:69 +msgid "comment" +msgstr "Kommentar" + +#: IDF/IssueComment.php:72 IDF/Review/Comment.php:75 IDF/Upload.php:63 +#: IDF/Wiki/PageRevision.php:85 +msgid "changes" +msgstr "Änderungen" + +#: IDF/IssueComment.php:73 +msgid "Serialized array of the changes in the issue." +msgstr "Serialisierte Liste von Änderungen im Ticket." + +#: IDF/IssueComment.php:180 +#, php-format +msgid "Comment on issue %3$d, by %4$s" +msgstr "" +"Kommentar zum Ticket %3$d, von %4$s" + +#: IDF/IssueComment.php:191 +#, php-format +msgid "%1$s: Comment on issue %2$d - %3$s" +msgstr "%1$s: Kommentar zum Ticket %2$d - %3$s" + +#: IDF/IssueFile.php:64 +msgid "file name" +msgstr "Dateiname" + +#: IDF/IssueFile.php:70 +msgid "the file" +msgstr "die Datei" + +#: IDF/IssueFile.php:76 +msgid "file size" +msgstr "Dateigröße" + +#: IDF/IssueFile.php:84 +msgid "type" +msgstr "Typ" + +#: IDF/IssueFile.php:86 +msgid "Image" +msgstr "Bild" + +#: IDF/IssueFile.php:87 +msgid "Other" +msgstr "Andere" + +#: IDF/IssueRelation.php:54 +msgid "verb" +msgstr "Verb" + +#: IDF/IssueRelation.php:61 +msgid "other issue" +msgstr "anderes Ticket" + +#: IDF/Key.php:55 +msgid "public key" +msgstr "öffentlicher Schlüssel" + +#: IDF/Key.php:90 +msgid "Invalid or unknown key data detected." +msgstr "Ungültige oder unbekannte Schlüsseldaten bemerkt." + +#: IDF/Plugin/SyncMercurial.php:78 IDF/Plugin/SyncSvn.php:81 +#, php-format +msgid "The repository %s already exists." +msgstr "Das Depot %s existiert bereits." + +#: IDF/Plugin/SyncMercurial.php:142 +#, php-format +msgid "%s does not exist or is not writable." +msgstr "%s existiert nicht oder ist nicht schreibbar." + +#: IDF/Plugin/SyncMonotone.php:107 IDF/Plugin/SyncMonotone.php:492 +msgid "\"mtn_repositories\" must be defined in your configuration file" +msgstr "\"mtn_repositories\" muss in Deiner Konfigurationsdatei definiert sein" + +#: IDF/Plugin/SyncMonotone.php:114 IDF/Plugin/SyncMonotone.php:482 +msgid "\"mtn_usher_conf\" does not exist or is not writable" +msgstr "\"mtn_usher_conf\" existiert nicht oder ist nicht schreibbar" + +#: IDF/Plugin/SyncMonotone.php:121 +#, php-format +msgid "Could not find mtn-post-push script \"%s\"" +msgstr "Konnte das mtn-post-push-Skript \"%s\" nicht finden" + +#: IDF/Plugin/SyncMonotone.php:155 +#, php-format +msgid "The configuration file \"%s\" is missing" +msgstr "Die Konfigurationsdatei \"%s\" fehlt" + +#: IDF/Plugin/SyncMonotone.php:164 +#, php-format +msgid "The project path \"%s\" already exists" +msgstr "Der Projektpfad \"%s\" existiert bereits" + +#: IDF/Plugin/SyncMonotone.php:170 +#, php-format +msgid "The project path \"%s\" could not be created" +msgstr "Der Projektpfad \"%s\" konnte nicht angelegt werden" + +#: IDF/Plugin/SyncMonotone.php:208 +#, php-format +msgid "The key directory \"%s\" could not be created" +msgstr "Das Schlüsselverzeichnis \"%s\" konnte nicht erstellt werden" + +#: IDF/Plugin/SyncMonotone.php:227 +#, php-format +msgid "Could not parse key information: %s" +msgstr "Konnte die Schlüsselinformationen nicht analysieren: %s" + +#: IDF/Plugin/SyncMonotone.php:265 +#, php-format +msgid "Could not create configuration directory \"%s\"" +msgstr "Konnte Konfigurationsverzeichnis \"%s\" nicht erstellen" + +#: IDF/Plugin/SyncMonotone.php:275 +#, php-format +msgid "Could not create symlink for configuration file \"%s\"" +msgstr "" +"Konnte den symbolischen Link für die Konfigurationsdatei \"%s\" nicht anlegen" + +#: IDF/Plugin/SyncMonotone.php:293 +#, php-format +msgid "Could not write configuration file \"%s\"" +msgstr "Konnte die Konfigurationsdatei \"%s\" nicht schreiben" + +#: IDF/Plugin/SyncMonotone.php:309 IDF/Plugin/SyncMonotone.php:525 +#, php-format +msgid "Could not parse usher configuration in \"%1$s\": %2$s" +msgstr "Konnte die usher-Konfiguration in \"%1$s\" nicht analysieren: %2$s" + +#: IDF/Plugin/SyncMonotone.php:320 +#, php-format +msgid "usher configuration already contains a server entry named \"%s\"" +msgstr "" +"Die usher-Konfiguration enthält bereits einen Servereintrag mit dem Namen " +"\"%s\"" + +#: IDF/Plugin/SyncMonotone.php:345 IDF/Plugin/SyncMonotone.php:546 +#, php-format +msgid "Could not write usher configuration file \"%s\"" +msgstr "Konnte die usher-Konfigurationsdatei \"%s\" nicht schreiben" + +#: IDF/Plugin/SyncMonotone.php:395 +#, php-format +msgid "Could not write write-permissions file \"%s\"" +msgstr "Konnte die write-permissions-Datei \"%s\" nicht schreiben" + +#: IDF/Plugin/SyncMonotone.php:420 +#, php-format +msgid "Could not write read-permissions file \"%s\"" +msgstr "Konnte die read-permissions-Datei \"%s\" nicht schreiben" + +#: IDF/Plugin/SyncMonotone.php:438 +#, php-format +msgid "Could not remove symlink \"%s\"" +msgstr "Konnte symbolischen Link \"%s\" nicht entfernen" + +#: IDF/Plugin/SyncMonotone.php:446 +#, php-format +msgid "Could not create symlink \"%s\"" +msgstr "Konnte symbolischen Link \"%s\" nicht erstellen" + +#: IDF/Plugin/SyncMonotone.php:500 +#, php-format +msgid "One or more paths underneath %s could not be deleted" +msgstr "Ein oder mehrere Pfade unterhalb %s konnten nicht gelöscht werden" + +#: IDF/Plugin/SyncMonotone.php:512 +#, php-format +msgid "Could not delete client private key \"%s\"" +msgstr "Konnte privaten Schlüssel \"%s\" des Clients nicht löschen" + +#: IDF/Plugin/SyncMonotone.php:599 IDF/Plugin/SyncMonotone.php:718 +#, php-format +msgid "Could not parse read-permissions for project \"%1$s\": %2$s" +msgstr "" +"Konnte read-permissions-Datei für Projekt \"%1$s\" nicht analysieren: %2$s" + +#: IDF/Plugin/SyncMonotone.php:643 IDF/Plugin/SyncMonotone.php:741 +#, php-format +msgid "Could not write read-permissions for project \"%s\"" +msgstr "Konnte read-permissions-Datei für Projekt \"%s\" nicht schreiben." + +#: IDF/Plugin/SyncMonotone.php:657 IDF/Plugin/SyncMonotone.php:760 +#, php-format +msgid "Could not write write-permissions file for project \"%s\"" +msgstr "Konnte write-permissions-Datei für Projekt \"%s\" nicht schreiben." + +#: IDF/Plugin/SyncMonotone.php:813 +msgid "\"mtn_repositories\" must be defined in your configuration file." +msgstr "" +"Die Variable \"mtn_repositories\" muss in der Konfigurationsdatei definiert " +"sein." + +#: IDF/Plugin/SyncMonotone.php:820 +#, php-format +msgid "The project path %s does not exists." +msgstr "Der Projektpfad %s existiert nicht." + +#: IDF/Plugin/SyncMonotone.php:838 +#, php-format +msgid "The command \"%s\" could not be executed." +msgstr "Das Kommando \"%s\" konnte nicht ausgeführt werden." + +#: IDF/Project.php:62 IDF/Tag.php:66 +msgid "name" +msgstr "Name" + +#: IDF/Project.php:69 +msgid "short name" +msgstr "Kurzname" + +#: IDF/Project.php:70 +msgid "" +"Used in the URL to access the project, must be short with only letters and " +"numbers." +msgstr "" +"Wird in der URL benutzt, um auf das Projekt zuzugreifen. Muss kurz sein und " +"darf nur Buchstaben und Zahlen enthalten." + +#: IDF/Project.php:78 +msgid "short description" +msgstr "Kurzbeschreibung" + +#: IDF/Project.php:86 IDF/Review/Patch.php:74 +msgid "description" +msgstr "Beschreibung" + +#: IDF/Project.php:87 +msgid "The description can be extended using the Markdown syntax." +msgstr "" +"Die Beschreibung kann durch die Benutzung der markdown-Syntax erweitert " +"werden." + +#: IDF/Project.php:100 +msgid "private" +msgstr "privat" + +#: IDF/Project.php:108 +msgid "current project activity" +msgstr "Derzeitige Projektaktivität" + +#: IDF/Project.php:159 +#, php-format +msgid "Project \"%s\" not found." +msgstr "Projekt \"%s\" nicht gefunden." + +#: IDF/ProjectActivity.php:56 +msgid "date" +msgstr "Datum" + +#: IDF/Review/Comment.php:55 IDF/Review/Patch.php:80 +msgid "patch" +msgstr "Patch" + +#: IDF/Review/Comment.php:83 +msgid "vote" +msgstr "abstimmen" + +#: IDF/Review/Comment.php:139 IDF/Review/Patch.php:151 +#, php-format +msgid "" +"Review %3$d, %4$s" +msgstr "" +"Code-Besprechung %3$d, %4$s" + +#: IDF/Review/Comment.php:141 +#, php-format +msgid "Update of review %3$d, by %4$s" +msgstr "" +"Aktualisierung von Code-Besprechung " +"%3$d, von %4$s" + +#: IDF/Review/Comment.php:151 +#, php-format +msgid "%1$s: Updated review %2$d - %3$s" +msgstr "%1$s: Aktualisierte Code-Besprechung %2$d - %3$s" + +#: IDF/Review/Comment.php:222 +#, php-format +msgid "Updated Code Review %1$s - %2$s (%3$s)" +msgstr "Aktualisierte Code-Besprechung %1$s - %2$s (%3$s)" + +#: IDF/Review/Patch.php:52 +msgid "review" +msgstr "Code-Besprechung" + +#: IDF/Review/Patch.php:67 +msgid "commit" +msgstr "Revision" + +#: IDF/Review/Patch.php:153 +#, php-format +msgid "Creation of review %3$d, by %4$s" +msgstr "" +"Erzeugung von Code-Besprechung %3$d, von " +"%4$s" + +#: IDF/Review/Patch.php:163 +#, php-format +msgid "%1$s: Creation of Review %2$d - %3$s" +msgstr "%1$s: Erstellung von Code-Besprechung %2$d -%3$s" + +#: IDF/Review/Patch.php:208 +#, php-format +msgid "New Code Review %1$s - %2$s (%3$s)" +msgstr "Neue Code-Besprechung %1$s - %2$s (%3$s)" + +#: IDF/Scm/Git.php:309 IDF/Scm/Mercurial.php:199 +#, php-format +msgid "Folder %1$s not found in commit %2$s." +msgstr "Verzeichnis %1$s in Revision %2$s nicht gefunden." + +#: IDF/Scm/Git.php:433 IDF/Scm/Mercurial.php:216 +#, php-format +msgid "Not a valid tree: %s." +msgstr "Kein gültiger Quellcode-Baum: %s." + +#: IDF/Scm/Monotone/Stdio.php:81 +msgid "Monotone client key name or hash not in project conf." +msgstr "" +"Kein monotone-Client-Schlüsselname oder -prüfsumme in Projektkonfiguration " +"gefunden." + +#: IDF/Scm/Monotone/Stdio.php:89 +#, php-format +msgid "The key directory %s could not be created." +msgstr "Das Schlüsselverzeichnis %s konnte nicht erstellt werden." + +#: IDF/Scm/Monotone/Stdio.php:100 +#, php-format +msgid "Could not write client key \"%s\"" +msgstr "Konnte Client-Schlüssel \"%s\" nicht schreiben" + +#: IDF/Search/Occ.php:33 +msgid "occurrence" +msgstr "Vorkommen" + +#: IDF/Search/Occ.php:49 +msgid "word" +msgstr "Wort" + +#: IDF/Search/Occ.php:75 +msgid "occurrences" +msgstr "Vorkommen" + +#: IDF/Search/Occ.php:81 +msgid "ponderated occurrence" +msgstr "gewichtete Vorkommen" + +#: IDF/Tag.php:59 +msgid "tag class" +msgstr "Tag-Klasse" + +#: IDF/Tag.php:60 +msgid "The class of the tag." +msgstr "Die Klasse des Tags." + +#: IDF/Tag.php:73 +msgid "lcname" +msgstr "Kleingeschriebener Name" + +#: IDF/Tag.php:74 +msgid "Lower case version of the name for fast searching." +msgstr "Kleingeschriebene Version des Namens zur schnelleren Suche." + +#: IDF/Template/Markdown.php:84 +msgid "Create this documentation page" +msgstr "Erstelle diese Dokumentations-Seite" + +#: IDF/Template/Markdown.php:97 +msgid "You are not allowed to access the wiki." +msgstr "Dir ist es nicht erlaubt, auf das Wiki zuzugreifen." + +#: IDF/Template/Markdown.php:106 +msgid "The wiki resource has not been found." +msgstr "Die Wiki-Ressource wurde nicht gefunden." + +#: IDF/Template/Markdown.php:113 +msgid "The wiki resource has not been found. Create it!" +msgstr "Die Wiki-Ressource wurde nicht gefunden. Lege sie an!" + +#: IDF/Template/Markdown.php:146 +msgid "This revision of the resource is no longer available." +msgstr "Diese Version der Ressource ist nicht mehr verfügbar." + +#: IDF/Template/ShowUser.php:51 +msgid "Anonymous" +msgstr "Anonym" + +#: IDF/Template/ShowUser.php:54 +msgid "Me" +msgstr "mir" + +#: IDF/Timeline/Paginator.php:49 +msgid "Today" +msgstr "Heute" + +#: IDF/Upload.php:70 +msgid "file" +msgstr "Datei" + +#: IDF/Upload.php:71 +msgid "The path is relative to the upload path." +msgstr "Der Pfad ist relativ zum Upload-Pfad." + +#: IDF/Upload.php:78 IDF/Wiki/ResourceRevision.php:71 +msgid "file size in bytes" +msgstr "Dateigröße in Bytes" + +#: IDF/Upload.php:84 +msgid "MD5" +msgstr "MD5" + +#: IDF/Upload.php:106 +msgid "number of downloads" +msgstr "Anzahl der Downloads" + +#: IDF/Upload.php:201 +#, php-format +msgid "Download %2$d, %3$s" +msgstr "Download %2$d, %3$s" + +#: IDF/Upload.php:204 +#, php-format +msgid "Addition of download %2$d, by %3$s" +msgstr "Hinzufügen von Download %2$d, von %3$s" + +#: IDF/Upload.php:214 +#, php-format +msgid "%1$s: Download %2$d added - %3$s" +msgstr "%1$s: Download %2$d hinzugefügt - %3$s" + +#: IDF/Upload.php:301 +#, php-format +msgid "New download - %1$s (%2$s)" +msgstr "Neuer Download - %1$s (%2$s)" + +#: IDF/Upload.php:305 +#, php-format +msgid "Updated download - %1$s (%2$s)" +msgstr "Download aktualisiert - %1$s (%2$s)" + +#: IDF/Views/Admin.php:47 +msgid "The forge configuration has been saved." +msgstr "Die Forge-Einstellungen wurden gespeichert." + +#: IDF/Views/Admin.php:80 +msgid "This table shows the projects in the forge." +msgstr "Diese Tabelle zeigt die Projekte dieser Forge." + +#: IDF/Views/Admin.php:85 +msgid "Short Name" +msgstr "Kurzname" + +#: IDF/Views/Admin.php:87 +msgid "Repository Size" +msgstr "Größe des Depots" + +#: IDF/Views/Admin.php:93 +msgid "No projects were found." +msgstr "Es wurden keine Projekte gefunden." + +#: IDF/Views/Admin.php:116 +msgid "The label configuration has been saved." +msgstr "Die Marken-Einstellungen wurden gespeichert." + +#: IDF/Views/Admin.php:147 IDF/Views/Admin.php:314 IDF/Views/Wiki.php:484 +#: IDF/Views/Wiki.php:536 +#, php-format +msgid "Update %s" +msgstr "Aktualisiere %s" + +#: IDF/Views/Admin.php:155 IDF/Views/Project.php:304 +msgid "The project has been updated." +msgstr "Das Projekt wurde aktualisiert." + +#: IDF/Views/Admin.php:192 +msgid "The project has been created." +msgstr "Das Projekt wurde angelegt." + +#: IDF/Views/Admin.php:223 +#, php-format +msgid "Delete %s Project" +msgstr "Lösche Projekt %s" + +#: IDF/Views/Admin.php:230 +msgid "The project has been deleted." +msgstr "Das Projekt wurde gelöscht." + +#: IDF/Views/Admin.php:260 +msgid "Not Validated User List" +msgstr "Liste nicht validierter Benutzer" + +#: IDF/Views/Admin.php:268 +msgid "This table shows the users in the forge." +msgstr "Diese Tabelle zeigt die Benutzer dieser Forge." + +#: IDF/Views/Admin.php:272 +msgid "login" +msgstr "Anmeldename" + +#: IDF/Views/Admin.php:275 +msgid "Admin" +msgstr "Administrator" + +#: IDF/Views/Admin.php:277 +msgid "Last Login" +msgstr "Letztes Login" + +#: IDF/Views/Admin.php:284 +msgid "No users were found." +msgstr "Es wurden keine Benutzer gefunden." + +#: IDF/Views/Admin.php:321 +msgid "You do not have the rights to update this user." +msgstr "Du hast nicht die Berechtigung, um diesen Benutzer zu aktualisieren." + +#: IDF/Views/Admin.php:339 +msgid "The user has been updated." +msgstr "Der Benutzer wurde aktualisiert." + +#: IDF/Views/Admin.php:372 +#, php-format +msgid "The user %s has been created." +msgstr "Der Benutzer %s wurde erstellt." + +#: IDF/Views/Admin.php:379 +msgid "Add User" +msgstr "Benutzer hinzufügen" + +#: IDF/Views/Admin.php:395 +msgid "Usher management" +msgstr "Usher-Verwaltung" + +#: IDF/Views/Admin.php:432 +msgid "Usher configuration has been reloaded" +msgstr "Usher-Konfiguration neu geladen" + +#: IDF/Views/Admin.php:436 +msgid "Usher has been shut down" +msgstr "Usher wurde heruntergefahren." + +#: IDF/Views/Admin.php:441 +msgid "Usher has been started up" +msgstr "Usher wurde hochgefahren." + +#: IDF/Views/Admin.php:479 +#, php-format +msgid "The server \"%s\" has been started" +msgstr "Der Server \"%s\" wurde gestartet." + +#: IDF/Views/Admin.php:483 +#, php-format +msgid "The server \"%s\" has been stopped" +msgstr "Der Server \"%s\" wurde gestoppt." + +#: IDF/Views/Admin.php:488 +#, php-format +msgid "The server \"%s\" has been killed" +msgstr "Der Server \"%s\" wurde getötet." + +#: IDF/Views/Admin.php:508 +#, php-format +msgid "Open connections for \"%s\"" +msgstr "Offene Verbindungen für \"%s\"" + +#: IDF/Views/Admin.php:513 +#, php-format +msgid "no connections for server \"%s\"" +msgstr "keine Verbindungen für Server \"%s\"" + +#: IDF/Views/Admin.php:534 +msgid "Yes" +msgstr "Ja" + +#: IDF/Views/Admin.php:534 +msgid "No" +msgstr "Nein" + +#: IDF/Views/Download.php:45 +#, php-format +msgid "%s Downloads" +msgstr "%s Downloads" + +#: IDF/Views/Download.php:51 +msgid "This table shows the files to download." +msgstr "Diese Tabelle zeigt die herunterladbaren Dateien." + +#: IDF/Views/Download.php:67 IDF/Views/Download.php:349 +msgid "Uploaded" +msgstr "Hochgeladen" + +#: IDF/Views/Download.php:71 IDF/Views/Download.php:353 +msgid "No downloads were found." +msgstr "Keine Downloads gefunden." + +#: IDF/Views/Download.php:94 +#, php-format +msgid "Download %s" +msgstr "Lade %s herunter" + +#: IDF/Views/Download.php:111 +#, php-format +msgid "The file %2$s has been updated." +msgstr "Die Datei %2$s wurde aktualisiert." + +#: IDF/Views/Download.php:144 +#, php-format +msgid "Delete Download %s" +msgstr "Lösche Download %s" + +#: IDF/Views/Download.php:177 +msgid "The file has been deleted." +msgstr "Die Datei wurde gelöscht." + +#: IDF/Views/Download.php:244 +#, php-format +msgid "The file has been uploaded." +msgstr "Die Datei wurde hochgeladen." + +#: IDF/Views/Download.php:271 +msgid "New Downloads from Archive" +msgstr "Neue Downloads aus einem Archiv" + +#: IDF/Views/Download.php:278 +msgid "The archive has been uploaded and processed." +msgstr "Das Archiv wurde hochgeladen und verarbeitet." + +#: IDF/Views/Download.php:331 +#, php-format +msgid "%1$s Downloads with Label %2$s" +msgstr "%1$s Downloads mit der Marke %2$s" + +#: IDF/Views/Download.php:341 +#, php-format +msgid "This table shows the downloads with label %s." +msgstr "Diese Tabelle zeigt die Downloads mit der Marke %s." + +#: IDF/Views/Issue.php:41 +#, php-format +msgid "%s Open Issues" +msgstr "%s Offene Tickets" + +#: IDF/Views/Issue.php:51 IDF/Views/Issue.php:382 IDF/Views/User.php:75 +msgid "This table shows the open issues." +msgstr "Diese Tabelle zeigt die offenen Tickets." + +#: IDF/Views/Issue.php:61 IDF/Views/Issue.php:220 IDF/Views/Issue.php:301 +#: IDF/Views/Issue.php:390 IDF/Views/Issue.php:542 IDF/Views/Issue.php:765 +#: IDF/Views/Issue.php:824 IDF/Views/Review.php:57 IDF/Views/User.php:81 +msgid "Id" +msgstr "Id" + +#: IDF/Views/Issue.php:64 IDF/Views/Issue.php:223 IDF/Views/Issue.php:305 +#: IDF/Views/Issue.php:393 IDF/Views/Issue.php:545 IDF/Views/Issue.php:768 +#: IDF/Views/Issue.php:827 IDF/Views/Review.php:60 IDF/Views/User.php:85 +msgid "Last Updated" +msgstr "Letzte Aktualisierung" + +#: IDF/Views/Issue.php:68 IDF/Views/Issue.php:227 IDF/Views/Issue.php:309 +#: IDF/Views/Issue.php:397 IDF/Views/Issue.php:549 IDF/Views/Issue.php:772 +#: IDF/Views/Issue.php:831 +msgid "No issues were found." +msgstr "Es wurden keine Tickets gefunden." + +#: IDF/Views/Issue.php:113 +msgid "Not assigned" +msgstr "Nicht zugeordnet" + +#: IDF/Views/Issue.php:149 +#, php-format +msgid "Summary of tracked issues in %s." +msgstr "Zusammenfassung verfolgter Tickets in %s" + +#: IDF/Views/Issue.php:194 +#, php-format +msgid "Watch List: Closed Issues for %s" +msgstr "Beobachtungsliste: Geschlossene Tickets für %s" + +#: IDF/Views/Issue.php:195 +#, php-format +msgid "This table shows the closed issues in your watch list for %s project." +msgstr "" +"Diese Tabelle zeigt die geschlossenen Tickets auf Deiner Beobachtungsliste " +"für das Projekt %s." + +#: IDF/Views/Issue.php:200 +#, php-format +msgid "Watch List: Open Issues for %s" +msgstr "Beobachtungsliste: Offene Tickets für %s" + +#: IDF/Views/Issue.php:201 +#, php-format +msgid "This table shows the open issues in your watch list for %s project." +msgstr "" +"Diese Tabelle zeigt die offenen Tickets auf Deiner Beobachtungsliste für das " +"Projekt %s." + +#: IDF/Views/Issue.php:277 +msgid "Watch List: Closed Issues" +msgstr "Beobachtungsliste: Geschlossene Tickets" + +#: IDF/Views/Issue.php:278 +msgid "This table shows the closed issues in your watch list." +msgstr "" +"Diese Tabelle zeigt die geschlossenen Tickets auf Deiner Beobachtungsliste." + +#: IDF/Views/Issue.php:283 +msgid "Watch List: Open Issues" +msgstr "Beobachtungsliste: Offene Tickets" + +#: IDF/Views/Issue.php:284 +msgid "This table shows the open issues in your watch list." +msgstr "Diese Tabelle zeigt die offenen Tickets auf Deiner Beobachtungsliste." + +#: IDF/Views/Issue.php:303 IDF/Views/User.php:82 +msgid "Project" +msgstr "Projekt" + +#: IDF/Views/Issue.php:344 +#, php-format +msgid "%1$s %2$s Submitted %3$s Issues" +msgstr "%1$s %2$s eingesandte Tickets für %3$s" + +#: IDF/Views/Issue.php:348 +#, php-format +msgid "%1$s %2$s Closed Submitted %3$s Issues" +msgstr "%1$s %2$s eingesandte, geschlossene Tickets für %3$s" + +#: IDF/Views/Issue.php:352 +#, php-format +msgid "%1$s %2$s Closed Working %3$s Issues" +msgstr "%1$s %2$s bearbeitete, geschlossene Tickets für %3$s" + +#: IDF/Views/Issue.php:356 +#, php-format +msgid "%1$s %2$s Working %3$s Issues" +msgstr "%1$s %2$s bearbeitete Tickets für %3$s" + +#: IDF/Views/Issue.php:417 +msgid "Submit a new issue" +msgstr "Erstelle ein neues Ticket" + +#: IDF/Views/Issue.php:433 +#, php-format +msgid "Issue %2$d has been created." +msgstr "Ticket %2$d wurde erstellt." + +#: IDF/Views/Issue.php:490 +#, php-format +msgid "Search issues - %s" +msgstr "Suche Tickets - %s" + +#: IDF/Views/Issue.php:492 +#, php-format +msgid "Search closed issues - %s" +msgstr "Suche geschlossene Tickets - %s" + +#: IDF/Views/Issue.php:539 +msgid "This table shows the found issues." +msgstr "Diese Tabelle zeigt die gefundenen Tickets." + +#: IDF/Views/Issue.php:604 +#, php-format +msgid "Issue %2$d: %3$s" +msgstr "Ticket %2$d: %3$s" + +#: IDF/Views/Issue.php:628 +#, php-format +msgid "Issue %2$d has been updated." +msgstr "Ticket %2$d wurde aktualisiert." + +#: IDF/Views/Issue.php:718 +#, php-format +msgid "View %s" +msgstr "Zeige %s" + +#: IDF/Views/Issue.php:745 +#, php-format +msgid "%s Closed Issues" +msgstr "%s Geschlossene Tickets" + +#: IDF/Views/Issue.php:755 +msgid "This table shows the closed issues." +msgstr "Diese Tabelle zeigt die geschlossenen Tickets." + +#: IDF/Views/Issue.php:798 +#, php-format +msgid "%1$s Issues with Label %2$s" +msgstr "%1$s Tickets mit Markierung %2$s" + +#: IDF/Views/Issue.php:801 +#, php-format +msgid "%1$s Closed Issues with Label %2$s" +msgstr "%1$s geschlossene Tickets mit Markierung %2$s" + +#: IDF/Views/Issue.php:814 +#, php-format +msgid "This table shows the issues with label %s." +msgstr "Diese Tabelle zeigt die Tickets mit der Markierung %s." + +#: IDF/Views/Issue.php:937 +msgid "The issue has been removed from your watch list." +msgstr "Das Ticket wurde von Deiner Beobachtungsliste entfernt." + +#: IDF/Views/Issue.php:940 +msgid "The issue has been added to your watch list." +msgstr "Das Ticket wurde zu Deiner Beobachtungsliste hinzugefügt." + +#: IDF/Views/Issue.php:1037 +msgid "On your watch list." +msgstr "Auf Deiner Beobachtungsliste." + +#: IDF/Views/Project.php:95 +msgid "Issues and Comments" +msgstr "Tickets u. Kommentare" + +#: IDF/Views/Project.php:99 +msgid "Documents" +msgstr "Dokumentation" + +#: IDF/Views/Project.php:101 +msgid "Reviews and Patches" +msgstr "Besprechungen u. Patches" + +#: IDF/Views/Project.php:180 +msgid "This table shows the project updates." +msgstr "Diese Tabelle zeigt Projekt-Aktualisierungen." + +#: IDF/Views/Project.php:191 +msgid "Change" +msgstr "Änderung" + +#: IDF/Views/Project.php:195 +msgid "No changes were found." +msgstr "Es wurden keine Änderungen gefunden." + +#: IDF/Views/Project.php:296 +#, php-format +msgid "%s Project Summary" +msgstr "%s Projektzusammenfassung" + +#: IDF/Views/Project.php:335 +#, php-format +msgid "%s Issue Tracking Configuration" +msgstr "%s Ticket-Einstellungen" + +#: IDF/Views/Project.php:344 +msgid "The issue tracking configuration has been saved." +msgstr "Die Ticket-Einstellungen wurden gespeichert." + +#: IDF/Views/Project.php:381 +#, php-format +msgid "%s Downloads Configuration" +msgstr "%s Download-Einstellungen" + +#: IDF/Views/Project.php:393 +msgid "The downloads configuration has been saved." +msgstr "Die Download-Einstellungen wurden gespeichert." + +#: IDF/Views/Project.php:428 +#, php-format +msgid "%s Documentation Configuration" +msgstr "%s Dokumentations-Einstellungen" + +#: IDF/Views/Project.php:437 +msgid "The documentation configuration has been saved." +msgstr "Die Dokumentations-Einstellungen wurden gespeichert." + +#: IDF/Views/Project.php:471 +#, php-format +msgid "%s Project Members" +msgstr "%s Projektmitglieder" + +#: IDF/Views/Project.php:480 +msgid "The project membership has been saved." +msgstr "Die Projektmitgliedschaft wurde gespeichert." + +#: IDF/Views/Project.php:503 +#, php-format +msgid "%s Tabs Access Rights" +msgstr "%s Zugriffsrechte auf Registerkarten" + +#: IDF/Views/Project.php:517 +msgid "" +"The project tabs access rights and notification settings have been saved." +msgstr "" +"Die Zugriffsrechte für die Projekt-Registerkarten und die " +"Benachrichtigungseinstellungen wurden gespeichert." + +#: IDF/Views/Project.php:566 +#, php-format +msgid "%s Source" +msgstr "%s Quellcode" + +#: IDF/Views/Project.php:580 +msgid "The project source configuration has been saved." +msgstr "Die Konfiguration des Projekt-Quellcodes wurde gespeichert." + +#: IDF/Views/Review.php:41 +#, php-format +msgid "%s Code Reviews" +msgstr "%s Code-Besprechungen" + +#: IDF/Views/Review.php:48 +msgid "This table shows the latest reviews." +msgstr "Diese Tabelle zeigt die letzten Besprechungen." + +#: IDF/Views/Review.php:64 +msgid "No reviews were found." +msgstr "Es wurden keine Besprechungen gefunden." + +#: IDF/Views/Review.php:94 +#, php-format +msgid "The code review %2$d has been created." +msgstr "Die Code-Besprechung %2$d wurde erstellt." + +#: IDF/Views/Review.php:140 +#, php-format +msgid "Review %2$d: %3$s" +msgstr "Besprechung %2$d: %3$s" + +#: IDF/Views/Review.php:160 +#, php-format +msgid "Your code review %2$d has been published." +msgstr "Deine Code-Besprechung %2$d wurde veröffentlicht." + +#: IDF/Views/Source.php:40 +#, php-format +msgid "%s Source Help" +msgstr "%s Quellcode-Hilfe" + +#: IDF/Views/Source.php:58 +#, php-format +msgid "%s Invalid Revision" +msgstr "%s Ungültige Revision" + +#: IDF/Views/Source.php:82 +#, php-format +msgid "%s Ambiguous Revision" +msgstr "%s Mehrdeutige Revision" + +#: IDF/Views/Source.php:107 +#, php-format +msgid "%1$s %2$s Change Log" +msgstr "%1$s %2$s Logmeldung" + +#: IDF/Views/Source.php:153 IDF/Views/Source.php:234 IDF/Views/Source.php:362 +#, php-format +msgid "%1$s %2$s Source Tree" +msgstr "%1$s %2$s Quellcode-Baum" + +#: IDF/Views/Source.php:310 +#, php-format +msgid "%s Commit Details" +msgstr "%s Revisions-Details" + +#: IDF/Views/Source.php:311 +#, php-format +msgid "%1$s Commit Details - %2$s" +msgstr "%1$s Revisions-Details - %2$s" + +#: IDF/Views/User.php:59 +msgid "Your Dashboard - Working Issues" +msgstr "Dein Dashboard - Bearbeitete Tickets" + +#: IDF/Views/User.php:62 +msgid "Your Dashboard - Submitted Issues" +msgstr "Dein Dashboard - Eingesandte Tickets" + +#: IDF/Views/User.php:89 +msgid "No issues are assigned to you, yeah!" +msgstr "Es liegen keine Tickets für Dich vor. Super!" + +#: IDF/Views/User.php:89 +msgid "All the issues you submitted are fixed, yeah!" +msgstr "Alle Tickets, die Du eingesandt hast, sind gelöst! Super!" + +#: IDF/Views/User.php:121 +msgid "Your personal information has been updated." +msgstr "Deine persönlichen Daten wurden aktualisiert." + +#: IDF/Views/User.php:133 +msgid "Your Account" +msgstr "Dein Konto" + +#: IDF/Views/User.php:157 +msgid "The public key has been deleted." +msgstr "Der öffentliche Schlüssel wurde gelöscht." + +#: IDF/Views/User.php:177 +msgid "The address has been deleted." +msgstr "Die Adresse wurde gelöscht." + +#: IDF/Views/User.php:200 +msgid "Confirm The Email Change" +msgstr "Bestätige die Änderung der E-Mail-Adresse" + +#: IDF/Views/User.php:232 +#, php-format +msgid "Your new email address \"%s\" has been validated. Thank you!" +msgstr "Deine neue E-Mail-Adresse \"%s\" wurde validiert. Danke!" + +#: IDF/Views/Wiki.php:41 +#, php-format +msgid "%s Documentation" +msgstr "%s Dokumentation" + +#: IDF/Views/Wiki.php:48 +msgid "This table shows the documentation pages." +msgstr "Diese Tabelle zeigt Dokumentations-Seiten." + +#: IDF/Views/Wiki.php:61 IDF/Views/Wiki.php:144 IDF/Views/Wiki.php:185 +msgid "Page Title" +msgstr "Seitentitel" + +#: IDF/Views/Wiki.php:63 IDF/Views/Wiki.php:103 IDF/Views/Wiki.php:146 +#: IDF/Views/Wiki.php:187 +msgid "Updated" +msgstr "Aktualisiert" + +#: IDF/Views/Wiki.php:67 IDF/Views/Wiki.php:191 +msgid "No documentation pages were found." +msgstr "Keine Dokumentations-Seiten gefunden." + +#: IDF/Views/Wiki.php:88 +#, php-format +msgid "%s Documentation Resources" +msgstr "%s Dokumentations-Ressourcen" + +#: IDF/Views/Wiki.php:94 +msgid "This table shows the resources that can be used on documentation pages." +msgstr "" +"Diese Tabelle zeigt die Ressourcen an, die in Dokumentations-Seiten " +"eingebunden werden können." + +#: IDF/Views/Wiki.php:100 +msgid "Resource Title" +msgstr "Ressourcen-Titel" + +#: IDF/Views/Wiki.php:107 +msgid "No resources were found." +msgstr "Es wurden keine Ressourcen gefunden." + +#: IDF/Views/Wiki.php:128 +#, php-format +msgid "Documentation Search - %s" +msgstr "Dokumentations-Suche - %s" + +#: IDF/Views/Wiki.php:139 +msgid "This table shows the pages found." +msgstr "Diese Tabelle zeigt die gefunden Seiten." + +#: IDF/Views/Wiki.php:150 +msgid "No pages were found." +msgstr "Es wurden keine Seiten gefunden." + +#: IDF/Views/Wiki.php:169 +#, php-format +msgid "%1$s Documentation Pages with Label %2$s" +msgstr "%1$s Dokumentations-Seiten mit der Marke %2$s" + +#: IDF/Views/Wiki.php:179 +#, php-format +msgid "This table shows the documentation pages with label %s." +msgstr "Diese Tabelle zeigt die Dokumentations-Seiten mit der Bezeichnung %s." + +#: IDF/Views/Wiki.php:222 +#, php-format +msgid "The page %2$s has been created." +msgstr "Die Seite %2$s wurde neu angelegt." + +#: IDF/Views/Wiki.php:265 +#, php-format +msgid "The resource %2$s has been created." +msgstr "Die Ressource %2$s wurde neu angelegt." + +#: IDF/Views/Wiki.php:409 IDF/Views/Wiki.php:448 +msgid "The old revision has been deleted." +msgstr "Alte Version der Seite wurde gelöscht." + +#: IDF/Views/Wiki.php:415 IDF/Views/Wiki.php:454 +#, php-format +msgid "Delete Old Revision of %s" +msgstr "Lösche alte Version von %s" + +#: IDF/Views/Wiki.php:496 +#, php-format +msgid "The page %2$s has been updated." +msgstr "Die Seite %2$s wurde aktualisiert." + +#: IDF/Views/Wiki.php:548 +#, php-format +msgid "The resource %2$s has been updated." +msgstr "Die Ressource %2$s wurde aktualisiert." + +#: IDF/Views/Wiki.php:583 +msgid "The documentation page has been deleted." +msgstr "Die Dokumentations-Seite wurde gelöscht." + +#: IDF/Views/Wiki.php:591 +#, php-format +msgid "Delete Page %s" +msgstr "Lösche Seite '%s'" + +#: IDF/Views/Wiki.php:623 +msgid "The documentation resource has been deleted." +msgstr "Die Dokumentations-Ressource wurde gelöscht." + +#: IDF/Views/Wiki.php:631 +#, php-format +msgid "Delete Resource %s" +msgstr "Lösche Ressource %s" + +#: IDF/Views.php:173 IDF/Views.php:199 +msgid "Confirm Your Account Creation" +msgstr "Bestätige die Erstellung Deines Accounts" + +#: IDF/Views.php:219 +msgid "Welcome! You can now participate in the life of your project of choice." +msgstr "" +"Willkommen! Du kannst nun am Leben eines Projektes Deiner Wahl teilhaben." + +#: IDF/Views.php:245 IDF/Views.php:269 IDF/Views.php:310 +msgid "Password Recovery" +msgstr "Passwort-Wiederherstellung" + +#: IDF/Views.php:289 +msgid "" +"Welcome back! Next time, you can use your broswer options to remember the " +"password." +msgstr "" +"Willkommen zurück! Beim nächsten Mal kannst Du Deine Browsereinstellungen " +"nutzen, um Dich automatisch einzuloggen." + +#: IDF/Views.php:331 +msgid "Here to Help You!" +msgstr "Hier, um Dir zu helfen!" + +#: IDF/Views.php:347 +msgid "InDefero Upload Archive Format" +msgstr "InDefero Upload-Archivformat" + +#: IDF/Views.php:363 +msgid "InDefero API (Application Programming Interface)" +msgstr "InDefero API (Application Programming Interface)" + +#: IDF/Wiki/Page.php:62 IDF/Wiki/Resource.php:64 +msgid "title" +msgstr "Titel" + +#: IDF/Wiki/Page.php:63 +msgid "" +"The title of the page must only contain letters, digits or the dash " +"character. For example: My-new-Wiki-Page." +msgstr "" +"Der Titel der Seite darf nur Buchstaben, Zahlen oder einen Bindestrich " +"enthalten. Beispiel: Meine-neue-Wiki-Seite." + +#: IDF/Wiki/Page.php:71 +msgid "A one line description of the page content." +msgstr "Eine einzeilige Beschreibung des Seiteninhalts." + +#: IDF/Wiki/Page.php:196 IDF/Wiki/PageRevision.php:196 +#, php-format +msgid "%2$s, %3$s" +msgstr "%2$s, %3$s" + +#: IDF/Wiki/Page.php:198 +#, php-format +msgid "Creation of page %2$s, by %3$s" +msgstr "Erstellung von Seite %2$s, von %3$s" + +#: IDF/Wiki/Page.php:208 +#, php-format +msgid "%1$s: Documentation page %2$s added - %3$s" +msgstr "%1$s: Dokumentations-Seite %2$s hinzugefügt - %3$s" + +#: IDF/Wiki/PageRevision.php:48 +msgid "page" +msgstr "Seite" + +#: IDF/Wiki/PageRevision.php:66 IDF/Wiki/ResourceRevision.php:64 +msgid "A one line description of the changes." +msgstr "Eine einzeilige Beschreibung der Änderungen." + +#: IDF/Wiki/PageRevision.php:72 +msgid "content" +msgstr "Inhalt" + +#: IDF/Wiki/PageRevision.php:218 IDF/Wiki/ResourceRevision.php:311 +#, php-format +msgid "Change of %2$s, by %3$s" +msgstr "Änderung von %2$s, von %3$s" + +#: IDF/Wiki/PageRevision.php:231 +#, php-format +msgid "%1$s: Documentation page %2$s updated - %3$s" +msgstr "%1$s: Dokumentations-Seite %2$s aktualisiert - %3$s" + +#: IDF/Wiki/PageRevision.php:293 +#, php-format +msgid "New Documentation Page %1$s - %2$s (%3$s)" +msgstr "Neue Dokumentations-Seite %1$s - %2$s (%3$s)" + +#: IDF/Wiki/PageRevision.php:297 +#, php-format +msgid "Documentation Page Changed %1$s - %2$s (%3$s)" +msgstr "Dokumentations-Seite geändert %1$s - %2$s (%3$s)" + +#: IDF/Wiki/Resource.php:65 +msgid "" +"The title of the resource must only contain letters, digits, dots or the " +"dash character. For example: my-resource.png." +msgstr "" +"Der Titel der Ressource darf nur Buchstaben, Zahlen, Punkte oder einen " +"Bindestrich enthalten. Beispiel: meine-ressource.png." + +#: IDF/Wiki/Resource.php:72 +msgid "MIME media type" +msgstr "MIME-Medientyp" + +#: IDF/Wiki/Resource.php:73 +msgid "The MIME media type of the resource." +msgstr "Der MIME-Medientyp der Ressource." + +#: IDF/Wiki/Resource.php:81 +msgid "A one line description of the resource." +msgstr "Einzeilige Beschreibung der Ressource." + +#: IDF/Wiki/Resource.php:176 IDF/Wiki/ResourceRevision.php:308 +#, php-format +msgid "%2$s, %3$s" +msgstr "%2$s, %3$s" + +#: IDF/Wiki/Resource.php:178 +#, php-format +msgid "Creation of resource %2$s, by %3$s" +msgstr "Erstellung von Ressource %2$s, von %3$s" + +#: IDF/Wiki/Resource.php:188 +#, php-format +msgid "%1$s: Documentation resource %2$s added - %3$s" +msgstr "%1$s: Dokumentations-Ressource %2$s hinzugefügt - %3$s" + +#: IDF/Wiki/ResourceRevision.php:47 +msgid "resource" +msgstr "Ressource" + +#: IDF/Wiki/ResourceRevision.php:78 +msgid "File extension" +msgstr "Dateierweiterung" + +#: IDF/Wiki/ResourceRevision.php:79 +msgid "The file extension of the uploaded resource." +msgstr "Die Dateierweiterung der hochgeladenen Ressource." + +#: IDF/Wiki/ResourceRevision.php:94 +msgid "page usage" +msgstr "Seitennutzung" + +#: IDF/Wiki/ResourceRevision.php:116 +#, php-format +msgid "id %d: %s" +msgstr "id %d: %s" + +#: IDF/Wiki/ResourceRevision.php:263 +#, php-format +msgid "Download (%s)" +msgstr "Download (%s)" + +#: IDF/Wiki/ResourceRevision.php:270 +msgid "View resource details" +msgstr "Zeige Details der Ressource" + +#: IDF/Wiki/ResourceRevision.php:324 +#, php-format +msgid "%1$s: Documentation resource %2$s updated - %3$s" +msgstr "%1$s: Dokumentations-Ressource %2$s aktualisiert - %3$s" + +#~ msgid "" +#~ "The master branch is empty or contains illegal characters, please use " +#~ "only letters, digits, dashs and dots as separators." +#~ msgstr "" +#~ "Der Hauptzweig ist leer oder enthält ungültige Zeichen. Bitte verwende " +#~ "nur Buchstaben, Ziffern, Bindestriche und Punkte als Trenner." + +#~ msgid "" +#~ "You can define bidirectional relations like \"is related to\" or " +#~ "\"blocks, is blocked by\"." +#~ msgstr "" +#~ "Du kannst bidirektionale Verknüpfungen wie \"ist verknüpft mit\" oder " +#~ "\"blockiert, wird blockiert von\" angeben. Für die Standard-Verknüpfungen " +#~ "sind bereits Übersetzungen vorkonfiguriert, neue Verknüpfungstypen " +#~ "sollten jedoch in einer Sprache angegegeben werden, die von allen " +#~ "Projektteilnehmern verstanden wird." + +#~ msgid "Learn more about the post-commit web hooks." +#~ msgstr "Erfahre mehr über die post-commit Web-Hooks." + +#~ msgid "Your mail" +#~ msgstr "Deine E-Mail-Adresse" + +#~ msgid "" +#~ "Notification emails will be sent from the %%from_email%% " +#~ "address, if you send the email to a mailing list, you may need to " +#~ "register this email address. Multiple email addresses must be separated " +#~ "through commas (','). If you do not want to send emails for a given type " +#~ "of changes, simply leave the corresponding field empty." +#~ msgstr "" +#~ "Benachrichtungs-E-Mails werden mit der Absenderadresse " +#~ "%%from_email%% versandt. Wenn Du die E-Mail zu einer " +#~ "Mailingliste senden möchtest, musst Du eventuell diese E-Mail-Adresse " +#~ "dort registrieren. Mehrere E-Mail-Adressen müssen durch Kommas (',') " +#~ "voneinander getrennt werden. Wenn Du keine E-Mails für einen bestimmten " +#~ "Änderungstyp versenden möchtest, lasse das entsprechende Feld einfach " +#~ "leer." + +#~ msgid "You have here access to the administration of the forge." +#~ msgstr "Hier hast Du Zugriff auf die Administration der Forge." + +#~ msgid "Forge statistics" +#~ msgstr "Forge-Statistiken" + +#~ msgid "Projects:" +#~ msgstr "Projekte:" + +#~ msgid "You need to provide comments on at least one file." +#~ msgstr "Du musst Kommentare zu mindestens einer Datei angeben." + +#~ msgid "Open Issues" +#~ msgstr "Offene Tickets" + +#~ msgid "Found issues:" +#~ msgstr "Gefundene Tickets:" + +#~ msgid "Property" +#~ msgstr "Eigenschaft" + +#~ msgid "set to:" +#~ msgstr "gesetzt auf:" + +#, qt-format +#~ msgid "Invalid value for the parameter %1$s: %2$s. Use %3$s." +#~ msgstr "Ungültiger Wert für Parameter %1$s: %2$s. Nutze %3$s." diff --git a/indefero/src/IDF/locale/es_ES/idf.po b/indefero/src/IDF/locale/es_ES/idf.po new file mode 100644 index 0000000..fd736bb --- /dev/null +++ b/indefero/src/IDF/locale/es_ES/idf.po @@ -0,0 +1,6066 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Mika , 2011. +msgid "" +msgstr "" +"Project-Id-Version: Indefero\n" +"Report-Msgid-Bugs-To: http://projects.ceondo.com/p/indefero/issues/\n" +"POT-Creation-Date: 2012-03-22 01:16+0100\n" +"PO-Revision-Date: 2011-10-31 00:19+0000\n" +"Last-Translator: tommyd \n" +"Language-Team: LANGUAGE \n" +"Language: es_ES\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" + +#: IDF/Commit.php:55 IDF/Conf.php:54 IDF/Issue.php:52 +#: IDF/ProjectActivity.php:49 IDF/Review.php:65 IDF/Search/Occ.php:69 +#: IDF/Tag.php:52 IDF/Upload.php:49 IDF/Wiki/Page.php:54 +#: IDF/Wiki/Resource.php:56 +msgid "project" +msgstr "proyecto" + +#: IDF/Commit.php:63 IDF/Issue.php:67 IDF/IssueComment.php:65 +#: IDF/IssueFile.php:57 IDF/IssueRelation.php:69 IDF/Review/Comment.php:69 +#: IDF/Review.php:80 IDF/Upload.php:91 IDF/Wiki/Page.php:78 +#: IDF/Wiki/PageRevision.php:79 IDF/Wiki/Resource.php:88 +#: IDF/Wiki/ResourceRevision.php:86 +msgid "submitter" +msgstr "autor" + +#: IDF/Commit.php:87 IDF/Issue.php:60 IDF/Review/Patch.php:60 +#: IDF/Review.php:73 IDF/Upload.php:57 IDF/Wiki/Page.php:70 +#: IDF/Wiki/PageRevision.php:65 IDF/Wiki/Resource.php:80 +#: IDF/Wiki/ResourceRevision.php:63 +msgid "summary" +msgstr "resumen" + +#: IDF/Commit.php:93 +msgid "changelog" +msgstr "registro de cambios" + +#: IDF/Commit.php:100 IDF/Issue.php:105 IDF/IssueComment.php:79 +#: IDF/IssueFile.php:96 IDF/IssueRelation.php:75 IDF/Review/Comment.php:90 +#: IDF/Review/FileComment.php:75 IDF/Review/Patch.php:87 IDF/Review.php:108 +#: IDF/Upload.php:112 IDF/Wiki/Page.php:100 IDF/Wiki/PageRevision.php:92 +#: IDF/Wiki/Resource.php:95 IDF/Wiki/ResourceRevision.php:101 +msgid "creation date" +msgstr "fecha de creación" + +#: IDF/Commit.php:238 +#, fuzzy, php-format +msgid "Commit %1$s, by %2$s" +msgstr "Commit %s, por %s" + +#: IDF/Commit.php:337 +#, fuzzy, php-format +msgid "New Commit %1$s - %2$s (%3$s)" +msgstr "Nuevo Commit %s - %s (%s)" + +#: IDF/Conf.php:61 IDF/Gconf.php:73 +msgid "key" +msgstr "clave" + +#: IDF/Conf.php:67 IDF/Gconf.php:79 IDF/ProjectActivity.php:62 +msgid "value" +msgstr "valor" + +#: IDF/Diff.php:460 +msgid "Old" +msgstr "Antiguo" + +#: IDF/Diff.php:460 +msgid "New" +msgstr "Nuevo" + +#: IDF/EmailAddress.php:49 IDF/Key.php:49 +msgid "user" +msgstr "usuario" + +#: IDF/EmailAddress.php:55 +msgid "email" +msgstr "email" + +#: IDF/Form/Admin/ForgeConf.php:34 +msgid "Custom forge page enabled" +msgstr "" + +#: IDF/Form/Admin/ForgeConf.php:39 IDF/Form/WikiPageCreate.php:80 +#: IDF/Form/WikiPageUpdate.php:72 +msgid "Content" +msgstr "Contenido" + +#: IDF/Form/Admin/LabelConf.php:40 +#, fuzzy +msgid "Predefined project labels" +msgstr "Etiquetas de tickets predefinidas" + +#: IDF/Form/Admin/LabelConf.php:55 +#, php-format +msgid "" +"The label \"%s\" is invalid: A label must only consist of alphanumeric " +"characters and dashes, and can optionally contain a \":\" with a group " +"prefix." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:38 IDF/Views/Project.php:600 +msgid "git" +msgstr "git" + +#: IDF/Form/Admin/ProjectCreate.php:39 IDF/Views/Project.php:601 +msgid "Subversion" +msgstr "Subversion" + +#: IDF/Form/Admin/ProjectCreate.php:40 IDF/Views/Project.php:602 +msgid "mercurial" +msgstr "mercurial" + +#: IDF/Form/Admin/ProjectCreate.php:41 IDF/Views/Project.php:603 +msgid "monotone" +msgstr "monótono" + +#: IDF/Form/Admin/ProjectCreate.php:49 IDF/Form/Admin/ProjectUpdate.php:44 +#: IDF/Form/ProjectConf.php:39 IDF/Views/Admin.php:86 IDF/Views/Admin.php:273 +msgid "Name" +msgstr "Nombre" + +#: IDF/Form/Admin/ProjectCreate.php:55 IDF/Form/TabsConf.php:101 +#: IDF/gettexttemplates/idf/base-full.html.php:5 +#: IDF/gettexttemplates/idf/base-full.html~.php:5 +#: IDF/gettexttemplates/idf/base.html.php:5 +#: IDF/gettexttemplates/idf/base.html~.php:5 +#: IDF/gettexttemplates/idf/main-menu.html.php:9 +#: IDF/gettexttemplates/idf/project-list.html.php:5 +#: IDF/gettexttemplates/idf/project-list.html.php:7 +msgid "Private project" +msgstr "Proyecto privado" + +#: IDF/Form/Admin/ProjectCreate.php:62 +msgid "Shortname" +msgstr "Nombre corto" + +#: IDF/Form/Admin/ProjectCreate.php:64 +msgid "" +"It must be unique for each project and composed only of letters, digits and " +"dash (-) like \"my-project\"." +msgstr "" +"Debe ser único para cada proyecto y compuesto únicamente de letras, dígitos " +"y el guión (-), como \"mi-proyecto\"." + +#: IDF/Form/Admin/ProjectCreate.php:69 IDF/Form/Admin/ProjectUpdate.php:50 +msgid "Short description" +msgstr "Descripción corta" + +#: IDF/Form/Admin/ProjectCreate.php:70 IDF/Form/Admin/ProjectUpdate.php:51 +#: IDF/Project.php:79 +msgid "A one line description of the project." +msgstr "Una línea de descripción del proyecto." + +#: IDF/Form/Admin/ProjectCreate.php:77 IDF/Form/Admin/ProjectUpdate.php:58 +#: IDF/Form/ProjectConf.php:56 +msgid "External URL" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:84 +msgid "Repository type" +msgstr "Tipo de Repositorio" + +#: IDF/Form/Admin/ProjectCreate.php:92 +msgid "Remote Subversion repository" +msgstr "Repositorio remoto Subversion" + +#: IDF/Form/Admin/ProjectCreate.php:99 IDF/Form/SourceConf.php:40 +msgid "Repository username" +msgstr "Nombre de usuario del Repositorio" + +#: IDF/Form/Admin/ProjectCreate.php:106 IDF/Form/SourceConf.php:47 +msgid "Repository password" +msgstr "Contraseña del Repositorio" + +#: IDF/Form/Admin/ProjectCreate.php:113 IDF/Form/Admin/ProjectUpdate.php:66 +msgid "Master branch" +msgstr "Principal Branch" + +#: IDF/Form/Admin/ProjectCreate.php:116 IDF/Form/Admin/ProjectUpdate.php:69 +msgid "" +"This should be a world-wide unique identifier for your project. A reverse " +"DNS notation like \"com.my-domain.my-project\" is a good idea." +msgstr "" +"Este debe ser un identificador único para su proyecto. Una notación tipo DNS " +"inversa como \"com.mi-dominio.mi-proyecto\" es una buena elección." + +#: IDF/Form/Admin/ProjectCreate.php:121 IDF/Form/Admin/ProjectUpdate.php:95 +#: IDF/Form/MembersConf.php:46 IDF/Form/TabsConf.php:53 +#: IDF/Form/TabsConf.php:72 +msgid "Project owners" +msgstr "Propietarios del Proyecto" + +#: IDF/Form/Admin/ProjectCreate.php:130 IDF/Form/Admin/ProjectUpdate.php:103 +#: IDF/Form/MembersConf.php:54 IDF/Form/TabsConf.php:52 +#: IDF/Form/TabsConf.php:78 +msgid "Project members" +msgstr "Miembros del proyecto" + +#: IDF/Form/Admin/ProjectCreate.php:140 IDF/Form/Admin/ProjectUpdate.php:85 +#: IDF/Form/IssueCreate.php:168 IDF/Form/IssueUpdate.php:164 +#: IDF/Form/ProjectConf.php:73 IDF/Form/UpdateUpload.php:71 +#: IDF/Form/Upload.php:70 IDF/Form/WikiPageCreate.php:93 +#: IDF/Form/WikiPageUpdate.php:104 +msgid "Labels" +msgstr "Etiquetas" + +#: IDF/Form/Admin/ProjectCreate.php:155 +msgid "Project template" +msgstr "Plantilla de Proyecto" + +#: IDF/Form/Admin/ProjectCreate.php:157 +msgid "" +"Use the given project to initialize the new project. Access rights and " +"general configuration will be taken from the template project." +msgstr "" +"Utilizar el proyecto propuesto para iniciar un nuevo proyecto. Los permisos " +"de acceso y configuración general se tomarán de la plantilla de proyecto." + +#: IDF/Form/Admin/ProjectCreate.php:204 +msgid "" +"Only a remote repository available through HTTP or HTTPS is allowed. For " +"example \"http://somewhere.com/svn/trunk\"." +msgstr "" +"Solo un repositorio remoto HTTP o HTTPS está permitido. Por ejemplo, " +"\"http://dominio.com/svn/trunk\"." + +#: IDF/Form/Admin/ProjectCreate.php:220 IDF/Form/Admin/ProjectUpdate.php:117 +msgid "" +"The master branch is empty or contains illegal characters, please use only " +"letters, digits, dashes and dots as separators." +msgstr "" +"El principal branch está vacío o contiene caracteres no válidos, por favor " +"utiliza sólo letras, dígitos, guiones y puntos como separadores." + +#: IDF/Form/Admin/ProjectCreate.php:230 IDF/Form/Admin/ProjectUpdate.php:128 +msgid "This master branch is already used. Please select another one." +msgstr "Esta rama principal ya está en uso. Por favor, seleccione otra." + +#: IDF/Form/Admin/ProjectCreate.php:241 +msgid "" +"This shortname contains illegal characters, please use only letters, digits " +"and dash (-)." +msgstr "" +"Este nombre corto contiene caracteres no válidos, por favor utiliza sólo " +"letras, dígitos y el guión (-)." + +#: IDF/Form/Admin/ProjectCreate.php:244 +msgid "The shortname cannot start with the dash (-) character." +msgstr "El nombre corto no puede comenzar con el carácter guión (-)." + +#: IDF/Form/Admin/ProjectCreate.php:247 +msgid "The shortname cannot end with the dash (-) character." +msgstr "El nombre corto no puede terminar con el carácter guión (-)." + +#: IDF/Form/Admin/ProjectCreate.php:252 +msgid "This shortname is already used. Please select another one." +msgstr "Este nombre corto ya está en uso. Por favor, seleccione otro." + +#: IDF/Form/Admin/ProjectCreate.php:303 IDF/Form/Admin/ProjectDelete.php:78 +#: IDF/Form/Admin/ProjectUpdate.php:153 IDF/Form/Admin/UserCreate.php:106 +#: IDF/Form/Admin/UserUpdate.php:191 IDF/Form/IssueCreate.php:338 +#: IDF/Form/IssueUpdate.php:329 IDF/Form/MembersConf.php:64 +#: IDF/Form/Password.php:76 IDF/Form/Register.php:112 +#: IDF/Form/ReviewCreate.php:187 IDF/Form/ReviewFileComment.php:143 +#: IDF/Form/TabsConf.php:122 IDF/Form/UpdateUpload.php:126 +#: IDF/Form/Upload.php:149 IDF/Form/UploadArchive.php:137 +#: IDF/Form/UserAccount.php:216 IDF/Form/UserChangeEmail.php:80 +#: IDF/Form/WikiPageCreate.php:167 IDF/Form/WikiPageDelete.php:59 +#: IDF/Form/WikiPageUpdate.php:178 IDF/Form/WikiResourceCreate.php:123 +#: IDF/Form/WikiResourceDelete.php:59 IDF/Form/WikiResourceUpdate.php:124 +msgid "Cannot save the model from an invalid form." +msgstr "No se puede guardar el modelo desde un formulario no válido." + +#: IDF/Form/Admin/ProjectCreate.php:341 +msgid "" +"Click on the Project Management tab to set the description of your project." +msgstr "" +"Haga clic en la pestaña Gestión de proyectos para establecer la descripción " +"de su proyecto." + +#: IDF/Form/Admin/ProjectCreate.php:426 +msgid "This project is not available." +msgstr "Este proyecto no está disponible." + +#: IDF/Form/Admin/ProjectDelete.php:41 +msgid "Confirmation code" +msgstr "Código de confirmación" + +#: IDF/Form/Admin/ProjectDelete.php:46 +msgid "I have made a backup of all the important data of this project." +msgstr "" +"He realizado una copia de seguridad de todos los datos importantes de este " +"proyecto." + +#: IDF/Form/Admin/ProjectDelete.php:55 +msgid "" +"The confirmation code does not match. Please provide a valid confirmation " +"code to delete the project." +msgstr "" +"El código de confirmación no coincide. Por favor, introduzca el código de " +"confirmación válido para eliminar el proyecto." + +#: IDF/Form/Admin/ProjectDelete.php:63 +msgid "Sorry, you really need to backup your data before deletion." +msgstr "Lo sentimos, necesita respaldar sus datos antes de la eliminación." + +#: IDF/Form/Admin/UserCreate.php:37 IDF/Form/Admin/UserUpdate.php:38 +#: IDF/Form/RegisterConfirmation.php:50 IDF/Form/UserAccount.php:40 +msgid "First name" +msgstr "Nombre" + +#: IDF/Form/Admin/UserCreate.php:46 IDF/Form/Admin/UserUpdate.php:47 +#: IDF/Form/RegisterConfirmation.php:59 IDF/Form/UserAccount.php:49 +msgid "Last name" +msgstr "Apellidos" + +#: IDF/Form/Admin/UserCreate.php:56 +msgid "Login" +msgstr "Iniciar sesión" + +#: IDF/Form/Admin/UserCreate.php:60 +msgid "" +"The login must be between 3 and 15 characters long and contains only letters " +"and digits." +msgstr "" +"El nombre de usuario debe tener entre 3 y 15 caracteres de largo y contener " +"solamente letras y dígitos." + +#: IDF/Form/Admin/UserCreate.php:69 IDF/Form/Admin/UserUpdate.php:57 +msgid "Email" +msgstr "Email" + +#: IDF/Form/Admin/UserCreate.php:71 +msgid "" +"Double check the email address as the password is sent directly to the user." +msgstr "" +"Vuelva a comprobar tanto la dirección de correo electrónico como la " +"contraseña, ambas se envían directamente al usuario." + +#: IDF/Form/Admin/UserCreate.php:76 IDF/Form/Admin/UserUpdate.php:67 +#: IDF/Form/UserAccount.php:66 +msgid "Language" +msgstr "Idioma" + +#: IDF/Form/Admin/UserCreate.php:87 IDF/Form/UserAccount.php:161 +msgid "Add a public key" +msgstr "Agregar una clave pública" + +#: IDF/Form/Admin/UserCreate.php:92 +msgid "" +"Paste a SSH or monotone public key. Be careful to not provide your private " +"key here!" +msgstr "" +"Pege un SSH o de clave pública monótona. ¡Tenga cuidado de no proporcionar " +"aquí su clave privada!" + +#: IDF/Form/Admin/UserCreate.php:157 +msgid "Your details to access your forge." +msgstr "Sus datos para acceder a la forja." + +#: IDF/Form/Admin/UserCreate.php:189 IDF/Form/UserAccount.php:429 +#: IDF/Form/UserAccount.php:438 +#, php-format +msgid "The email \"%s\" is already used." +msgstr "La dirección de correo electrónico \"%s\" ya está en uso." + +#: IDF/Form/Admin/UserCreate.php:198 IDF/Form/Register.php:72 +#, php-format +msgid "The login \"%s\" can only contain letters and digits." +msgstr "El nombre de usuario \"%s\" solo puede contener letras y digitos." + +#: IDF/Form/Admin/UserCreate.php:203 IDF/Form/Register.php:77 +#, php-format +msgid "The login \"%s\" is already used, please find another one." +msgstr "El nombre de usuario \"%s\" ya está en uso, por favor encuentra otro." + +#: IDF/Form/Admin/UserUpdate.php:78 +msgid "Password" +msgstr "Contraseña" + +#: IDF/Form/Admin/UserUpdate.php:81 +msgid "Leave blank if you do not want to change the password." +msgstr "Dejar en blanco si no quiere cambiar la contraseña." + +#: IDF/Form/Admin/UserUpdate.php:81 +msgid "" +"The password must be hard for other people to guess, but easy for the user " +"to remember." +msgstr "" +"La contraseña debe ser difícil de averiguar para otras personas, pero fácil " +"de recordar para el usuario." + +#: IDF/Form/Admin/UserUpdate.php:89 +msgid "Confirm password" +msgstr "Confirmar contraseña" + +#: IDF/Form/Admin/UserUpdate.php:100 IDF/Form/IssueCreate.php:66 +#: IDF/Form/ProjectConf.php:48 IDF/Form/ReviewCreate.php:54 +#: IDF/Form/UpdateUpload.php:51 IDF/Form/Upload.php:49 +#: IDF/Form/UserAccount.php:101 IDF/Form/WikiPageCreate.php:70 +#: IDF/Form/WikiPageUpdate.php:60 IDF/Form/WikiResourceCreate.php:54 +#: IDF/Form/WikiResourceUpdate.php:46 IDF/Views/Wiki.php:102 +msgid "Description" +msgstr "Descripción" + +#: IDF/Form/Admin/UserUpdate.php:109 IDF/Form/UserAccount.php:110 +msgid "Twitter username" +msgstr "Nombre de usuario Twitter " + +#: IDF/Form/Admin/UserUpdate.php:119 IDF/Form/UserAccount.php:120 +msgid "Public email address" +msgstr "Dirección de correo electrónico Pública " + +#: IDF/Form/Admin/UserUpdate.php:129 IDF/Form/UserAccount.php:130 +msgid "Website URL" +msgstr "URL del sitio web" + +#: IDF/Form/Admin/UserUpdate.php:139 IDF/Form/UserAccount.php:140 +msgid "Upload custom avatar" +msgstr "Carga tu avatar personalizado" + +#: IDF/Form/Admin/UserUpdate.php:146 IDF/Form/UserAccount.php:147 +msgid "" +"An image file with a width and height not larger than 60 pixels (bigger " +"images are scaled down)." +msgstr "" +"Un archivo de imagen con una anchura y una altura no mayor de 60 píxeles " +"(imágenes más grandes se reducirán)." + +#: IDF/Form/Admin/UserUpdate.php:151 IDF/Form/UserAccount.php:152 +msgid "Remove custom avatar" +msgstr "Eliminar avatar personalizado" + +#: IDF/Form/Admin/UserUpdate.php:155 IDF/Form/UserAccount.php:156 +msgid "Tick this to delete the custom avatar." +msgstr "Marque esta opción para eliminar el avatar personalizado." + +#: IDF/Form/Admin/UserUpdate.php:161 IDF/Views/Admin.php:274 +msgid "Staff" +msgstr "Staff" + +#: IDF/Form/Admin/UserUpdate.php:164 +#, fuzzy +msgid "If you give staff rights to a user, you really need to trust him." +msgstr "" +"Si le da permisos de Staff a un usuario, debe confiar plenamente en él." + +#: IDF/Form/Admin/UserUpdate.php:172 IDF/Views/Admin.php:276 +msgid "Active" +msgstr "Activo" + +#: IDF/Form/Admin/UserUpdate.php:176 +msgid "" +"If the user is not getting the confirmation email or is abusing the system, " +"you can directly enable or disable their account here." +msgstr "" +"Si el usuario no recibe el email de confirmación o está abusando del " +"sistema, puede directamente activar o desactivar su cuenta desde aquí." + +#: IDF/Form/Admin/UserUpdate.php:274 +msgid "--- is not a valid first name." +msgstr "--- No es un nombre válido." + +#: IDF/Form/Admin/UserUpdate.php:290 +msgid "" +"A user with this email already exists, please provide another email address." +msgstr "" +"Ya existe un usuario con este correo electrónico , por favor, introduce otro " +"email." + +#: IDF/Form/Admin/UserUpdate.php:301 IDF/Form/UserAccount.php:398 +msgid "For security reason, you cannot upload a file with this extension." +msgstr "" +"Por razones de seguridad, no se puede cargar un archivo con esta extensión." + +#: IDF/Form/Admin/UserUpdate.php:316 IDF/Form/UserAccount.php:461 +msgid "The passwords do not match. Please give them again." +msgstr "Las contraseñas no coinciden. Por favor, vuelve a intentarlo." + +#: IDF/Form/Field/EmailList.php:45 +msgid "Please enter one or more valid email addresses." +msgstr "" +"Por favor, introduzca una o más direcciones de correo electrónico válidas." + +#: IDF/Form/IssueCreate.php:57 IDF/Form/IssueUpdate.php:46 +#: IDF/Form/ReviewCreate.php:45 IDF/Form/ReviewFileComment.php:73 +#: IDF/Form/UpdateUpload.php:42 IDF/Form/Upload.php:40 +#: IDF/gettexttemplates/idf/issues/base.html.php:3 IDF/Views/Download.php:65 +#: IDF/Views/Download.php:347 IDF/Views/Issue.php:62 IDF/Views/Issue.php:221 +#: IDF/Views/Issue.php:302 IDF/Views/Issue.php:391 IDF/Views/Issue.php:543 +#: IDF/Views/Issue.php:766 IDF/Views/Issue.php:825 IDF/Views/Review.php:58 +#: IDF/Views/User.php:83 IDF/Views/Wiki.php:62 IDF/Views/Wiki.php:145 +#: IDF/Views/Wiki.php:186 +msgid "Summary" +msgstr "Resumen" + +#: IDF/Form/IssueCreate.php:76 IDF/Form/IssueUpdate.php:66 +#: IDF/Form/ReviewCreate.php:83 +msgid "The \"upload_issue_path\" configuration variable was not set." +msgstr "" +"La variable de configuración \"upload_issue_path\" no se ha establecido." + +#: IDF/Form/IssueCreate.php:86 IDF/Form/IssueUpdate.php:76 +msgid "Attach a file" +msgstr "Adjuntar un archivo" + +#: IDF/Form/IssueCreate.php:99 IDF/Form/IssueUpdate.php:89 +#: IDF/Form/ReviewCreate.php:103 IDF/Form/ReviewFileComment.php:83 +#: IDF/Views/Issue.php:63 IDF/Views/Issue.php:222 IDF/Views/Issue.php:304 +#: IDF/Views/Issue.php:392 IDF/Views/Issue.php:544 IDF/Views/Issue.php:767 +#: IDF/Views/Issue.php:826 IDF/Views/Review.php:59 IDF/Views/User.php:84 +msgid "Status" +msgstr "Estado" + +#: IDF/Form/IssueCreate.php:108 IDF/Form/IssueUpdate.php:99 +msgid "Owner" +msgstr "Propietario" + +#: IDF/Form/IssueCreate.php:118 IDF/Form/IssueUpdate.php:112 +#: IDF/Form/IssueUpdate.php:129 +msgid "This issue" +msgstr "" + +#: IDF/Form/IssueCreate.php:210 +msgid "You cannot add a label with the \"Status\" prefix to an issue." +msgstr "" +"No se puede agregar una etiqueta con el prefijo \"Status\" a un ticket." + +#: IDF/Form/IssueCreate.php:211 IDF/Form/IssueCreate.php:218 +#: IDF/Form/UpdateUpload.php:110 IDF/Form/Upload.php:121 +#: IDF/Form/WikiPageCreate.php:151 IDF/Form/WikiPageUpdate.php:162 +msgid "You provided an invalid label." +msgstr "Proporcionaste una etiqueta no válida." + +#: IDF/Form/IssueCreate.php:217 IDF/Form/UpdateUpload.php:109 +#, fuzzy, php-format +msgid "You cannot provide more than one label from the %s class to an issue." +msgstr "No puede proporcionar más de una etiqueta de la clase %s en un ticket." + +#: IDF/Form/IssueCreate.php:228 IDF/Form/IssueUpdate.php:194 +msgid "You need to provide a description of the issue." +msgstr "Es necesario proporcionar una descripción del ticket." + +#: IDF/Form/IssueCreate.php:251 IDF/Form/ReviewCreate.php:159 +msgid "You provided an invalid status." +msgstr "Ha introducido un estado no válido." + +#: IDF/Form/IssueCreate.php:272 +msgid "You provided an invalid relation type." +msgstr "" + +#: IDF/Form/IssueCreate.php:294 +#, php-format +msgid "The value \"%s\" is not a valid issue id." +msgstr "" + +#: IDF/Form/IssueCreate.php:300 +#, php-format +msgid "The issue \"%s\" does not exist." +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:86 +msgid "is related to" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:87 +msgid "blocks" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:88 +msgid "is blocked by" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:89 +msgid "duplicates" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:90 +msgid "is duplicated by" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:97 +msgid "" +"Define an issue template to hint the reporter to provide certain information" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:106 +msgid "Open issue status values" +msgstr "Valores de estado para Tickets abiertos" + +#: IDF/Form/IssueTrackingConf.php:114 +msgid "Closed issue status values" +msgstr "Valores de estado para Tickets cerrados" + +#: IDF/Form/IssueTrackingConf.php:123 +msgid "Predefined issue labels" +msgstr "Etiquetas de tickets predefinidas" + +#: IDF/Form/IssueTrackingConf.php:125 +msgid "" +"The first \"Type:\" and \"Priority:\" entries found in this list are " +"automatically chosen as defaults for new issues." +msgstr "" +"La primera entrada \"Tipo:\" y \"Prioridad:\" de esta lista será " +"seleccionada automáticamente por defecto para los nuevos tickets." + +#: IDF/Form/IssueTrackingConf.php:133 +#, fuzzy +msgid "Each issue may have at most one label with each of these classes." +msgstr "" +"Cada ticket puede tener como máximo una etiqueta para cada una de sus clases" + +#: IDF/Form/IssueTrackingConf.php:140 +msgid "Issue relations" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:142 +msgid "" +"You can define bidirectional relations like \"is related to\" or \"blocks, " +"is blocked by\". For standard relations pre-configured translations exist, " +"new relations should however be defined in a language that is understood by " +"all project members." +msgstr "" + +#: IDF/Form/IssueUpdate.php:56 IDF/Form/ReviewFileComment.php:45 +#: IDF/Form/WikiPageUpdate.php:82 IDF/Form/WikiResourceUpdate.php:66 +msgid "Comment" +msgstr "Comentario" + +#: IDF/Form/IssueUpdate.php:316 +msgid "No changes were entered." +msgstr "No se han introducido cambios." + +#: IDF/Form/MembersConf.php:104 +#, php-format +msgid "The following login is invalid: %s." +msgid_plural "The following logins are invalid: %s." +msgstr[0] "El siguiente nombre de usuario no es válido: %s." +msgstr[1] "Los siguientes nombres de usuarios no son válidos: %s." + +#: IDF/Form/Password.php:34 +msgid "Your login or email" +msgstr "Su nombre de usuario o correo electrónico" + +#: IDF/Form/Password.php:35 +msgid "Provide either your login or your email to recover your password." +msgstr "" +"Proporcione su nombre de usuario o dirección de correo electrónico para " +"recuperar la contraseña." + +#: IDF/Form/Password.php:49 IDF/Form/Password.php:64 +msgid "" +"Sorry, we cannot find a user with this email address or login. Feel free to " +"try again." +msgstr "" +"Lo sentimos, no hemos encontrado ningún usuario con esta dirección de correo " +"electrónico o nombre de usuario. Vuelva a intentarlo." + +#: IDF/Form/Password.php:100 +msgid "Password Recovery - InDefero" +msgstr "Recuperar la contraseña - InDefero" + +#: IDF/Form/PasswordInputKey.php:36 IDF/Form/PasswordReset.php:39 +#: IDF/Form/UserChangeEmail.php:36 +msgid "Your verification key" +msgstr "Tu clave de verificación" + +#: IDF/Form/PasswordInputKey.php:50 IDF/Form/PasswordReset.php:89 +msgid "" +"We are sorry but this validation key is not valid. Maybe you should directly " +"copy/paste it from your validation email." +msgstr "" +"Lo sentimos, pero esta clave de validación no es válida. Intente copiar/" +"pegar desde el email de validación." + +#: IDF/Form/PasswordInputKey.php:61 IDF/Form/PasswordReset.php:100 +msgid "" +"Sorry, but this verification key has expired, please restart the password " +"recovery sequence. For security reasons, the verification key is only valid " +"24h." +msgstr "" +"Lo sentimos, pero esta clave de verificación ha expirado, por favor, " +"reinicie la secuencia de recuperación de la contraseña. Por razones de " +"seguridad, la clave de verificación sólo es válida durante 24 horas." + +#: IDF/Form/PasswordInputKey.php:76 IDF/Form/PasswordReset.php:108 +#: IDF/Form/RegisterConfirmation.php:137 IDF/Form/RegisterInputKey.php:72 +msgid "Cannot save an invalid form." +msgstr "No se puede guardar un formulario no válido." + +#: IDF/Form/PasswordReset.php:45 IDF/Form/RegisterConfirmation.php:69 +#: IDF/Form/UserAccount.php:77 +msgid "Your password" +msgstr "Su contraseña" + +#: IDF/Form/PasswordReset.php:48 IDF/Form/UserAccount.php:80 +msgid "" +"Your password must be hard for other people to find it, but easy for you to " +"remember." +msgstr "" +"Su contraseña debe ser difícil de averiguar por otras personas, pero fácil " +"de recordar." + +#: IDF/Form/PasswordReset.php:56 IDF/Form/RegisterConfirmation.php:80 +#: IDF/Form/UserAccount.php:89 +msgid "Confirm your password" +msgstr "Confirme su contraseña" + +#: IDF/Form/PasswordReset.php:74 IDF/Form/RegisterConfirmation.php:122 +msgid "The two passwords must be the same." +msgstr "Las dos contraseñas deben ser iguales." + +#: IDF/Form/PasswordReset.php:77 +msgid "" +"This account is not active. Please contact the forge administrator to " +"activate it." +msgstr "" +"Esta cuenta no está activa. Póngase en contacto con el administrador de la " +"forja para activarlo." + +#: IDF/Form/ProjectConf.php:43 +msgid "Short Description" +msgstr "" + +#: IDF/Form/ProjectConf.php:85 +msgid "The \"upload_path\" configuration variable was not set." +msgstr "" + +#: IDF/Form/ProjectConf.php:90 +msgid "Update the logo" +msgstr "" + +#: IDF/Form/ProjectConf.php:92 +msgid "The logo must be a picture with a size of 32 by 32." +msgstr "" + +#: IDF/Form/ProjectConf.php:103 +msgid "Remove the current logo" +msgstr "" + +#: IDF/Form/ProjectConf.php:139 +msgid "Could not determine the size of the uploaded picture." +msgstr "" + +#: IDF/Form/ProjectConf.php:143 +msgid "The picture must have a size of 32 by 32." +msgstr "" + +#: IDF/Form/ProjectConf.php:164 +msgid "The entered URL is invalid. Only http and https URLs are allowed." +msgstr "" + +#: IDF/Form/Register.php:41 +msgid "Your login" +msgstr "Tu nombre de usuario" + +#: IDF/Form/Register.php:45 +msgid "" +"The login must be between 3 and 15 characters long and contain only letters " +"and digits." +msgstr "" +"El nombre de usuario debe tener entre 3 y 15 caracteres y contener solamente " +"letras y dígitos." + +#: IDF/Form/Register.php:53 IDF/Form/UserAccount.php:59 +msgid "Your email" +msgstr "Correo electrónico" + +#: IDF/Form/Register.php:55 +msgid "We will never send you any unsolicited emails. We hate spam too!" +msgstr "" +"Nunca te enviaremos correo electrónico que no haya solicitado. ¡También " +"odiamos el spam!" + +#: IDF/Form/Register.php:60 +msgid "I agree to the terms and conditions." +msgstr "Estoy de acuerdo con los términos y condiciones." + +#: IDF/Form/Register.php:88 +msgid "" +"We know, this is boring, but you need to agree with the terms and conditions." +msgstr "" +"Lo sabemos, esto es aburrido, pero es necesario aceptar los términos y " +"condiciones." + +#: IDF/Form/Register.php:97 +#, fuzzy, php-format +msgid "" +"The email \"%1$s\" is already used. If you need to, you can recover your password." +msgstr "" +"La dirección de correo \"%s\" ya está en uso. Si lo necesita, haga clic en " +"el enlace de ayuda para recuperar su contraseña." + +#: IDF/Form/Register.php:148 +msgid "Confirm the creation of your account." +msgstr "Confirme la creación de su cuenta." + +#: IDF/Form/RegisterConfirmation.php:40 IDF/Form/RegisterInputKey.php:36 +msgid "Your confirmation key" +msgstr "Tu clave de confirmación" + +#: IDF/Form/RegisterConfirmation.php:72 +msgid "" +"Your password must be hard for other people to guess, but easy for you to " +"remember." +msgstr "" +"Su contraseña debe ser difícil de averiguar para otras personas, pero que le " +"sea fácil de recordar." + +#: IDF/Form/RegisterConfirmation.php:99 IDF/Form/RegisterInputKey.php:50 +msgid "" +"We are sorry but this confirmation key is not valid. Maybe you should " +"directly copy/paste it from your confirmation email." +msgstr "" +"Lo sentimos, pero esta clave de confirmación no es válida. Pruebe a copiar y " +"pegar directamente desde el email de confirmación." + +#: IDF/Form/RegisterConfirmation.php:110 +#, fuzzy, php-format +msgid "" +"This account has already been confirmed. Maybe should you try to recover your password." +msgstr "" +"Esta cuenta ya ha sido confirmada. Trate de recuperar su contraseña usando " +"el enlace de ayuda." + +#: IDF/Form/ReviewCreate.php:74 +#: IDF/gettexttemplates/idf/source/base.html.php:5 +#: IDF/gettexttemplates/idf/source/changelog.html.php:7 +msgid "Commit" +msgstr "Commit" + +#: IDF/Form/ReviewCreate.php:92 +msgid "Patch" +msgstr "Patch" + +#: IDF/Form/ReviewCreate.php:119 +msgid "We were not able to parse your patch. Please provide a valid patch." +msgstr "" +"No hemos podido analizar el parche. Por favor, proporcione un parche válido." + +#: IDF/Form/ReviewCreate.php:128 +msgid "You provided an invalid commit." +msgstr "Ha introducido un commit no válido." + +#: IDF/Form/ReviewCreate.php:202 +msgid "Initial patch to be reviewed." +msgstr "El Parche inicial debe ser revisado." + +#: IDF/Form/ReviewFileComment.php:56 +msgid "General comment" +msgstr "Comentario General" + +#: IDF/Form/ReviewFileComment.php:113 +msgid "" +"You need to provide your general comment about the proposal, or comments on " +"at least one file." +msgstr "" + +#: IDF/Form/ReviewFileComment.php:124 +msgid "The status have been updated." +msgstr "" + +#: IDF/Form/ReviewFileComment.php:130 +msgid "This field is required." +msgstr "" + +#: IDF/Form/SourceConf.php:54 IDF/Form/UploadConf.php:70 +msgid "Webhook URL" +msgstr "URL de Webhook" + +#: IDF/Form/TabsConf.php:38 IDF/gettexttemplates/idf/admin/base.html.php:4 +#: IDF/gettexttemplates/idf/base-full.html.php:8 +#: IDF/gettexttemplates/idf/base-full.html~.php:7 +#: IDF/gettexttemplates/idf/base.html.php:8 +#: IDF/gettexttemplates/idf/base.html~.php:7 +#: IDF/gettexttemplates/idf/downloads/base.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:14 +#: IDF/Views/Project.php:97 +msgid "Downloads" +msgstr "Descargas" + +#: IDF/Form/TabsConf.php:39 IDF/gettexttemplates/idf/base-full.html.php:12 +#: IDF/gettexttemplates/idf/base-full.html~.php:11 +#: IDF/gettexttemplates/idf/base.html.php:12 +#: IDF/gettexttemplates/idf/base.html~.php:11 +msgid "Code Review" +msgstr "Revisión del Código" + +#: IDF/Form/TabsConf.php:40 IDF/gettexttemplates/idf/admin/base.html.php:5 +#: IDF/gettexttemplates/idf/base-full.html.php:9 +#: IDF/gettexttemplates/idf/base-full.html~.php:8 +#: IDF/gettexttemplates/idf/base.html.php:9 +#: IDF/gettexttemplates/idf/base.html~.php:8 +msgid "Documentation" +msgstr "Documentación" + +#: IDF/Form/TabsConf.php:41 IDF/gettexttemplates/idf/admin/base.html.php:7 +#: IDF/gettexttemplates/idf/base-full.html.php:11 +#: IDF/gettexttemplates/idf/base-full.html~.php:10 +#: IDF/gettexttemplates/idf/base.html.php:11 +#: IDF/gettexttemplates/idf/base.html~.php:10 +msgid "Source" +msgstr "Fuentes" + +#: IDF/Form/TabsConf.php:42 IDF/gettexttemplates/idf/base-full.html.php:10 +#: IDF/gettexttemplates/idf/base-full.html~.php:9 +#: IDF/gettexttemplates/idf/base.html.php:10 +#: IDF/gettexttemplates/idf/base.html~.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:17 +msgid "Issues" +msgstr "Tickets" + +#: IDF/Form/TabsConf.php:50 +msgid "Open to all" +msgstr "Abierto a Todos" + +#: IDF/Form/TabsConf.php:51 +msgid "Signed in users" +msgstr "Usuarios Registrados" + +#: IDF/Form/TabsConf.php:54 +msgid "Closed" +msgstr "Cerrado" + +#: IDF/Form/TabsConf.php:84 +#, fuzzy +msgid "Others" +msgstr "Otros" + +#: IDF/Form/TabsConf.php:107 +msgid "Extra authorized users" +msgstr "Usuarios autorizados adicionales" + +#: IDF/Form/Upload.php:59 IDF/Form/WikiResourceCreate.php:65 +#: IDF/Form/WikiResourceUpdate.php:56 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:7 +#: IDF/Views/Download.php:64 IDF/Views/Download.php:346 +msgid "File" +msgstr "Archivo" + +#: IDF/Form/Upload.php:87 IDF/Form/WikiResourceCreate.php:96 +#: IDF/Form/WikiResourceUpdate.php:83 +msgid "For security reasons, you cannot upload a file with this extension." +msgstr "" +"Por razones de seguridad, no se puede cargar un archivo con esta extensión." + +#: IDF/Form/Upload.php:120 +#, fuzzy, php-format +msgid "You cannot provide more than one label from the %s class to a download." +msgstr "" +"No puede proporcionar más de una etiqueta para la clase %s en una página." + +#: IDF/Form/UploadArchive.php:41 +#, fuzzy +msgid "Archive file" +msgstr "Archivo" + +#: IDF/Form/UploadArchive.php:67 +#, fuzzy, php-format +msgid "" +"For security reasons, you cannot upload a file (%s) with this extension." +msgstr "" +"Por razones de seguridad, no se puede cargar un archivo con esta extensión." + +#: IDF/Form/UploadArchive.php:98 +#, fuzzy, php-format +msgid "" +"You cannot provide more than label from the %1$s class to a download (%2$s)." +msgstr "No puede proporcionar más de una etiqueta de la clase %s en un ticket." + +#: IDF/Form/UploadArchive.php:109 +#, php-format +msgid "" +"A file with the name \"%s\" has already been uploaded and is not marked to " +"be replaced." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:41 +#, fuzzy +msgid "The archive does not exist." +msgstr "La ruta del proyecto %s no existe." + +#: IDF/Form/UploadArchiveHelper.php:48 +#, fuzzy, php-format +msgid "The archive could not be read (code %d)." +msgstr "El directorio clave %s no puede ser creado." + +#: IDF/Form/UploadArchiveHelper.php:53 +msgid "The archive does not contain a manifest.xml." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:61 +#, fuzzy, php-format +msgid "The archive's manifest is invalid: %s" +msgstr "El siguiente nombre de usuario no es válido: %s." + +#: IDF/Form/UploadArchiveHelper.php:77 +#, php-format +msgid "The entry %d in the manifest is missing a file name." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:82 +#, php-format +msgid "The entry %d in the manifest is missing a summary." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:86 +msgid "The manifest must not reference itself." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:91 +#, php-format +msgid "The entry %s in the manifest does not exist in the archive." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:96 +#, php-format +msgid "The entry %s in the manifest is referenced more than once." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:108 +#, php-format +msgid "The entry %s in the manifest has more than the six allowed labels set." +msgstr "" + +#: IDF/Form/UploadConf.php:53 +msgid "Predefined download labels" +msgstr "Etiquetas predefinidas para descarga" + +#: IDF/Form/UploadConf.php:62 +msgid "Each download may have at most one label with each of these classes" +msgstr "" +"Cada descarga puede tener como máximo una etiqueta para cada una de estas " +"clases." + +#: IDF/Form/UserAccount.php:61 +msgid "" +"If you change your email address, an email will be sent to the new address " +"to confirm it." +msgstr "" +"Si cambia su dirección de correo electrónico, un email será enviado a la " +"dirección nueva para confirmarla." + +#: IDF/Form/UserAccount.php:80 +msgid "Leave blank if you do not want to change your password." +msgstr "Dejar en blanco si no desea cambiar su contraseña." + +#: IDF/Form/UserAccount.php:166 +msgid "" +"Paste an SSH or monotone public key. Be careful to not provide your private " +"key here!" +msgstr "" +"Pega una clave pública SSH o monotone. ¡Tenga cuidado de no proporcionar " +"aquí su clave privada!" + +#: IDF/Form/UserAccount.php:171 +#, fuzzy +msgid "Add a secondary email address" +msgstr "Añadir una dirección de correo secundaria" + +#: IDF/Form/UserAccount.php:173 +#, fuzzy +msgid "You will get an email to confirm that you own the address you specify." +msgstr "" +"Recibirá un correo electrónico para confirmar que eres el dueño de la " +"dirección que ha especificado." + +#: IDF/Form/UserAccount.php:200 +msgid "Confirm your new email address." +msgstr "Confirme su nueva dirección de correo electrónico." + +#: IDF/Form/UserAccount.php:203 +#, php-format +msgid "" +"A validation email has been sent to \"%s\" to validate the email address " +"change." +msgstr "" +"Un email de validación ha sido enviado a \"%s\" para validar el cambio de " +"dirección de correo electrónico." + +#: IDF/Form/UserAccount.php:341 +msgid "" +"Please check the key as it does not appear to be a valid SSH public key." +msgstr "" +"Por favor, compruebe la clave, ya que no parece ser válida la clave pública " +"SSH." + +#: IDF/Form/UserAccount.php:363 +msgid "" +"Please check the key as it does not appear to be a valid monotone public key." +msgstr "" +"Por favor, compruebe la clave, ya que parece no ser una clave pública " +"monotone válida ." + +#: IDF/Form/UserAccount.php:371 +msgid "Public key looks like neither an SSH nor monotone public key." +msgstr "" +"La clave pública no coincide con una clave pública SSH, ni con a una clave " +"monotone." + +#: IDF/Form/UserAccount.php:383 +msgid "You already have uploaded this key." +msgstr "Ya has subido esta clave." + +#: IDF/Form/UserChangeEmail.php:63 +msgid "" +"The validation key is not valid. Please copy/paste it from your confirmation " +"email." +msgstr "" +"La clave de validación no es válido. Por favor, copia/pega desde su email de " +"confirmación." + +#: IDF/Form/WikiConf.php:49 +msgid "Predefined documentation page labels" +msgstr "Etiquetas predefinidas para página de documentación" + +#: IDF/Form/WikiConf.php:58 +msgid "" +"Each documentation page may have at most one label with each of these classes" +msgstr "" +"Cada página de documentación podrá tener más de una etiqueta para cada una " +"de estas clases" + +#: IDF/Form/WikiPageCreate.php:38 +msgid "" +"# Introduction\n" +"\n" +"Add your content here.\n" +"\n" +"\n" +"# Details\n" +"\n" +"Add your content here. Format your content with:\n" +"\n" +"* Text in **bold** or *italic*.\n" +"* Headings, paragraphs, and lists.\n" +"* Links to other [[WikiPage]].\n" +msgstr "" +"# Introducción\n" +"\n" +"Añade tu contenido aquí.\n" +"\n" +"\n" +"# Detalles\n" +"\n" +"Añade tu contenido aquí. Formatea el contenido con:\n" +"\n" +"* Texto en **negrita** o *cursiva*.\n" +"* Títulos, párrafos y listas.\n" +"* Enlaces a otro [[WikiPage]].\n" + +#: IDF/Form/WikiPageCreate.php:57 +msgid "PageName" +msgstr "NombreDeLaPágina" + +#: IDF/Form/WikiPageCreate.php:60 IDF/Form/WikiPageUpdate.php:50 +msgid "Page title" +msgstr "Título de la página" + +#: IDF/Form/WikiPageCreate.php:66 IDF/Form/WikiPageUpdate.php:56 +msgid "" +"The page name must contains only letters, digits and the dash (-) character." +msgstr "" +"El nombre de la página debe contener sólo letras, dígitos y el carácter " +"guión (-)." + +#: IDF/Form/WikiPageCreate.php:71 IDF/Form/WikiPageUpdate.php:61 +msgid "This one line description is displayed in the list of pages." +msgstr "Breve descripción que se mostrará en la lista de páginas." + +#: IDF/Form/WikiPageCreate.php:108 IDF/Form/WikiPageUpdate.php:119 +#: IDF/Form/WikiResourceCreate.php:78 +msgid "The title contains invalid characters." +msgstr "El título contiene caracteres no válidos." + +#: IDF/Form/WikiPageCreate.php:114 IDF/Form/WikiPageUpdate.php:125 +msgid "A page with this title already exists." +msgstr "Una página con este título ya existe." + +#: IDF/Form/WikiPageCreate.php:150 IDF/Form/WikiPageUpdate.php:161 +#, fuzzy, php-format +msgid "You cannot provide more than one label from the %s class to a page." +msgstr "" +"No puede proporcionar más de una etiqueta para la clase %s en una página." + +#: IDF/Form/WikiPageCreate.php:200 +msgid "Initial page creation" +msgstr "Creación de la página inicial" + +#: IDF/Form/WikiPageDelete.php:39 +msgid "Yes, I understand that the page and all its revisions will be deleted." +msgstr "Sí, entiendo que la página y todas sus revisiones serán eliminados." + +#: IDF/Form/WikiPageDelete.php:50 IDF/Form/WikiResourceDelete.php:50 +msgid "You need to confirm the deletion." +msgstr "Necesitas confirmar la eliminación." + +#: IDF/Form/WikiPageUpdate.php:83 IDF/Form/WikiResourceUpdate.php:67 +msgid "One line to describe the changes you made." +msgstr "Breve descripción para los cambios realizados." + +#: IDF/Form/WikiResourceCreate.php:40 +msgid "ResourceName" +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:44 +msgid "Resource title" +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:50 +#, fuzzy +msgid "" +"The resource name must contains only letters, digits and the dash (-) " +"character." +msgstr "" +"El nombre de la página debe contener sólo letras, dígitos y el carácter " +"guión (-)." + +#: IDF/Form/WikiResourceCreate.php:55 IDF/Form/WikiResourceUpdate.php:47 +#, fuzzy +msgid "This one line description is displayed in the list of resources." +msgstr "Breve descripción que se mostrará en la lista de páginas." + +#: IDF/Form/WikiResourceCreate.php:84 +#, fuzzy +msgid "A resource with this title already exists." +msgstr "Una página con este título ya existe." + +#: IDF/Form/WikiResourceCreate.php:142 +#, fuzzy +msgid "Initial resource creation" +msgstr "Creación de la página inicial" + +#: IDF/Form/WikiResourceDelete.php:39 +#, fuzzy +msgid "" +"Yes, I understand that the resource and all its revisions will be deleted." +msgstr "Sí, entiendo que la página y todas sus revisiones serán eliminados." + +#: IDF/Form/WikiResourceUpdate.php:89 +#, php-format +msgid "" +"The mime type of the uploaded file \"%1$s\" does not match the mime type of " +"this resource \"%2$s\"" +msgstr "" + +#: IDF/Form/WikiResourceUpdate.php:97 +msgid "The current version of the resource and the uploaded file are equal." +msgstr "" + +#: IDF/Gconf.php:60 IDF/Search/Occ.php:56 +msgid "model class" +msgstr "clase del modelo" + +#: IDF/Gconf.php:66 IDF/Search/Occ.php:62 +msgid "model id" +msgstr "id del modelo" + +#: IDF/gettexttemplates/idf/admin/base.html.php:3 +msgid "Project Summary" +msgstr "Resumen del proyecto" + +#: IDF/gettexttemplates/idf/admin/base.html.php:6 +msgid "Issue Tracking" +msgstr "Seguimiento de Ticket" + +#: IDF/gettexttemplates/idf/admin/base.html.php:8 +msgid "Project Members" +msgstr "Miembros de proyecto" + +#: IDF/gettexttemplates/idf/admin/base.html.php:9 +msgid "Tabs Access and Notifications" +msgstr "Pestañas de Accesos y Notificaciones" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:3 +#: IDF/gettexttemplates/idf/admin/issue-tracking.html.php:3 +#: IDF/gettexttemplates/idf/admin/wiki.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/labels.html.php:3 +msgid "" +"\n" +"

Instructions:

\n" +"

List one status value per line in desired sort-order.

\n" +"

Optionally, use an equals-sign to document the meaning of each status " +"value.

\n" +msgstr "" +"\n" +"

Instrucciones:

\n" +"

Lista un valor por línea en el orden deseado.

\n" +"

Si lo desea, puede utilizar un signo de igual para documentar el valor de " +"cada estado.

\n" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:8 +#, fuzzy +msgid "" +"

The webhook URL setting specifies an URL to which a HTTP PUT\n" +"request is sent after a new download has been added or to which a HTTP " +"POST\n" +"request is sent after an existing download has been updated.\n" +"If this field is empty, notifications are disabled.

\n" +"\n" +"

Only properly-escaped HTTP URLs are supported, for " +"example:

\n" +"\n" +"
    \n" +"
  • http://domain.com/upload
  • \n" +"
  • http://domain.com/upload?my%20param
  • \n" +"
\n" +"\n" +"

In addition, the URL may contain the following \"%\" notation, which\n" +"will be replaced with specific project values for each download:

\n" +"\n" +"
    \n" +"
  • %p - project name
  • \n" +"
  • %d - download id
  • \n" +"
\n" +"\n" +"

For example, updating download 123 of project 'my-project' with\n" +"web hook URL http://mydomain.com/%p/%d would send a POST " +"request to\n" +"http://mydomain.com/my-project/123.

" +msgstr "" +"

La configuración URL WebHook especifica una URL con una solicitud HTTP " +"POST\n" +"que se envía después de cada commit del repositorio. Si este campo está " +"vacío,\n" +"las notificaciones están desactivadas.

\n" +"\n" +"

Únicamente las URLs HTTP, \n" +"se aceptan 'escapándolas' apropiadamente, por ejemplo:

\n" +"\n" +"
    \n" +"
  • http://dominio.com/commit
  • \n" +"
  • http://dominio.com/commit?mi%20parametro
  • \n" +"
\n" +"\n" +"

Además, la URL puede contener la siguiente notación: \"%\", que\n" +"será reemplazada por los valores específicos del proyecto para cada commit:\n" +"\n" +"

    \n" +"
  • %p - nombre del proyecto
  • \n" +"
  • %r - número de revisión
  • \n" +"
\n" +"\n" +"

Por ejemplo, el commit de la revisión 123 del proyecto 'mi-proyecto' con " +"URL de post-commit http://midominio.com/%p/%r enviaría la solicitud\n" +"http://midominio.com/mi-proyecto/123.

" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:31 +#: IDF/gettexttemplates/idf/admin/source.html.php:30 +#, fuzzy +msgid "Web-Hook authentication key:" +msgstr "Clave de autenticación Post-commit:" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:32 +#: IDF/gettexttemplates/idf/admin/issue-tracking.html.php:8 +#: IDF/gettexttemplates/idf/admin/members.html.php:13 +#: IDF/gettexttemplates/idf/admin/source.html.php:31 +#: IDF/gettexttemplates/idf/admin/summary.html.php:11 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:12 +#: IDF/gettexttemplates/idf/admin/wiki.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/forge/index.html.php:13 +#: IDF/gettexttemplates/idf/gadmin/projects/labels.html.php:8 +msgid "Save Changes" +msgstr "Guardar cambios" + +#: IDF/gettexttemplates/idf/admin/members.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:3 +msgid "" +"\n" +"

Instructions:

\n" +"

Specify each person by its login. Each person must have already " +"registered with the given login.

\n" +"

Separate the logins with commas and/or new lines.

\n" +msgstr "" +"\n" +"

Instrucciones:

\n" +"

Especifique cada persona por su nombre de usuaro. Cada persona debe " +"haberse registrado con el nombre de usuario dado.

\n" +"

Separe los nombres de usuarios con comas y/o nuevas líneas.

\n" + +#: IDF/gettexttemplates/idf/admin/members.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:8 +msgid "" +"\n" +"

Notes:

\n" +"

A project owner may make any change to this project, including removing " +"other project owners. You need to be carefull when you give owner rights.\n" +"

A project member will not have access to the administration area but will " +"have more options available in the use of the project.

\n" +msgstr "" +"\n" +"

Notas:

\n" +"

El propietario de un proyecto puede hacer cualquier cambio a este " +"proyecto, incluyendo la eliminación de otros propietarios del proyecto. " +"¡Tienes que tener cuidado cuando das permisos de propietario!.

\n" +"

Un miembro del proyecto no tendrá acceso al área de administración, pero " +"tendrá más opciones disponibles para usar en el proyecto.

\n" + +#: IDF/gettexttemplates/idf/admin/source.html.php:3 +msgid "You can find here the current repository configuration of your project." +msgstr "" +"Puede encontrar aquí la configuración actual del repositorio de su proyecto." + +#: IDF/gettexttemplates/idf/admin/source.html.php:4 +#, fuzzy +msgid "" +"

The webhook URL setting specifies an URL to which a HTTP \n" +"%%hook_request_method%% request is sent after each " +"repository\n" +"commit. If this field is empty, notifications are disabled.

\n" +"\n" +"

Only properly-escaped HTTP URLs are supported, for " +"example:

\n" +"\n" +"
    \n" +"
  • http://domain.com/commit
  • \n" +"
  • http://domain.com/commit?my%20param
  • \n" +"
\n" +"\n" +"

In addition, the URL may contain the following \"%\" notation, which\n" +"will be replaced with specific project values for each commit:

\n" +"\n" +"
    \n" +"
  • %p - project name
  • \n" +"
  • %r - revision number
  • \n" +"
\n" +"\n" +"

For example, committing revision 123 to project 'my-project' with\n" +"post-commit URL http://mydomain.com/%p/%r would send a request " +"to\n" +"http://mydomain.com/my-project/123.

" +msgstr "" +"

La configuración URL WebHook especifica una URL con una solicitud HTTP " +"POST\n" +"que se envía después de cada commit del repositorio. Si este campo está " +"vacío,\n" +"las notificaciones están desactivadas.

\n" +"\n" +"

Únicamente las URLs HTTP, \n" +"se aceptan 'escapándolas' apropiadamente, por ejemplo:

\n" +"\n" +"
    \n" +"
  • http://dominio.com/commit
  • \n" +"
  • http://dominio.com/commit?mi%20parametro
  • \n" +"
\n" +"\n" +"

Además, la URL puede contener la siguiente notación: \"%\", que\n" +"será reemplazada por los valores específicos del proyecto para cada commit:\n" +"\n" +"

    \n" +"
  • %p - nombre del proyecto
  • \n" +"
  • %r - número de revisión
  • \n" +"
\n" +"\n" +"

Por ejemplo, el commit de la revisión 123 del proyecto 'mi-proyecto' con " +"URL de post-commit http://midominio.com/%p/%r enviaría la solicitud\n" +"http://midominio.com/mi-proyecto/123.

" + +#: IDF/gettexttemplates/idf/admin/source.html.php:26 +msgid "" +"The form contains some errors. Please correct them to update the source " +"configuration." +msgstr "" +"El formulario contiene algunos errores. Por favor, corríjalos para " +"actualizar la configuración de las fuentes." + +#: IDF/gettexttemplates/idf/admin/source.html.php:27 +msgid "Repository type:" +msgstr "Tipo de Repositorio:" + +#: IDF/gettexttemplates/idf/admin/source.html.php:28 +msgid "Repository access:" +msgstr "Acceso Repositorio:" + +#: IDF/gettexttemplates/idf/admin/source.html.php:29 +msgid "Repository size:" +msgstr "Tamaño Respositorio:" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

The description of the project can be improved using the Markdown syntax.

\n" +msgstr "" +"\n" +"

Instrucciones:

\n" +"

La descripción del proyecto puede ser mejorada mediante la Sintaxis de Marcado.

\n" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:7 +msgid "" +"The form contains some errors. Please correct them to update the summary." +msgstr "" +"El formulario contiene algunos errores. Por favor, corríjalos para " +"actualizar el resumen." + +#: IDF/gettexttemplates/idf/admin/summary.html.php:8 +msgid "Current logo" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:9 +#: IDF/gettexttemplates/idf/base-full.html.php:4 +#: IDF/gettexttemplates/idf/base-full.html~.php:4 +#: IDF/gettexttemplates/idf/base.html.php:4 +#: IDF/gettexttemplates/idf/base.html~.php:4 +#: IDF/gettexttemplates/idf/main-menu.html.php:8 +#: IDF/gettexttemplates/idf/project-list.html.php:4 +msgid "Project logo" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:10 +msgid "Your project does not have a logo configured yet." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:3 +#, fuzzy +msgid "" +"This section allows you to configure project tabs access rights and " +"notifications." +msgstr "" +"Puede configurar aquí los permisos de acceso a las pestañas del proyecto y " +"los mensajes de notificación." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:4 +msgid "" +"Tab access controls whether a single user can navigate into a particular " +"section of your project via the main menu or automatically generated object " +"links." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:5 +#, fuzzy +msgid "" +"If you mark a project as private, only the project members and " +"administrators, together with the extra authorized users you provide will " +"have access to the project as a whole. You will still be able to define " +"further access rights for the different tabs but the \"Open to all\" and " +"\"Signed in users\" will default to authorized users only." +msgstr "" +"Si marca un proyecto como privado, sólo los miembros del proyecto y los " +"administradores, junto con los usuarios adicionales autorizados tendrán " +"acceso al proyecto. Podrá definir nuevos permisos de acceso para las " +"diferentes pestañas, pero \"Abierto a todos\" y \"Usuarios Registrados\" se " +"establecerán por defecto para autorizar usuarios." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:6 +#, fuzzy +msgid "" +"For the extra authorized user list, specify each person by its login. Each " +"person must have already registered with the given login. Separate the " +"logins with commas and/or new lines." +msgstr "" +"Especifique cada persona con su usuario. Cada persona debe haberse " +"registrado con el usuario proporcionado. Separe los usuarios con comas y/o " +"nueva línea." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:7 +#, fuzzy +msgid "" +"Only project members and admins have write access to the source. If you " +"restrict the access to the source, anonymous access is not provided and the " +"users must authenticate themselves with their password or SSH key." +msgstr "" +"\n" +"Solo los miembros del proyecto y los administradores tienen acceso de " +"escritura sobre las fuentes.
\n" +"Si restringe el acceso a las fuentes, el acceso anónimo,
\n" +"no estará habilitado y los usuarios deberán autentificarse con su
\n" +"contraseña o clave SSH." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:8 +#, php-format +msgid "" +"Here you can configure who should be notified about changes in a particular " +"section. You can also configure additional addresses, like the one of a " +"mailing list, that should be notified. (Keep in mind that you might have to " +"register the sender address %%from_email%% to let the " +"mailing list actually accept notification emails.) Multiple email addresses " +"must be separated through commas (',')." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:9 +msgid "" +"The form contains some errors. Please correct them to update the access " +"rights." +msgstr "" +"El formulario contiene algunos errores. Por favor, corríjalos para " +"actualizar los derechos de acceso." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:10 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:13 +msgid "Access Rights" +msgstr "Derechos de Acceso" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:11 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:14 +#, fuzzy +msgid "Notifications" +msgstr "Notificación por email" + +#: IDF/gettexttemplates/idf/base-full.html.php:3 +#: IDF/gettexttemplates/idf/base-full.html~.php:3 +#: IDF/gettexttemplates/idf/base.html.php:3 +#: IDF/gettexttemplates/idf/base.html~.php:3 +#, php-format +msgid "" +"Sign in or create your account to create issues or " +"add comments" +msgstr "" +"Accede o create una cuenta para crear tickets y " +"añadir comentarios" + +#: IDF/gettexttemplates/idf/base-full.html.php:6 +#: IDF/gettexttemplates/idf/base.html.php:6 +#: IDF/gettexttemplates/idf/project-list.html.php:6 +msgid "External link to project" +msgstr "" + +#: IDF/gettexttemplates/idf/base-full.html.php:7 +#: IDF/gettexttemplates/idf/base-full.html~.php:6 +#: IDF/gettexttemplates/idf/base.html.php:7 +#: IDF/gettexttemplates/idf/base.html~.php:6 +msgid "Project Home" +msgstr "Inicio del Proyecto" + +#: IDF/gettexttemplates/idf/base-full.html.php:13 +#: IDF/gettexttemplates/idf/base-full.html~.php:12 +#: IDF/gettexttemplates/idf/base.html.php:13 +#: IDF/gettexttemplates/idf/base.html~.php:12 +msgid "Project Management" +msgstr "Gestión de Proyecto" + +#: IDF/gettexttemplates/idf/downloads/base.html.php:4 +#: IDF/gettexttemplates/idf/downloads/index.html.php:4 +#: IDF/Views/Download.php:235 +msgid "New Download" +msgstr "Nueva descarga" + +#: IDF/gettexttemplates/idf/downloads/base.html.php:5 +#, fuzzy +msgid "Upload Archive" +msgstr "Archivo" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:3 +msgid "" +"Each file must have a distinct name and file contents\n" +"cannot be changed, so be sure to include release numbers in each file\n" +"name." +msgstr "" +"Cada archivo debe tener un nombre distinto y el contenido del archivo\n" +"no se puede cambiar, así que asegúrese de incluir los números de versión en " +"el nombre de cada\n" +"archivo." + +#: IDF/gettexttemplates/idf/downloads/create.html.php:6 +#, php-format +msgid "" +"You can use the Markdown syntax for the description." +msgstr "" +"Puede usar sintaxis de Marcado para la descripción." + +#: IDF/gettexttemplates/idf/downloads/create.html.php:7 +msgid "The form contains some errors. Please correct them to submit the file." +msgstr "" +"El formulario contiene algunos errores. Por favor, corríjalo para enviar el " +"archivo." + +#: IDF/gettexttemplates/idf/downloads/create.html.php:8 +msgid "Submit File" +msgstr "Enviar Archivo" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:9 +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:8 +#: IDF/gettexttemplates/idf/downloads/delete.html.php:7 +#: IDF/gettexttemplates/idf/downloads/view.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:21 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:14 +#: IDF/gettexttemplates/idf/issues/create.html.php:14 +#: IDF/gettexttemplates/idf/issues/view.html.php:27 +#: IDF/gettexttemplates/idf/register/confirmation.html.php:7 +#: IDF/gettexttemplates/idf/register/index.html.php:8 +#: IDF/gettexttemplates/idf/register/inputkey.html.php:5 +#: IDF/gettexttemplates/idf/review/create.html.php:12 +#: IDF/gettexttemplates/idf/review/view.html.php:41 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:5 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:13 +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:7 +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:9 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:5 +msgid "Cancel" +msgstr "Cancelar" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:10 +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:9 +#: IDF/gettexttemplates/idf/register/inputkey.html.php:6 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:6 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:6 +msgid "Instructions" +msgstr "Instrucciones" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:3 +msgid "" +"The archive must include a manifest.xml file with meta " +"information about the\n" +"files to process inside the archive. All processed files must be unique or " +"replace existing files explicitely." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:5 +#, fuzzy, php-format +msgid "" +"You can learn more about the archive format here." +msgstr "" +"Si aún no tienes una cuenta, puedes crear una aquí." + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:6 +#, fuzzy +msgid "" +"The form contains some errors. Please correct them to submit the archive." +msgstr "" +"El formulario contiene algunos errores. Por favor, corríjalo para enviar el " +"archivo." + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:7 +#, fuzzy +msgid "Submit Archive" +msgstr "Enviar Archivo" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:3 +msgid "" +"Attention! If you want to delete a specific version of your " +"software, maybe, someone is depending on this specific version to run his " +"systems. Are you sure, you will not affect anybody when removing this file?" +msgstr "" +"¡Atención! Si desea eliminar una versión específica del " +"software, tal vez, alguien está utilizando esta versión específica para " +"ejecutarlo en su sistema. ¿Estás seguro de que no afectará a nadie cuando se " +"elimine este archivo?" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:4 +#, php-format +msgid "" +"Instead of deleting the file, you could mark it as " +"deprecated." +msgstr "" +"En lugar de borrar el archivo, puede marcarlo como " +"obsoleto." + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:5 +#: IDF/gettexttemplates/idf/downloads/view.html.php:4 +#: IDF/gettexttemplates/idf/issues/attachment.html.php:4 +#: IDF/gettexttemplates/idf/issues/view.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:5 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:7 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:7 +#, php-format +msgid "by %%submitter%%" +msgstr "por %%submitter%%" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:6 +msgid "Delete File" +msgstr "Eliminar archivo" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:8 +#: IDF/gettexttemplates/idf/downloads/view.html.php:14 +msgid "Uploaded:" +msgstr "Subido por:" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:9 +#: IDF/gettexttemplates/idf/downloads/view.html.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:29 +#: IDF/gettexttemplates/idf/review/view.html.php:27 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:12 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:14 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:14 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:15 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:17 +msgid "Updated:" +msgstr "Actualización:" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:10 +#: IDF/gettexttemplates/idf/downloads/view.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:6 +#: IDF/gettexttemplates/idf/listProjects.html.php:17 +msgid "Downloads:" +msgstr "Descargas:" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:11 +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:7 +#: IDF/gettexttemplates/idf/downloads/view.html.php:17 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:6 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:6 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:11 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:16 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:10 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:21 +#: IDF/gettexttemplates/idf/issues/view.html.php:33 +#: IDF/gettexttemplates/idf/project-list.html.php:8 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:6 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:13 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:16 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:12 +#: IDF/IssueComment.php:157 IDF/Wiki/PageRevision.php:204 +msgid "Labels:" +msgstr "Etiquetas:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:3 +msgid "A new file is available for download:" +msgstr "Un nuevo archivo está disponible desde descargas:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:4 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:6 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:5 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:8 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:4 +msgid "Hello," +msgstr "Hola," + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:6 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:5 +msgid "Project:" +msgstr "Proyecto:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:6 +msgid "Submitted by:" +msgstr "Enviado por:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:8 +msgid "Download:" +msgstr "Descarga:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/view.html.php:31 +#: IDF/gettexttemplates/idf/user/public.html.php:4 +msgid "Description:" +msgstr "Descripción:" + +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:3 +msgid "A file download was updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/feedfragment.xml.php:3 +msgid "Details" +msgstr "Detalles" + +#: IDF/gettexttemplates/idf/downloads/index.html.php:3 +#, php-format +msgid "See the deprecated files." +msgstr "Ver archivos obsoletos." + +#: IDF/gettexttemplates/idf/downloads/index.html.php:5 +msgid "Number of files:" +msgstr "Número de archivos:" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:3 +msgid "" +"Attention! This file is marked as deprecated, download it " +"only if you are sure you need this specific version." +msgstr "" +"¡Atención! Este archivo está marcado como obsoleto, " +"descárgalo sólo si está seguro de que necesita esta versión específica." + +#: IDF/gettexttemplates/idf/downloads/view.html.php:5 +msgid "md5:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:6 +msgid "Changes" +msgstr "Cambios" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:7 +msgid "The form contains some errors. Please correct them to update the file." +msgstr "" +"El formulario contiene algunos errores. Por favor, corríjalos para " +"actualizar el archivo." + +#: IDF/gettexttemplates/idf/downloads/view.html.php:8 +msgid "Update File" +msgstr "Actualizar archivo" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:10 +#: IDF/gettexttemplates/idf/downloads/view.html.php:12 +msgid "Remove this file" +msgstr "Eliminar este archivo" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:11 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:18 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:7 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:12 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:12 +msgid "Trash" +msgstr "Papelera" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:13 +msgid "Delete this file" +msgstr "Eliminar este archivo" + +#: IDF/gettexttemplates/idf/faq-api.html.php:3 +#: IDF/gettexttemplates/idf/faq-archive-format.html.php:3 +#: IDF/gettexttemplates/idf/faq.html.php:65 +msgid "Here we are, just to help you." +msgstr "Aquí estamos, para ayudarte." + +#: IDF/gettexttemplates/idf/faq-api.html.php:4 +#: IDF/gettexttemplates/idf/faq-archive-format.html.php:4 +#: IDF/gettexttemplates/idf/faq.html.php:66 +#: IDF/gettexttemplates/idf/gadmin/base.html.php:4 +#: IDF/gettexttemplates/idf/index.html.php:4 IDF/Views/Admin.php:77 +#: IDF/Views.php:91 +msgid "Projects" +msgstr "Proyectos" + +#: IDF/gettexttemplates/idf/faq.html.php:3 +#, fuzzy +msgid "" +"

This is simple:

\n" +"
    \n" +"
  1. Write in the comments \"This is a duplicate of issue 123\" or - if you " +"are a member of the crew -\n" +"directly add the \"duplicates\" relation with the value \"123\" below the " +"comment field. Change \"123\"\n" +"with the corresponding issue number.
  2. \n" +"
  3. Change the status of the current issue to Duplicate.
  4. \n" +"
  5. Submit the changes.
  6. \n" +"
" +msgstr "" +"

Es simple:

\n" +"
    \n" +"
  1. Escribe en los comentarios \"Esto es una duplicado del ticket 123\", " +"cambia 123 por el número de ticket correspondiente.
  2. \n" +"
  3. Cambia el estado del ticket actual a Duplicado.
  4. \n" +"
  5. Envíe los cambios.
  6. \n" +"
" + +#: IDF/gettexttemplates/idf/faq.html.php:11 +msgid "" +"You need to create an account on Gravatar, this takes about 5 minutes and is free." +msgstr "" +"Necesitas crear una cuenta en Gravatar , tardarás 5 minutos y es gratuito." + +#: IDF/gettexttemplates/idf/faq.html.php:12 +msgid "" +"\n" +"

To embed any previously uploaded resource into your wiki page, you can " +"use the [[!ResourceName]] syntax.

\n" +"\n" +"

The rendering of the resource can then be further fine-tuned:\n" +"

    \n" +"
  • [[!ImageResource, align=right, width=200]] renders " +"\"ImageResource\" right-aligned and scale its width to 200
  • \n" +"
  • [[!TextResource, align=center, width=300, height=300]] " +"renders \"TextResource\" in a centered, 300 by 300 px iframe
  • \n" +"
  • [[!AnyResource, preview=no]] does not render a preview of " +"the resource, but only provides a download link (default for binary " +"resources)
  • \n" +"
  • [[!BinaryResource, title=Download]] renders the download " +"link of \"BinaryResource\" with an alternative title
  • \n" +"
\n" +"

\n" +"\n" +"Resources are versioned, just like wiki pages. If you update a resource, old " +"wiki pages still show the state of the resource\n" +"at the time when the wiki page was edited. If you specifically want to " +"update a resource on a page, you therefor need to update\n" +"the resource at first and then also the page where it is referenced, " +"otherwise the change won't be visible until the next regular edit. \n" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:28 +msgid "" +"

If you have to publish many files at once for a new release, it is a very " +"tedious task\n" +"to upload them one after another and enter meta information like a summary, " +"a description or additional\n" +"labels for each of them.

\n" +"

InDefero therefore supports a special archive format that is basically a " +"standard zip file which comes with\n" +"some meta information. These meta information are kept in a special manifest " +"file, which is distinctly kept from\n" +"the rest of the files in the archive that should be published.

\n" +"

Once this archive has been uploaded, InDefero reads in the meta " +"information, unpacks the other files from\n" +"the archive and creates new individual downloads for each of them.

" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:36 +#, fuzzy, php-format +msgid "
Learn more about the archive format." +msgstr "Obtener más información sobre la API." + +#: IDF/gettexttemplates/idf/faq.html.php:37 +msgid "" +"The API (Application Programming Interface) is used to interact with " +"InDefero with another program. For example, this can be used to create a " +"desktop program to submit new tickets easily." +msgstr "" +"La API (Interfazaz de Programación de la Aplicación ) se utiliza para " +"interactuar InDefero con otro programa. Por ejemplo, puede ser usado en la " +"creación de un programa de escritorio para enviar nuevos tickets con " +"facilidad." + +#: IDF/gettexttemplates/idf/faq.html.php:38 +#, php-format +msgid "Learn more about the API." +msgstr "Obtener más información sobre la API." + +#: IDF/gettexttemplates/idf/faq.html.php:39 +#: IDF/gettexttemplates/idf/faq.html.php:45 +msgid "What are the keyboard shortcuts?" +msgstr "¿Cuáles son los métodos abreviados de teclado?" + +#: IDF/gettexttemplates/idf/faq.html.php:40 +#: IDF/gettexttemplates/idf/faq.html.php:60 +msgid "How to mark an issue as duplicate?" +msgstr "¿Cómo marcar un ticket como duplicado?" + +#: IDF/gettexttemplates/idf/faq.html.php:41 +#: IDF/gettexttemplates/idf/faq.html.php:61 +msgid "How can I display my head next to my comments?" +msgstr "¿Cómo puedo mostrar mi avatar al lado de mis comentarios?" + +#: IDF/gettexttemplates/idf/faq.html.php:42 +#: IDF/gettexttemplates/idf/faq.html.php:62 +msgid "How can I embed images and other resources in my documentation pages?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:43 +#: IDF/gettexttemplates/idf/faq.html.php:63 +msgid "What is this \"Upload Archive\" functionality about?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:44 +#: IDF/gettexttemplates/idf/faq.html.php:64 +msgid "What is the API and how is it used?" +msgstr "¿Que es la API y cómo se usa?" + +#: IDF/gettexttemplates/idf/faq.html.php:46 +msgid "Shift+h: This help page." +msgstr "Shift+h: Página de ayuda." + +#: IDF/gettexttemplates/idf/faq.html.php:47 +msgid "If you are in a project, you have the following shortcuts:" +msgstr "Si estás en un proyecto, tienes los siguientes accesos directos:" + +#: IDF/gettexttemplates/idf/faq.html.php:48 +msgid "Shift+u: Project updates." +msgstr "Shift+u: Actualizaciones de proyecto." + +#: IDF/gettexttemplates/idf/faq.html.php:49 +msgid "Shift+d: Downloads." +msgstr "Shift+d: Descargas." + +#: IDF/gettexttemplates/idf/faq.html.php:50 +msgid "Shift+o: Documentation." +msgstr "Shift+o: Documentación." + +#: IDF/gettexttemplates/idf/faq.html.php:51 +msgid "Shift+a: Create a new issue." +msgstr "Shift+a: Crear un nuevo ticket." + +#: IDF/gettexttemplates/idf/faq.html.php:52 +msgid "Shift+i: List of open issues." +msgstr "Shift+i: Lista de tickets abiertos." + +#: IDF/gettexttemplates/idf/faq.html.php:53 +msgid "Shift+m: The issues you submitted." +msgstr "Shift+m: Tickets que has enviado." + +#: IDF/gettexttemplates/idf/faq.html.php:54 +msgid "Shift+w: The issues assigned to you." +msgstr "Shift+w: Tickets que te han asignado." + +#: IDF/gettexttemplates/idf/faq.html.php:55 +msgid "Shift+s: Source." +msgstr "Shift+s: Código." + +#: IDF/gettexttemplates/idf/faq.html.php:56 +msgid "You also have the standard access keys:" +msgstr "También tienes las teclas de acceso estándar:" + +#: IDF/gettexttemplates/idf/faq.html.php:57 +msgid "Alt+1: Home." +msgstr "Alt+1: Inicio." + +#: IDF/gettexttemplates/idf/faq.html.php:58 +msgid "Alt+2: Skip the menus." +msgstr "Alt+2: Saltar los menús." + +#: IDF/gettexttemplates/idf/faq.html.php:59 +msgid "Alt+4: Search (when available)." +msgstr "Alt+4: Búsqueda (cuando esté disponible)." + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:3 +msgid "Forge" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:5 +msgid "People" +msgstr "Personas" + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:6 +msgid "Usher" +msgstr "Usher" + +#: IDF/gettexttemplates/idf/gadmin/forge/base.html.php:3 +#, fuzzy +msgid "Frontpage" +msgstr "página" + +#: IDF/gettexttemplates/idf/gadmin/forge/index.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

You can set up a custom forge page that is used as entry page for the " +"forge instead of the plain project listing. This page is then also " +"accessible via the 'Home' link in main menu bar.

\n" +"

The content of the page can use the Markdown syntax with the Extra extension.

\n" +"

Additionally, the following macros are available:
\n" +"

    \n" +"
  • {projectlist, label=..., order=(name|activity), limit=...} - Renders a project list that can optionally be filtered by label, " +"ordered by 'name' or 'activity' and / or limited to a specific number of " +"projects.
  • \n" +"
\n" +"

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:3 +#: IDF/gettexttemplates/idf/main-menu.html.php:7 +msgid "Project List" +msgstr "Lista de Proyectos" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:4 +#: IDF/Views/Admin.php:110 +#, fuzzy +msgid "Project Labels" +msgstr "Lista de Proyectos" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:16 +#: IDF/gettexttemplates/idf/listProjects.html.php:6 IDF/Views/Admin.php:186 +msgid "Create Project" +msgstr "Crear proyecto" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:6 +msgid "Change Project Details" +msgstr "Cambiar Detalles del Proyecto" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:3 +msgid "" +"You can select the type of repository you want. In the case of subversion, " +"you can use optionally a remote repository instead of the local one." +msgstr "" +"Puede seleccionar el tipo de repositorio que desee. En el caso de " +"subversión, puede utilizar opcionalmente un repositorio remoto en lugar de " +"uno local." + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:4 +msgid "" +"Once you have defined the repository type, you cannot change it." +msgstr "" +"Una vez que haya definido el tipo de repositorio, no se puede " +"modificar." + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:5 +msgid "" +"\n" +"

Specify each person by its login. Each person must have already " +"registered with the given login.

\n" +"

Separate the logins with commas and/or new lines.

\n" +msgstr "" +"\n" +"

Especifique cada persona por su nombre de usuario. Cada persona debe " +"estar registrada con el nombre de usuario proporcionado.

\n" +"

Separe los nombres de usuario con comas y / o saltos de líneas.

\n" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:14 +msgid "" +"The form contains some errors. Please correct them to create the project." +msgstr "" +"El formulario contiene algunos errores. Por favor, corríjalos para crear el " +"proyecto." + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:15 +msgid "Provide at least one owner for the project or use a template." +msgstr "" +"Proporcione al menos un propietario para el proyecto o utilice una plantilla." + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:15 +msgid "Instructions:" +msgstr "Instrucciones:" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:3 +#, php-format +msgid "" +"Confirmation code to confirm the deletion of the project: \n" +"%%code%%." +msgstr "" +"Código de confirmación para autorizar la eliminación del proyecto: \n" +"%%code%%." + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:5 +msgid "" +"\n" +"Attention! Deleting a project is a one second operation\n" +"with the consequences that all the data related to the \n" +"project will be deleted.\n" +msgstr "" +"\n" +"¡Atención! Eliminar un proyecto es una operación delicada,\n" +"que tiene como resultado borrar todos los datos del " +"proyecto.\n" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:10 +msgid "" +"The form contains some errors. Please correct them to delete the project." +msgstr "" +"El formulario contiene algunos errores. Por favor, corríjalo para eliminar " +"el proyecto." + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:11 +msgid "Project Statistics" +msgstr "Estadísticas del proyecto" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:12 +msgid "Tab" +msgstr "Pestaña" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:13 +msgid "Number" +msgstr "Número" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:15 +msgid "Code reviews" +msgstr "Revisiones del código" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:16 +#: IDF/Views/Project.php:93 +msgid "Commits" +msgstr "Commits" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:18 +msgid "Documentation pages" +msgstr "Páginas documentación" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:19 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:20 +msgid "Delete Project" +msgstr "Eliminar Proyecto" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:22 +msgid "" +"For large projects, the suppression can take a while, please be patient." +msgstr "" +"Para los proyectos grandes, la supresión puede tomar un tiempo, por favor, " +"sea paciente." + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:3 +msgid "Space Usage Statistics" +msgstr "Estadísticas espacio utilizado" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:4 +msgid "Repositories:" +msgstr "Repositorios:" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:5 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:11 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:18 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:16 +msgid "Attachments:" +msgstr "Archivos adjuntos:" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:7 +msgid "Database:" +msgstr "Base de datos:" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:8 +msgid "Total Forge:" +msgstr "Total Forja:" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:13 +msgid "" +"The form contains some errors. Please correct them to update the project." +msgstr "" +"El formulario contiene algunos errores. Por favor, corríjalos para " +"actualizar el proyecto." + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:14 +msgid "Provide at least one owner for the project." +msgstr "Proporcione al menos un propietario para el proyecto." + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:15 +msgid "Update Project" +msgstr "Actualizar Proyecto" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:19 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:20 +msgid "Delete this project" +msgstr "Eliminar este proyecto" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:21 +msgid "You will be asked to confirm." +msgstr "Se le pedirá confirmación." + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:3 +#: IDF/Views/Admin.php:264 +msgid "User List" +msgstr "Lista de usuarios" + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:13 +msgid "Update User" +msgstr "Actualizar usuario" + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:4 +msgid "Create User" +msgstr "Crear usuario" + +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:3 +msgid "The form contains some errors. Please correct them to create the user." +msgstr "" +"El formulario contiene algunos errores. Por favor, corríjalos para crear el " +"usuario." + +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:6 +msgid "The user password will be sent by email to the user." +msgstr "La contraseña será enviada por correo electrónico al usuario." + +#: IDF/gettexttemplates/idf/gadmin/users/createuser-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"An account on the forge has been created for you by\n" +"the administrator %%admin%%.\n" +"\n" +"Please find here your details to access the forge:\n" +"\n" +" Address: %%url%%\n" +" Login: %%user.login%%\n" +" Password: %%password%%\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" +"Hola %%user%%,\n" +"\n" +"Se ha creado una cuenta en la forja para ti por el administrador %%admin%%.\n" +"\n" +"Aquí encontrará sus datos para acceder a la forja:\n" +"\n" +" Dirección: %%url%%\n" +" Nombre de usuario: %%user.login%%\n" +" Contraseña: %%password%%\n" +"\n" +"Atentamente,\n" +"El equipo de desarrollo.\n" + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:3 +#, php-format +msgid "See not validated users." +msgstr "Ver usuarios sin validar." + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:4 +msgid "

You have here an overview of the users registered in the forge.

" +msgstr "" +"

Tiene aquí una visión general de los usuarios registrados en la forja. " + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:5 +msgid "Number of users:" +msgstr "Número de usuarios:" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:3 +msgid "" +"If you are changing the email address of the user, you\n" +"need to ensure that you are providing a valid email\n" +"address" +msgstr "" +"Si va a cambiar la dirección de correo electrónico del usuario,\n" +"es necesario asegurarse que proporciona una dirección \n" +"de correo electrónico válida" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:6 +msgid "" +"If you give the user staff rights, the user will be\n" +"able to create new projects and update other non staff users.\n" +msgstr "" +"Si da permisos de acceso tipo Staff, el usuario será capaz \n" +"de crear nuevos proyectos y actualizar a otros usuarios que no sean del " +"Staff.\n" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:9 +msgid "The form contains some errors. Please correct them to update the user." +msgstr "" +"El formulario contiene algunos errores. Por favor, corríjalos para " +"actualizar el usuario." + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:10 +#: IDF/gettexttemplates/idf/register/confirmation.html.php:4 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:4 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:4 +msgid "Login:" +msgstr "Inicio de sesión:" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:11 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:5 +msgid "Public Profile" +msgstr "Perfil público" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:12 +msgid "Administrative" +msgstr "Administrativo" + +#: IDF/gettexttemplates/idf/gadmin/usher/base.html.php:3 +msgid "Configured servers" +msgstr "Servidores configurados" + +#: IDF/gettexttemplates/idf/gadmin/usher/base.html.php:4 +#: IDF/Views/Admin.php:421 +msgid "Usher control" +msgstr "Control Usher" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html~.php:3 +msgid "address" +msgstr "dirección" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html~.php:4 +msgid "port" +msgstr "puerto" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:5 +msgid "No connections found." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:3 +msgid "current server status:" +msgstr "estado actual del servidor:" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:4 +msgid "startup" +msgstr "inicio" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:5 +msgid "shutdown" +msgstr "apagado" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:6 +msgid "reload server configuration:" +msgstr "Recargar la configuración del servidor:" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:7 +msgid "reload" +msgstr "Recargar" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:11 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:11 +msgid "Status explanation" +msgstr "Explicación del estado" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:9 +msgid "active with n total open connections" +msgstr "activo con un total de n conexiones abiertas" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:10 +msgid "waiting for new connections" +msgstr "esperando nuevas conexiones" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:11 +msgid "usher is being shut down, not accepting connections" +msgstr "Usher está siendo cerrado, no aceptará conexiones" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:12 +msgid "" +"usher is shut down, all local servers are stopped and not accepting " +"connections" +msgstr "" +"Usher está apagado, todos los servidores locales están detenidos y no " +"aceptan conexiones" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:3 +msgid "server name" +msgstr "Nombre del servidor" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:4 IDF/Issue.php:99 +#: IDF/Review.php:102 +msgid "status" +msgstr "estado" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:5 +msgid "action" +msgstr "acción" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:6 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:6 +msgid "No monotone servers configured." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:7 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:7 +msgid "stop" +msgstr "parada" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:8 +msgid "start" +msgstr "inicio" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:9 +msgid "kill" +msgstr "matar" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:10 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:10 +msgid "active connections" +msgstr "conexiones activas" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:12 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:12 +msgid "remote server without open connections" +msgstr "servidor remoto sin conexiones abiertas" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:13 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:13 +msgid "server with n open connections" +msgstr "servidores con n conexiones abiertas" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:14 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:14 +msgid "local server running, without open connections" +msgstr "El servidor local se está ejecutando, sin conexiones abiertas" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:15 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:15 +msgid "local server not running, waiting for connections" +msgstr "El servidor local no se está ejecutando, a la espera de conexiones" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:16 +msgid "local server is about to stop, n connections still open" +msgstr "El servidor local está a punto de parar, n conexiones siguen abiertas" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:17 +msgid "local server not running, not accepting connections" +msgstr "El servidor local no se está ejecutando, no se aceptan conexiones" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:18 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:18 +msgid "usher is shut down, not running and not accepting connections" +msgstr "Usher está apagado, no se está ejecutando y no acepta conexiones" + +#: IDF/gettexttemplates/idf/index.atom.php:3 +#, php-format +msgid "Personal project feed for %%user%%." +msgstr "Feed del proyecto personal de %%user%%." + +#: IDF/gettexttemplates/idf/index.html.php:3 +#: IDF/gettexttemplates/idf/main-menu.html.php:6 +msgid "Home" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:3 +#, php-format +msgid "Attachment to issue %%issue.id%%" +msgstr "Archivo adjunto al ticket %%issue.id%%" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:5 +#: IDF/gettexttemplates/idf/review/view.html.php:35 +#: IDF/gettexttemplates/idf/source/commit.html.php:23 +#: IDF/gettexttemplates/idf/source/commit.html~.php:22 +#: IDF/gettexttemplates/idf/source/git/file.html.php:6 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:7 +msgid "Archive" +msgstr "Archivo" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:6 +#: IDF/gettexttemplates/idf/source/git/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:12 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:12 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:10 +msgid "Download this file" +msgstr "Descargar este archivo" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:7 +#: IDF/gettexttemplates/idf/issues/view.html.php:28 +#: IDF/gettexttemplates/idf/review/view.html.php:26 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:13 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:14 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:16 +msgid "Created:" +msgstr "Creado:" + +#: IDF/gettexttemplates/idf/issues/base.html.php:4 +msgid "All Issues" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/base.html.php:5 +msgid "My Issues" +msgstr "Mis Tickets" + +#: IDF/gettexttemplates/idf/issues/base.html.php:6 +msgid "My watch list" +msgstr "Mi lista de seguimiento" + +#: IDF/gettexttemplates/idf/issues/base.html.php:7 +#: IDF/gettexttemplates/idf/issues/by-label.html.php:6 +#: IDF/gettexttemplates/idf/issues/index.html.php:5 +#: IDF/gettexttemplates/idf/issues/project-watchlist.html.php:5 +#: IDF/gettexttemplates/idf/issues/search.html.php:8 +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:5 +msgid "New Issue" +msgstr "Nuevo Ticket" + +#: IDF/gettexttemplates/idf/issues/base.html.php:8 +#: IDF/gettexttemplates/idf/wiki/base.html.php:9 +msgid "Search" +msgstr "Búsqueda" + +#: IDF/gettexttemplates/idf/issues/base.html.php:9 +msgid "Back to the issue" +msgstr "Volver al ticket" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:3 +#, php-format +msgid "" +"

Open issues: %%open%%

\n" +"

Closed issues: %%closed%%

\n" +msgstr "" +"

Tickets abiertos: %%open%%\n" +"

Tickets cerrados: %%closed%%

\n" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:7 +msgid "Label:" +msgstr "Etiqueta:" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:8 +msgid "Completion:" +msgstr "Finalizados:" + +#: IDF/gettexttemplates/idf/issues/create.html.php:3 +msgid "" +"

When you submit the issue do not forget to provide the following " +"information:

\n" +"
    \n" +"
  • The steps to reproduce the problem.
  • \n" +"
  • The version of the software and your operating system.
  • \n" +"
  • Any information that can help the developers to solve the issue.
  • \n" +"
  • Do not provide any password or confidential information!
  • \n" +"
" +msgstr "" +"

Cuando envío el ticket, no se olvide proporcionar la siguiente " +"información:

\n" +"
    \n" +"
  • Los pasos para reproducir el problema.
  • \n" +"
  • La versión del software y tu sistema operativo.
  • \n" +"
  • Cualquier información que pueda ayudar a los desarrolladores para " +"resolver la incidencia.
  • \n" +"
  • ¡No proporcione ninguna contraseña o información confidencial!
  • \n" +"
" + +#: IDF/gettexttemplates/idf/issues/create.html.php:10 +msgid "The form contains some errors. Please correct them to submit the issue." +msgstr "" +"El formulario contiene algunos errores. Por favor, corríjalos para enviar el " +"ticket." + +#: IDF/gettexttemplates/idf/issues/create.html.php:11 +#: IDF/gettexttemplates/idf/issues/create.html.php:13 +#: IDF/gettexttemplates/idf/issues/view.html.php:24 +#: IDF/gettexttemplates/idf/issues/view.html.php:26 +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:5 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:5 +msgid "Preview" +msgstr "Previsualizar" + +#: IDF/gettexttemplates/idf/issues/create.html.php:12 +msgid "Submit Issue" +msgstr "Enviar Ticket" + +#: IDF/gettexttemplates/idf/issues/create.html.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:34 +msgid "Attach file" +msgstr "Adjuntar archivo" + +#: IDF/gettexttemplates/idf/issues/create.html.php:16 +#: IDF/gettexttemplates/idf/issues/create.html.php:17 +#: IDF/gettexttemplates/idf/issues/view.html.php:35 +#: IDF/gettexttemplates/idf/issues/view.html.php:36 +msgid "Attach another file" +msgstr "Adjuntar otro archivo" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:3 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:3 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:13 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:12 +#: IDF/gettexttemplates/idf/issues/view.html.php:18 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:3 +#: IDF/gettexttemplates/idf/review/view.html.php:38 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:11 +#: IDF/IssueComment.php:151 +msgid "Summary:" +msgstr "Resumen:" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:4 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:4 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:8 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:14 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:13 +#: IDF/gettexttemplates/idf/issues/view.html.php:19 +#: IDF/gettexttemplates/idf/issues/view.html.php:30 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:4 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/view.html.php:39 IDF/IssueComment.php:153 +msgid "Status:" +msgstr "Estado:" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:5 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:15 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:14 +#: IDF/gettexttemplates/idf/issues/view.html.php:20 +#: IDF/gettexttemplates/idf/issues/view.html.php:31 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:5 +#: IDF/IssueComment.php:155 +msgid "Owner:" +msgstr "Propietario:" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:17 +#: IDF/gettexttemplates/idf/issues/view.html.php:22 IDF/IssueComment.php:159 +msgid "Relations:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/forge-watchlist.html.php:3 +#: IDF/gettexttemplates/idf/issues/index.html.php:3 +#: IDF/gettexttemplates/idf/issues/project-watchlist.html.php:3 +#, php-format +msgid "" +"

Open issues: %%open%%

\n" +"

Closed issues: %%closed%%

" +msgstr "" +"

Tickets abiertos: %%open%%\n" +"

Tickets cerrados: %%closed%%

" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:3 +#, fuzzy +msgid "A new issue has been created and assigned to you:" +msgstr "" +"Un nuevo ticket ha sido creado y asignado\n" +"a tí:" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:4 +#, fuzzy +msgid "A new issue has been created:" +msgstr "Un nuevo commit se ha creado:" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:8 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:11 +msgid "Reported by:" +msgstr "Reportado por:" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:12 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:19 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:17 +msgid "Issue:" +msgstr "Tickets:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:3 +#, fuzzy +msgid "The following issue you are owning has been updated:" +msgstr "El ticket siguiente se ha actualizado:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:4 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:3 +msgid "The following issue has been updated:" +msgstr "El ticket siguiente se ha actualizado:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:4 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:4 +#, php-format +msgid "By %%who%%, %%c.creation_dtime%%:" +msgstr "Por %%who%%, %%c.creation_dtime%%:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:10 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:9 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:12 +msgid "URL:" +msgstr "URL:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:12 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:11 +msgid "Comments (last first):" +msgstr "Comentarios (más reciente primero):" + +#: IDF/gettexttemplates/idf/issues/search.html.php:3 +#, php-format +msgid "" +"\n" +"

Found open issues: %%open%%

\n" +"

Found closed issues: %%closed" +"%%

" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/search.html.php:6 +#, php-format +msgid "" +"

Label:\n" +"%%tag.class%%:" +"%%tag.name%%

" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:3 +#, fuzzy +msgid "View all open issues." +msgstr "Esta tabla muestra los tickets abiertos." + +#: IDF/gettexttemplates/idf/issues/summary.html.php:4 +#, fuzzy +msgid "Create an issue." +msgstr "Crear usuario" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:5 +#, php-format +msgid "" +"The issue tracker is empty.
Create your " +"first issue." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:6 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:4 +#, php-format +msgid "Unresolved: By %%key%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:7 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:5 +msgid "Status Summary" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:8 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:6 +msgid "Unresolved: By Assignee" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html~.php:3 +#, php-format +msgid "" +"The issue tracker is empty.
You can create your first issue here." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:3 +#, php-format +msgid "" +"See the %%nb_submit_closed%% closed." +msgid_plural "" +"See the %%nb_submit_closed%% closed." +msgstr[0] "" +"Ver %%nb_submit_closed%% tickets cerrado." +msgstr[1] "" +"Ver %%nb_submit_closed%% cerrado." + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:4 +#, php-format +msgid "" +"See the %%nb_owner_closed%% closed." +msgid_plural "" +"See the %%nb_owner_closed%% closed." +msgstr[0] "" +"Ver %%nb_owner_closed%% tickets cerrado." +msgstr[1] "" +"Ver %%nb_owner_closed%% cerrado." + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:6 +#: IDF/gettexttemplates/idf/user/dashboard.html.php:7 +msgid "Submitted issues:" +msgstr "Tickets enviados:" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:7 +#: IDF/gettexttemplates/idf/user/dashboard.html.php:6 +msgid "Working issues:" +msgstr "Tickets en curso:" + +#: IDF/gettexttemplates/idf/issues/view.html.php:3 +#, php-format +msgid "Reported by %%submitter%%, %%c.creation_dtime%%" +msgstr "Reportado por %%submitter%%, %%c.creation_dtime%%" + +#: IDF/gettexttemplates/idf/issues/view.html.php:4 +#: IDF/gettexttemplates/idf/review/view.html.php:22 +#, php-format +msgid "" +"Comment %%i%% by %%submitter%%, %%c.creation_dtime%%" +msgstr "" +"Comentario %%i%% por %%submitter%%, %%c." +"creation_dtime%%" + +#: IDF/gettexttemplates/idf/issues/view.html.php:5 +#, php-format +msgid "Sign in to reply to this comment." +msgstr "Accede para contestar a este comentario." + +#: IDF/gettexttemplates/idf/issues/view.html.php:6 +msgid "" +"This issue is marked as closed, add a comment only if you think this issue " +"is still valid and more work is needed to fully fix it." +msgstr "" +"Este ticket fue marcado como cerrado, añade un comentario sólo si crees que " +"este problema sigue activo y se necesita más trabajo hasta su completa " +"revisión." + +#: IDF/gettexttemplates/idf/issues/view.html.php:8 +#, php-format +msgid "%%interested%% person" +msgid_plural "%%interested%% persons" +msgstr[0] "%%interested%% persona" +msgstr[1] "%%interested%% personas" + +#: IDF/gettexttemplates/idf/issues/view.html.php:9 +#, php-format +msgid "This issue %%verb%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:10 +msgid "Remove this issue from your watch list" +msgstr "Eliminar este ticket de mi lista de seguimiento" + +#: IDF/gettexttemplates/idf/issues/view.html.php:11 +msgid "Add this issue to your watch list" +msgstr "Añadir este ticket a mi lista de seguimiento" + +#: IDF/gettexttemplates/idf/issues/view.html.php:12 +#, fuzzy +msgid "View the previous closed issue" +msgstr "Haga clic aquí para ver el anterior ticket cerrado" + +#: IDF/gettexttemplates/idf/issues/view.html.php:13 +#, fuzzy +msgid "View the previous open issue" +msgstr "Haga clic aquí para ver el anterior ticket abierto" + +#: IDF/gettexttemplates/idf/issues/view.html.php:14 +#, fuzzy +msgid "View the next closed issue" +msgstr "Haga clic aquí para ver la siguiente ticket cerrado" + +#: IDF/gettexttemplates/idf/issues/view.html.php:15 +#, fuzzy +msgid "View the next open issue" +msgstr "Haga clic aquí para ver la siguiente ticket abierto" + +#: IDF/gettexttemplates/idf/issues/view.html.php:16 +msgid "download" +msgstr "descarga" + +#: IDF/gettexttemplates/idf/issues/view.html.php:17 +msgid "view" +msgstr "ver" + +#: IDF/gettexttemplates/idf/issues/view.html.php:23 +msgid "The form contains some errors. Please correct them to change the issue." +msgstr "" +"El formulario contiene algunos errores. Por favor, corríjalos para " +"actualizar el ticket." + +#: IDF/gettexttemplates/idf/issues/view.html.php:25 +msgid "Submit Changes" +msgstr "Enviar cambios" + +#: IDF/gettexttemplates/idf/issues/view.html.php:32 +msgid "Followed by:" +msgstr "Seguido por:" + +#: IDF/gettexttemplates/idf/listProjects.html.php:3 +#, fuzzy, php-format +msgid "1 project" +msgid_plural "%%label.project_count%% projects" +msgstr[0] "proyecto" +msgstr[1] "proyecto" + +#: IDF/gettexttemplates/idf/listProjects.html.php:4 +#, php-format +msgid "Remove filter for %%tag%%" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:5 +msgid "No projects managed with InDefero were found." +msgstr "No se encontraron proyectos gestionados con InDefero." + +#: IDF/gettexttemplates/idf/listProjects.html.php:7 +msgid "Filter projects by label" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:8 +#, fuzzy +msgid "No projects with labels found." +msgstr "No se encontraron proyectos." + +#: IDF/gettexttemplates/idf/listProjects.html.php:9 +msgid "Order" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:10 +#, fuzzy +msgid "By name" +msgstr "nombre" + +#: IDF/gettexttemplates/idf/listProjects.html.php:11 +msgid "By activity" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:12 +msgid "Filtered project stats" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:13 +msgid "Members:" +msgstr "Miembros:" + +#: IDF/gettexttemplates/idf/listProjects.html.php:14 +msgid "Issues:" +msgstr "Tickets:" + +#: IDF/gettexttemplates/idf/listProjects.html.php:15 +msgid "Commits:" +msgstr "Commits" + +#: IDF/gettexttemplates/idf/listProjects.html.php:16 +msgid "Documentations:" +msgstr "Documentación:" + +#: IDF/gettexttemplates/idf/listProjects.html.php:18 +msgid "Code reviews:" +msgstr "Revisiones del código:" + +#: IDF/gettexttemplates/idf/login_form.html.php:3 +#, fuzzy, php-format +msgid "" +"You can create an account if you don't have one yet." +msgstr "" +"Puede usar sintaxis de Marcado para la descripción." + +#: IDF/gettexttemplates/idf/login_form.html.php:4 +msgid "What is your account information?" +msgstr "¿Cuál es la información de su cuenta?" + +#: IDF/gettexttemplates/idf/login_form.html.php:5 +msgid "My login is" +msgstr "Mi identificador es" + +#: IDF/gettexttemplates/idf/login_form.html.php:6 +msgid "My password is" +msgstr "Mi contraseña es" + +#: IDF/gettexttemplates/idf/login_form.html.php:7 +msgid "Sign in" +msgstr "Ingresar" + +#: IDF/gettexttemplates/idf/login_form.html.php:8 +msgid "I lost my password!" +msgstr "¡He perdido mi contraseña!" + +#: IDF/gettexttemplates/idf/login_form.html.php:9 +msgid "Welcome." +msgstr "Bienvenido." + +#: IDF/gettexttemplates/idf/login_form.html.php:10 +msgid "It takes less than a minute to create your account." +msgstr "Se tarda menos de un minuto en crearte una cuenta." + +#: IDF/gettexttemplates/idf/main-menu.html.php:3 +#, php-format +msgid "" +"Welcome, %%user%%." +msgstr "" +"Bienvenido, %%user%%." + +#: IDF/gettexttemplates/idf/main-menu.html.php:4 +msgid "Sign Out" +msgstr "Salir" + +#: IDF/gettexttemplates/idf/main-menu.html.php:5 +msgid "Sign in or create your account" +msgstr "Accede o create una cuenta" + +#: IDF/gettexttemplates/idf/main-menu.html.php:10 IDF/Views/Admin.php:40 +msgid "Forge Management" +msgstr "Gestión de la Forja" + +#: IDF/gettexttemplates/idf/main-menu.html.php:11 +msgid "Help and accessibility features" +msgstr "Ayuda y características de accesibilidad" + +#: IDF/gettexttemplates/idf/main-menu.html.php:12 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:14 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:14 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:15 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:13 +msgid "Help" +msgstr "Ayuda" + +#: IDF/gettexttemplates/idf/project/home.html.php:3 +#: IDF/gettexttemplates/idf/project/timeline.html.php:4 IDF/Views.php:46 +msgid "Welcome" +msgstr "Bienvenido" + +#: IDF/gettexttemplates/idf/project/home.html.php:4 +#: IDF/gettexttemplates/idf/project/timeline.html.php:5 +msgid "Latest Updates" +msgstr "Últimas actualizaciones" + +#: IDF/gettexttemplates/idf/project/home.html.php:5 +msgid "Featured Downloads" +msgstr "Descargas destacadas" + +#: IDF/gettexttemplates/idf/project/home.html.php:6 +#, fuzzy +msgid "Show more featured downloads" +msgstr "Descargas destacadas" + +#: IDF/gettexttemplates/idf/project/home.html.php:7 +#: IDF/gettexttemplates/idf/project/home.html.php:10 +msgid "show more..." +msgstr "ver más..." + +#: IDF/gettexttemplates/idf/project/home.html.php:8 +msgid "Featured Documentation" +msgstr "Documentación destacada" + +#: IDF/gettexttemplates/idf/project/home.html.php:9 +#, fuzzy +msgid "Show more featured documentation" +msgstr "Documentación destacada" + +#: IDF/gettexttemplates/idf/project/home.html.php:11 +msgid "Development Team" +msgstr "Equipo de Desarrollo" + +#: IDF/gettexttemplates/idf/project/home.html.php:12 +msgid "Admins" +msgstr "Administradores" + +#: IDF/gettexttemplates/idf/project/home.html.php:13 +msgid "Happy Crew" +msgstr "Equipo Feliz" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:3 +msgid "Latest updates" +msgstr "Últimas actualizaciones" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:6 +#: IDF/Views/Project.php:90 +msgid "All Updates" +msgstr "Todas las actualizaciones" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:7 +msgid "Filter by type" +msgstr "Filtrar por tipo" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:8 +msgid "Subscribe to this timeline" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:9 +msgid "RSS" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:10 +msgid "Atom feed" +msgstr "" + +#: IDF/gettexttemplates/idf/project-list.html.php:3 +msgid "Project activity: %%activity%%%" +msgstr "" + +#: IDF/gettexttemplates/idf/project-list.html.php:9 +msgid "n/a" +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation-email.txt.php:3 +#, php-format +msgid "" +"Hello,\n" +"\n" +"You have requested the creation of an account to\n" +"participate in the life of a software project.\n" +"\n" +"To confirm the account please follow this link:\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following confirmation key:\n" +"\n" +"%%key%%\n" +"\n" +"If you are not interested any longer in taking\n" +"part in the life of the software project or if\n" +"you can't remember having requested the creation\n" +"of an account, please excuse us and simply ignore\n" +"this email. \n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" +"Hola,\n" +"\n" +"Has solicitado la creación de una cuenta para\n" +"participar en el desarrollo de un proyecto software.\n" +"\n" +"Para confirmar la cuenta, por favor siga este enlace:\n" +"\n" +"%%url%%\n" +"\n" +"Alternativamente, vaya a esta página:\n" +"\n" +"%%urlik%%\n" +"\n" +"y proporcione la siguiente clave de confirmación:\n" +"\n" +"%%key%%\n" +"\n" +"Si no está interesado en participar en el desarrollo de un \n" +"proyecto software o si\n" +"no recuerdas haber solicitado la creación de una cuenta,\n" +"por favor, perdone y simplemente ignore \n" +"este mensaje. \n" +"\n" +"Atentamente,\n" +"El equipo de desarrollo.\n" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:3 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:3 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:3 +msgid "Oops, please check the form for errors." +msgstr "Oups, por favor revise los errores del formulario." + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:5 +msgid "Email:" +msgstr "Email:" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:6 +msgid "Enable Your Account" +msgstr "Activar tu cuenta" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:8 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:8 +msgid "" +"This is the last step, but just be sure to have the cookies enabled to log in afterwards." +msgstr "" +"Este es el último paso, pero asegúrese de tener las cookies " +"activadas para identificarte." + +#: IDF/gettexttemplates/idf/register/index.html.php:3 +#, fuzzy +msgid "" +"Read the terms and conditions – " +"basically \"Please be nice, we respect you\"." +msgstr "" +"Lea los términos y condiciones " +"– basicamente \"Por favor, sea amable y respetuoso\"." + +#: IDF/gettexttemplates/idf/register/index.html.php:4 +#, fuzzy, php-format +msgid "" +"If you have just forgotten your login information, then there is no need to " +"create a new account. You can just recover your login " +"name and password." +msgstr "" +"Si ha olvidado los datos de acceso, entonces no tiene porque crear una nueva " +"cuenta. Simplemente haga click aquí para recuperar " +"su nombre de usuario y contraseña." + +#: IDF/gettexttemplates/idf/register/index.html.php:5 +#, php-format +msgid "" +"With your account, you will able to participate in the life of all the " +"projects hosted here. Participating in a software project must be fun, so if " +"you have troubles, you can let us know about your issues " +"at anytime!" +msgstr "" +"Con su cuenta, será capaz de participar en el desarrollo de todos los " +"proyectos alojados aquí. Participar en un proyecto software tiene que ser " +"algo divertido e interesante, así que si tiene problemas, puede ¡hacernos saber cuáles son sus inquietudes en cualquier momento!" + +#: IDF/gettexttemplates/idf/register/index.html.php:6 +msgid "Oops, please check the provided login and email address to register." +msgstr "" +"Oups, por favor comprueba el nombre de usuario y dirección de correo " +"electrónico de registro." + +#: IDF/gettexttemplates/idf/register/index.html.php:7 IDF/Views.php:137 +msgid "Create Your Account" +msgstr "Crea tu cuenta" + +#: IDF/gettexttemplates/idf/register/index.html.php:9 +msgid "" +"Be sure to provide a valid email address, as we are sending a validation " +"link by email." +msgstr "" +"Asegúrese de proporcionar una dirección válida de correo electrónico, ya que " +"se enviará un enlace de confirmación por correo electrónico." + +#: IDF/gettexttemplates/idf/register/index.html.php:10 +msgid "Did you know?" +msgstr "¿Sabía que?" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:3 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:3 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:3 +msgid "Oops, we found an error in the form." +msgstr "Oups, se encontró un error en el formulario." + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:4 +msgid "Confirm Your Account" +msgstr "Confirma tu cuenta" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:7 +msgid "" +"Use your email software to read your emails and open your confirmation " +"email. Either click directly on the confirmation link or copy/paste the " +"confirmation key in the box and submit the form." +msgstr "" +"Utilice su software de correo electrónico para abrir y leer el email de " +"confirmación. Puede hacer clic directamente en el enlace de confirmación o " +"copiar y pegar la clave de confirmación y enviar el formulario." + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:8 +msgid "" +"Just after providing the confirmation key, you will be able to set your " +"password and start using this website fully." +msgstr "" +"Sólo después de proporcionar la clave de confirmación, será capaz de " +"establecer su contraseña y empezar a usar completamente el sitio web." + +#: IDF/gettexttemplates/idf/review/base-full.html.php:3 +#: IDF/gettexttemplates/idf/review/base.html.php:3 +msgid "Open Reviews" +msgstr "Revisiones abiertas" + +#: IDF/gettexttemplates/idf/review/base.html.php:4 +#: IDF/gettexttemplates/idf/review/create.html.php:11 +#: IDF/gettexttemplates/idf/review/index.html.php:3 IDF/Views/Review.php:83 +msgid "Start Code Review" +msgstr "Iniciar revisión del Código" + +#: IDF/gettexttemplates/idf/review/create.html.php:3 +msgid "" +"

To start a code review, you need to provide:

\n" +"
    \n" +"
  • A commit or revision of the current code in the repository from which " +"you started your work.
  • \n" +"
  • A patch describing your changes with respect to the reference commit.\n" +"
  • Check your patch does not provide any password or confidential " +"information!
  • \n" +"
" +msgstr "" +"

Para iniciar una revisión de código, debe proporcionar:

\n" +"
    \n" +"
  • Un commit o revisión del actual código del repositorio, desde el que ha " +"comenzado su trabajo.
  • \n" +"
  • Un parche que describa los cambios con respecto al commit referenciado.\n" +"
  • ¡Asegúrese de que el parche no contiene ninguna contraseña o " +"información confidencial!
  • \n" +"
" + +#: IDF/gettexttemplates/idf/review/create.html.php:9 +msgid "" +"The form contains some errors. Please correct them to submit the code review." +msgstr "" +"El formulario contiene algunos errores. Por favor, corríjalos para enviar la " +"revisión de código." + +#: IDF/gettexttemplates/idf/review/create.html.php:10 +msgid "" +"Select the commit against which you created your patch to be sure it applies " +"correctly." +msgstr "" +"Seleccione el commit contra el que creó el parche para asegurarse de que se " +"aplica correctamente." + +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:3 +msgid "The following review has been created:" +msgstr "La siguiente revisión se ha creado:" + +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:16 +msgid "Review:" +msgstr "Revisión:" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:3 +msgid "The following review has been updated:" +msgstr "La siguiente revisión se ha actualizado:" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:5 +#, php-format +msgid "" +"By %%who%%, %%c.creation_dtime%%, on file:\n" +"%%c.cfile%%\n" +msgstr "" +"Por %%who%%, %%c.creation_dtime%%, en el archivo:\n" +"%%c.cfile%%\n" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:14 +msgid "General comments (last first):" +msgstr "Comentarios generales (más reciente primero):" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:15 +msgid "Detailed file comments (last first):" +msgstr "Comentarios detallados del archivo (más reciente primero):" + +#: IDF/gettexttemplates/idf/review/view.html.php:3 +msgid "" +"Code review is a process in which\n" +"after or before changes are commited into the code repository,\n" +"different people discuss the code changes. The goal is\n" +"to improve the quality of the code and the\n" +"contributions, as such, you must be pragmatic when writing\n" +"your review. Correctly mention the line numbers (in the old or in the\n" +"new file) and try to keep a good balance between seriousness and fun.\n" +msgstr "" +"La revisión de código es una proceso en el que\n" +"antes o después los cambios son commited en el código del repositorio,\n" +"diferentes personas discuten sobre los cambios en el código. El objetivo " +"es \n" +"mejorar la calidad del código y las\n" +"contribuciones, por esto, debe ser pragmático cuando escriba \n" +"sus comentarios. Menciona correctamente los números de línea (tanto en el " +"antiguo como en el \n" +"nuevo código) y trata de mantener un buen equilibrio entre seriedad y " +"diversión\n" + +#: IDF/gettexttemplates/idf/review/view.html.php:11 +msgid "" +"\n" +"Proposing code for review is intimidating, you know\n" +"you will receive critics, so please, as a reviewer, keep this\n" +"process fun, use it to help your contributor learn your\n" +"coding standards and the structure of the code and make them want\n" +"to propose more contributions.\n" +msgstr "" +"\n" +"La propuesta para revisar código es intimidante, debes " +"saber \n" +"que recibirás críticas, así que por favor, como revisor, haz que " +"este \n" +"proceso sea divertido, úsalo para para ayudar al colaborador a " +"aprender tus \n" +"normas de codificación y a estructurar el código y hacer que \n" +"quieran proponer más contribuciones.\n" + +#: IDF/gettexttemplates/idf/review/view.html.php:18 +#: IDF/gettexttemplates/idf/source/commit.html.php:3 +#: IDF/gettexttemplates/idf/source/commit.html~.php:3 +#, php-format +msgid "%%ndiff%% diff" +msgid_plural "%%ndiff%% diffs" +msgstr[0] "%%ndiff%% diferencia" +msgstr[1] "%%ndiff%% diferencias" + +#: IDF/gettexttemplates/idf/review/view.html.php:19 +#, php-format +msgid "%%nc%% comment" +msgid_plural "%%nc%% comments" +msgstr[0] "%%nc%% comentario" +msgstr[1] "%%nc%% comentarios" + +#: IDF/gettexttemplates/idf/review/view.html.php:20 +#, php-format +msgid "" +"Comment
%%i%% by %%who%%, " +"%%c.creation_dtime%%" +msgstr "" +"Comentario %%i%% por %%who%%, %%c.creation_dtime%%" + +#: IDF/gettexttemplates/idf/review/view.html.php:21 +#, php-format +msgid "Your comments on the changes in file %%file%%:" +msgstr "Tus comentarios sobre los cambios en el archivo %%file%%:" + +#: IDF/gettexttemplates/idf/review/view.html.php:23 +#, php-format +msgid "Sign in to participate in the review." +msgstr "Accede para participar en la revisión." + +#: IDF/gettexttemplates/idf/review/view.html.php:24 +msgid "" +"The form contains some errors. Please correct them to submit your review." +msgstr "" +"El formulario contiene algunos errores. Por favor, corríjalos para enviar su " +"revisión." + +#: IDF/gettexttemplates/idf/review/view.html.php:25 +msgid "How to Participate in a Code Review" +msgstr "Cómo participar en una revisión de código" + +#: IDF/gettexttemplates/idf/review/view.html.php:28 +#: IDF/gettexttemplates/idf/source/commit.html.php:5 +#: IDF/gettexttemplates/idf/source/commit.html~.php:5 +msgid "Author:" +msgstr "Autor:" + +#: IDF/gettexttemplates/idf/review/view.html.php:29 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/source/commit.html.php:7 +#: IDF/gettexttemplates/idf/source/commit.html~.php:7 +msgid "Commit:" +msgstr "Commit:" + +#: IDF/gettexttemplates/idf/review/view.html.php:30 +#: IDF/gettexttemplates/idf/source/commit.html.php:8 +#: IDF/gettexttemplates/idf/source/commit.html~.php:8 +msgid "View corresponding source tree" +msgstr "Ver código fuente correspondiente" + +#: IDF/gettexttemplates/idf/review/view.html.php:32 +msgid "Reviewers:" +msgstr "Revisores:" + +#: IDF/gettexttemplates/idf/review/view.html.php:33 +msgid "No reviewers at the moment." +msgstr "Sin revisores en este momento." + +#: IDF/gettexttemplates/idf/review/view.html.php:34 +msgid "Files:" +msgstr "Archivos:" + +#: IDF/gettexttemplates/idf/review/view.html.php:36 +#: IDF/gettexttemplates/idf/source/commit.html.php:24 +#: IDF/gettexttemplates/idf/source/commit.html~.php:23 +msgid "Download the corresponding diff file" +msgstr "Descargue el correspondiente archivo diff" + +#: IDF/gettexttemplates/idf/review/view.html.php:37 +msgid "General Comments" +msgstr "Comentarios generales" + +#: IDF/gettexttemplates/idf/review/view.html.php:40 +msgid "Submit Code Review" +msgstr "Enviar Revisión del Código" + +#: IDF/gettexttemplates/idf/source/base.html.php:3 +msgid "Source Tree" +msgstr "Árbol de las fuentes" + +#: IDF/gettexttemplates/idf/source/base.html.php:4 +msgid "Change Log" +msgstr "Listado de cambios" + +#: IDF/gettexttemplates/idf/source/base.html.php:6 +msgid "How To Get The Code" +msgstr "Cómo obtener el Código" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:3 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:8 +#: IDF/Views/Project.php:190 +msgid "Age" +msgstr "Edad" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:4 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:10 +msgid "Message" +msgstr "Mensaje" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:5 +msgid "Parent:" +msgstr "Padres:" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:6 +#: IDF/gettexttemplates/idf/source/commit.html.php:10 +#: IDF/gettexttemplates/idf/source/commit.html~.php:10 +msgid "View corresponding commit" +msgstr "Ver commit correspondiente" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:8 +msgid "by" +msgstr "por" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:3 +msgid "A new commit has been created:" +msgstr "Un nuevo commit se ha creado:" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:8 +msgid "Created by:" +msgstr "Creado por:" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:8 +msgid "Created at:" +msgstr "Creado el:" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:8 +msgid "Content:" +msgstr "Contenido:" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:10 +msgid "Commit details:" +msgstr "Detalles del commit:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:4 +#: IDF/gettexttemplates/idf/source/commit.html~.php:4 +msgid "Date:" +msgstr "Fecha:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:6 +#: IDF/gettexttemplates/idf/source/commit.html~.php:6 +msgid "Branch:" +msgstr "Branch:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:9 +#: IDF/gettexttemplates/idf/source/commit.html~.php:9 +msgid "Parents:" +msgstr "Padres:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:11 +#: IDF/gettexttemplates/idf/source/commit.html~.php:11 +msgid "Message:" +msgstr "Mensaje:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:12 +#: IDF/gettexttemplates/idf/source/commit.html~.php:12 +#: IDF/gettexttemplates/idf/wiki/feedfragment-page.xml.php:3 +#: IDF/gettexttemplates/idf/wiki/feedfragment-resource.xml.php:3 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:10 +msgid "Changes:" +msgstr "Cambios:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:13 +#: IDF/gettexttemplates/idf/source/commit.html~.php:13 +msgid "deleted" +msgstr "eliminado" + +#: IDF/gettexttemplates/idf/source/commit.html.php:14 +#: IDF/gettexttemplates/idf/source/commit.html.php:18 +#: IDF/gettexttemplates/idf/source/commit.html~.php:14 +#: IDF/gettexttemplates/idf/source/commit.html~.php:17 +msgid "full" +msgstr "completo" + +#: IDF/gettexttemplates/idf/source/commit.html.php:15 +#: IDF/gettexttemplates/idf/source/commit.html~.php:15 +msgid "renamed" +msgstr "renombrado" + +#: IDF/gettexttemplates/idf/source/commit.html.php:16 +msgid "copied" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:17 +#: IDF/gettexttemplates/idf/source/commit.html~.php:16 +msgid "added" +msgstr "añadido" + +#: IDF/gettexttemplates/idf/source/commit.html.php:19 +#: IDF/gettexttemplates/idf/source/commit.html~.php:18 +msgid "modified" +msgstr "modificado" + +#: IDF/gettexttemplates/idf/source/commit.html.php:20 +#, fuzzy +msgid "properties changed" +msgstr "propiedades modificadas" + +#: IDF/gettexttemplates/idf/source/commit.html.php:21 +#: IDF/gettexttemplates/idf/source/commit.html~.php:20 +msgid "removed" +msgstr "eliminado" + +#: IDF/gettexttemplates/idf/source/commit.html.php:22 +#: IDF/gettexttemplates/idf/source/commit.html~.php:21 +msgid "File differences" +msgstr "Diferencias de archivos" + +#: IDF/gettexttemplates/idf/source/commit.html~.php:19 +msgid "properies changed" +msgstr "propiedades modificadas" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:3 +#, php-format +msgid "" +"The revision identifier %%commit%% is ambiguous and can be\n" +"expanded to multiple valid revisions - please choose one:" +msgstr "" +"Identificador de la revisión %%commit%% es ambiguo y puede estar\n" +"asociado con diferentes revisiones válidas - Por favor, elija uno:" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:5 +msgid "Title" +msgstr "Título" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:6 +msgid "Author" +msgstr "Autor" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:7 +msgid "Date" +msgstr "Fecha" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:8 +msgid "Branch" +msgstr "Branch" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:9 +msgid "Revision" +msgstr "Revisión" + +#: IDF/gettexttemplates/idf/source/feedfragment.xml.php:3 +#, php-format +msgid "%%cproject.name%%: Commit %%c.scm_id%%" +msgstr "%%cproject.name%%: Commit %%c.scm_id%%" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:3 +msgid "Branches" +msgstr "Branches" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:4 +msgid "filter branches" +msgstr "Filtrar branches" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:5 +msgid "Tags" +msgstr "Etiquetas" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:6 +msgid "filter tags" +msgstr "Filtrar etiquetas" + +#: IDF/gettexttemplates/idf/source/git/file.html.php:3 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:4 +#, php-format +msgid "" +"Source at commit %%commit%% created " +"%%cobject.date%%." +msgstr "" +"Fuente del commit %%commit%% creado " +"%%cobject.date%%." + +#: IDF/gettexttemplates/idf/source/git/file.html.php:4 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:5 +#, php-format +msgid "By %%cobject.author%%, %%cobject.title%%" +msgstr "Por %%cobject.author%%, %%cobject.title%%" + +#: IDF/gettexttemplates/idf/source/git/file.html.php:5 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:6 +msgid "Root" +msgstr "Root" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the git software to manage the source\n" +"code." +msgstr "" +"El equipo detrás de %%project%% está utilizando\n" +"el software git para gestionar el código\n" +"fuente." + +#: IDF/gettexttemplates/idf/source/git/help.html.php:6 +#, php-format +msgid "" +"You may need to provide your SSH key. The " +"synchronization of your SSH key can take a couple of minutes. You can learn " +"more about SSH key authentication." +msgstr "" +"Puede que tenga que proporcionar su clave SSH. La " +"sincronización de la clave SSH puede tomar un par de minutos. Puede saber " +"más acerca de autenticación de claves SSH." + +#: IDF/gettexttemplates/idf/source/git/help.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:6 +msgid "To make a first commit in the repository, perform the following steps:" +msgstr "" +"Para hacer el primer commit en el repositorio, siga los siguientes pasos:" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:8 +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:7 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:7 +#, php-format +msgid "Find here more details on how to access %%project%% source code." +msgstr "" +"Encuentra aquí más detalles sobre la forma de acceso al código fuente del " +"proyecto %%project%%." + +#: IDF/gettexttemplates/idf/source/git/help.html.php:9 +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:8 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:8 +msgid "Command-Line Access" +msgstr "Acceso línea de comandos" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:10 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:9 +msgid "First Commit" +msgstr "Primer Commit" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:11 +#: IDF/Views/Download.php:66 IDF/Views/Download.php:348 +msgid "Size" +msgstr "Tamaño" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:12 +msgid ":" +msgstr ":" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:13 +msgid "Download this version" +msgstr "Descargar esta versión" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:13 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:13 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:14 +msgid "or" +msgstr "o" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:3 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:3 +#, php-format +msgid "" +"The branch or revision %%commit%% is not valid or does not exist\n" +"in this repository." +msgstr "" +"La rama o revisión %%commit%% no es válida o no existe\n" +"en este repositorio." + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:5 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:5 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:5 +msgid "The following list shows all available branches:" +msgstr "La siguiente lista muestra todas las ramas disponibles:" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:6 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:6 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:6 +#, php-format +msgid "" +"If this is a new repository, the reason for this error\n" +"could be that you have not committed and / or pushed any change so far.\n" +"In this case please take a look at the Help page\n" +"how to access your repository." +msgstr "" +"Si se trata de un nuevo repositorio, la razón de este error\n" +"podría ser que no ha realizado ningún commit y / o push hasta el momento.\n" +"En este caso, por favor eche un vistazo a la Página de " +"Ayuda\n" +"sobre cómo tener acceso a su repositorio." + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the Mercurial software to manage the source\n" +"code." +msgstr "" +"El equipo detrás de %%project%% está utilizando\n" +"el software Mercurial para gestionar el código\n" +"fuente." + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:6 +#, php-format +msgid "" +"To get write access to the repository, you need to use your username and " +"your extra password." +msgstr "" +"Para tener acceso de escritura al repositorio, necesita usar su nombre de " +"usuario y su contraseña adicional." + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:9 +msgid "Write Access Authentication" +msgstr "Escribe una autenticación de acceso" + +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:3 +#, php-format +msgid "Property %%prop%% set to %%val%%" +msgstr "" + +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the monotone software to manage the source\n" +"code." +msgstr "" +"El equipo detrás de %%project%% está utilizando\n" +"el software monotone para administrar el código fuente." + +#: IDF/gettexttemplates/idf/source/svn/changelog.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/commit.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/commit.html~.php:3 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:14 +msgid "Revision:" +msgstr "Revisión:" + +#: IDF/gettexttemplates/idf/source/svn/changelog.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/commit.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/commit.html~.php:4 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:10 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:15 +msgid "Switch" +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the subversion software to manage the source\n" +"code." +msgstr "" +"El equipo detrás de %%project%% está utilizando\n" +"el software subversion para gestionar el código\n" +"fuente." + +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:3 +#, php-format +msgid "" +"The revision %%commit%% is not valid or does not exist\n" +"in this repository." +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:9 +msgid "Rev" +msgstr "Rev" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:16 +msgid "Branches:" +msgstr "Branches:" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:17 +msgid "Tags:" +msgstr "Etiquetas:" + +#: IDF/gettexttemplates/idf/user/changeemail-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"To confirm that you want %%email%%\n" +"to be your new email address, just follow this link:\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following verification key:\n" +"\n" +"%%key%%\n" +"\n" +"If you do not want to change your email address, \n" +"just ignore this message.\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" +"Hola %%user%%,\n" +"\n" +"Para confirmar que quieres %%email%%\n" +"como nuevo email, solo tienes que seguir este enlace:\n" +"\n" +"%%url%%\n" +"\n" +"Alternativamente, vaya a esta página:\n" +"\n" +"%%urlik%%\n" +"\n" +"y proporciona el siguiente código de verificación:\n" +"\n" +"%%key%%\n" +"\n" +"Si no desea cambiar su dirección email, \n" +"simplemente ignore este mensaje.\n" +"\n" +"Atentamente,\n" +"El equipo de desarrollo.\n" + +#: IDF/gettexttemplates/idf/user/changeemail.html.php:4 +msgid "Confirm Your New Email Address" +msgstr "Confirme su nueva dirección de email" + +#: IDF/gettexttemplates/idf/user/changeemail.html.php:7 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:7 +msgid "" +"Use your email software to read your emails and open your verification " +"email. Either click directly on the verification link or copy/paste the " +"verification key in the box and submit the form." +msgstr "" +"Utilice su software de correo electrónico para leer su email y abrir su " +"email de verificación. Puede hacer clic directamente en el enlace de " +"verificación o copiar y pegar la clave de verificación en la caja y darle a " +"enviar en el formulario." + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:3 +#, php-format +msgid "Update your account." +msgstr "Actualiza tu cuenta." + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:4 +#, php-format +msgid "See your public profile." +msgstr "Ver tu perfil público." + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:5 +#, php-format +msgid "See your forge issue watch list." +msgstr "" +"Ver tus tickets de la lista de mantenimiento de la " +"Forja." + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:6 +msgid "Key Management" +msgstr "Administración de claves" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:7 +msgid "Secondary Emails" +msgstr "Emails secundarios" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:8 +msgid "Extra password" +msgstr "Contraseña adicional" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:9 +msgid "" +"This password is used to access some of the external systems managed by our " +"infrastructure. It will be regenerated if you change your password." +msgstr "" +"Esta contraseña se utiliza para acceder a algunos de los sistemas externos " +"gestionados por nuestra infraestructura. Se regenerará si usted cambia su " +"contraseña." + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:10 +msgid "API key" +msgstr "Clave de API" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:11 +msgid "" +"Your API key will be regenerated automatically if you change your password." +msgstr "" +"La clave de la API se regenera automáticamente si usted cambia su contraseña." + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:12 +msgid "Update Your Account" +msgstr "Actualiza tu cuenta" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:14 +msgid "Your Current Public Keys" +msgstr "Tus claves públicas actuales" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:15 +msgid "Delete this key" +msgstr "Eliminar esta clave" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:16 +msgid "Your additional email addresses" +msgstr "Sus direcciones de correo electrónico adicionales." + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:17 +msgid "Delete this address" +msgstr "Eliminar esta dirección" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:18 +msgid "" +"If possible, use your real name. By using your real name, people will have " +"more trust in your comments and remarks." +msgstr "" +"Si es posible, use su nombre real. Mediante el uso de su nombre real, las " +"personas tendrán más confianza en sus comentarios y observaciones." + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:19 +msgid "" +"The extra password is used to access some of the external systems and the " +"API key is used to interact with this website using a program." +msgstr "" +"La contraseña adicional se utiliza para acceder a algunos de los sistemas " +"externos y la clave de la API se utiliza para interactuar con este sitio web " +"utilizando un programa." + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:20 +msgid "Show API key and extra password" +msgstr "Mostrar clave de API y contraseña adicional" + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:3 +msgid "" +"Oops, please check the provided login or email address to recover your " +"password." +msgstr "" +"Oups, por favor comprueba el nombre de usuario o dirección de correo " +"electrónico para recuperar su clave." + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:4 +msgid "Recover My Password" +msgstr "Recuperar mi contraseña" + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:6 +msgid "" +"Provide either your login or email address, if a corresponding user is found " +"in the database, we will send you an email with the details on how to reset " +"your password." +msgstr "" +"Proporcione un usuario o dirección de correo electrónico, si el usuario " +"correspondiente se encuentra en la base de datos, le enviaremos un email con " +"los detalles sobre cómo restablecer su contraseña." + +#: IDF/gettexttemplates/idf/user/passrecovery-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"You lost your password and wanted to recover it.\n" +"To provide a new password for your account, you\n" +"just have to follow the provided link. You will\n" +"get a simple form to provide a new password.\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following verification key:\n" +"\n" +"%%key%%\n" +"\n" +"If you are not the one who requested to reset\n" +"your password, simply ignore this email, your\n" +"password will not be changed.\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" +"Hola %%user%%,\n" +"\n" +"Has perdido tu contraseña y quieres recuperarla.\n" +"Para proporcionarte una nueva contraseña para tu cuenta, solo\n" +"tienes que seguir el siguiente enlace. Obtendrás\n" +"un simple formulario donde proporcionar una nueva contraseña.\n" +"\n" +"%%url%%\n" +"\n" +"Alternativamente, puede ir a esta página:\n" +"\n" +"%%urlik%%\n" +"\n" +"y proporcionar la clave de verificación siguiente:\n" +"\n" +"%%key%%\n" +"\n" +"Si no solicitó reestablecer la contraseña,\n" +"simplemente ignore este correo electrónico, tu\n" +"contraseña no cambiará.\n" +"\n" +"Atentamente,\n" +"El equipo de desarrollo.\n" + +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:4 +msgid "Recover Your Password" +msgstr "Recuperar contraseña" + +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:8 +msgid "" +"Just after providing the confirmation key, you will be able to reset your " +"password and use this website fully." +msgstr "" +"Sólo después de proporcionar la clave de confirmación, será capaz de " +"restablecer la contraseña y hacer uso completamente del sitio web." + +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:6 +msgid "Reset Your Password" +msgstr "Restablecer contraseña" + +#: IDF/gettexttemplates/idf/user/public.html.php:3 +#, php-format +msgid "You are looking at the public profile of %%member%%." +msgstr "Estás viendo el perfil público de %%member%%." + +#: IDF/gettexttemplates/idf/user/public.html.php:5 +msgid "Twitter:" +msgstr "Twitter:" + +#: IDF/gettexttemplates/idf/user/public.html.php:6 +msgid "Public Email:" +msgstr "Email Público:" + +#: IDF/gettexttemplates/idf/user/public.html.php:7 +msgid "Website:" +msgstr "Página web:" + +#: IDF/gettexttemplates/idf/user/public.html.php:8 +msgid "Last time seen:" +msgstr "Última vez visto:" + +#: IDF/gettexttemplates/idf/user/public.html.php:9 +msgid "Member since:" +msgstr "Miembro desde:" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:3 +msgid "List Pages" +msgstr "Lista de Páginas" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:4 +#, fuzzy +msgid "List Resources" +msgstr "Fuente %s" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:5 +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:4 +#: IDF/gettexttemplates/idf/wiki/search.html.php:3 IDF/Views/Wiki.php:211 +msgid "New Page" +msgstr "Nueva página" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:6 +#: IDF/gettexttemplates/idf/wiki/listResources.html.php:3 +#: IDF/Views/Wiki.php:256 +#, fuzzy +msgid "New Resource" +msgstr "Nuevo Ticket" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:7 +msgid "Update This Page" +msgstr "Actualizar esta página" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:8 +#, fuzzy +msgid "Update This Resource" +msgstr "Actualizar esta página" + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:3 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:3 +msgid "Preview of the Page" +msgstr "Vista previa de la página" + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:7 +msgid "The form contains some errors. Please correct them to create the page." +msgstr "" +"El formulario contiene algunos errores. Por favor, corríjalos para crear la " +"página." + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:6 +msgid "Create Page" +msgstr "Crear Página" + +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:3 +msgid "" +"\n" +"Wiki resources are later addressed in wiki pages by their title, so ensure " +"that you\n" +"give your resource a unique and an easy to remember name.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:8 +#, fuzzy +msgid "Create Resource" +msgstr "Crear usuario" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:3 +msgid "" +"If you delete this documentation page, it will be removed from the database " +"with all the associated revisions and you will not be able to " +"recover it." +msgstr "" +"Si elimina esta página de documentación, será eliminada de la base de datos " +"con todas las revisiones relacionadas y no será capaz de recuperarla." +"" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:6 +msgid "Delete Page" +msgstr "Eliminar página" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:14 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:15 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:15 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:17 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:18 +msgid "Old Revisions" +msgstr "Revisiones antiguas" + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:3 +#, php-format +msgid "" +"You are looking at an old revision (%%oldrev.summary%%) of the " +"page \n" +"%%page.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" +"Está viendo una revisión antigua (%%oldrev.summary%%) de la " +"página \n" +"%%page.title%%. Esta revisión fue creada por " +"%%submitter%%." + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:5 +msgid "" +"If you delete this old revision, it will be removed from the database and " +"you will not be able to recover it." +msgstr "" +"Si elimina esta antigua revisión, será eliminada de la base de datos y " +"no podrá ser recuperada." + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:8 +msgid "Delete Revision" +msgstr "Eliminar Revisión" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:3 +#, fuzzy +msgid "" +"If you delete this documentation resource, it will be removed from the " +"database with all the associated revisions \n" +"and you will not be able to recover it. Any documentation " +"pages that reference this resource,\n" +"will no longer be able to render it, but won't be deleted." +msgstr "" +"Si elimina esta página de documentación, será eliminada de la base de datos " +"con todas las revisiones relacionadas y no será capaz de recuperarla." +"" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:8 +#, fuzzy +msgid "Delete Resource" +msgstr "Eliminar Revisión" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:10 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:8 +#, fuzzy +msgid "File size" +msgstr "Tamaño del archivo" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:9 +#: IDF/Views/Wiki.php:101 +#, fuzzy +msgid "MIME type" +msgstr "tipo" + +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:3 +#, fuzzy, php-format +msgid "" +"You are looking at an old revision (%%oldrev.summary%%) of the " +"resource \n" +"%%resource.title%%. This revision was created by " +"%%submitter%%." +msgstr "" +"Está viendo una revisión antigua (%%oldrev.summary%%) de la " +"página \n" +"%%page.title%%. Esta revisión fue creada por " +"%%submitter%%." + +#: IDF/gettexttemplates/idf/wiki/edit-info.html.php:3 +#, fuzzy, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

The content of the page can use the Markdown syntax with the Extra extension.

\n" +"

Website addresses are automatically linked and you can link to another " +"page in the documentation using double square brackets like that " +"[[AnotherPage]].

\n" +"

If you want to embed uploaded resources, use the [[!ResourceName]] syntax for that. This is described more in detail in the FAQ.

\n" +"

To directly include a file content from the repository, embrace its path " +"with triple square brackets: [[[my/file.txt]]].

\n" +msgstr "" +"\n" +"

Instrucciones:

\n" +"

El contenido de la página puede usar sintaxis de " +"Marcado con la extensión Extra.

\n" +"

Las direcciones Web se enlazan automáticamente y se puede vincular con " +"otras páginas de la documentación usando corchetes dobles como: " +"[[OtraPágina]].

\n" +"

Para incluir directamente el contenido de un fichero del repositorio, " +"rodee la ruta con corchetes triples como: [[[ruta/al/fichero.txt]]].

\n" + +#: IDF/gettexttemplates/idf/wiki/feedfragment-resource.xml.php:4 +#, fuzzy +msgid "Initial creation" +msgstr "Creación de la página inicial" + +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:3 +#, php-format +msgid "See the deprecated pages." +msgstr "Ver páginas en desuso." + +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:5 +msgid "Number of pages:" +msgstr "Número de páginas:" + +#: IDF/gettexttemplates/idf/wiki/listResources.html.php:4 +#, fuzzy +msgid "Number of resources:" +msgstr "Número de usuarios:" + +#: IDF/gettexttemplates/idf/wiki/search.html.php:4 +msgid "Pages found:" +msgstr "Páginas encontradas:" + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:3 +msgid "The form contains some errors. Please correct them to update the page." +msgstr "" +"El formulario contiene algunos errores. Por favor, corríjalos para " +"actualizar la página." + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:6 +msgid "Update Page" +msgstr "Actualizar Página" + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:10 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:11 +msgid "Delete this page" +msgstr "Eliminar esta página" + +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:4 +#, fuzzy +msgid "Update Resource" +msgstr "Actualizar usuario" + +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:8 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:9 +#, fuzzy +msgid "Delete this resource" +msgstr "Eliminar esta revisión" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:3 +msgid "" +"Attention! This page is marked as deprecated, \n" +"use it as reference only if you are sure you need these specific information." +msgstr "" +"¡Atención! Esta página está marcada como obsoleta,\n" +"úsala como referencia solamente si está seguro de que usted necesita " +"específicamente esta información ." + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:5 +#, php-format +msgid "" +"You are looking at an old revision of the page \n" +"%%page.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" +"Está viendo una revisión antigua de la página \n" +"%%page.title%%. Esta revisión fue creada por " +"%%submitter%%." + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:10 +msgid "Table of Content" +msgstr "Tabla de Contenido" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:13 +msgid "Delete this revision" +msgstr "Eliminar esta revisión" + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:3 +#, fuzzy, php-format +msgid "" +"You are looking at an old revision of the resource \n" +"%%resource.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" +"Está viendo una revisión antigua de la página \n" +"%%page.title%%. Esta revisión fue creada por " +"%%submitter%%." + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:14 +#, fuzzy +msgid "Page Usage" +msgstr "NombreDeLaPágina" + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:15 +msgid "This resource is not used on any pages yet." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:3 +msgid "A new documentation page has been created:" +msgstr "Una nueva página de documentación ha sido creada:" + +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:14 +msgid "Documentation page:" +msgstr "Página documentación:" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:3 +msgid "The following documentation page has been updated:" +msgstr "La siguiente página de documentación se ha actualizado:" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:7 +msgid "Updated by:" +msgstr "Actualizado por:" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:13 +msgid "New content:" +msgstr "Nuevo contenido:" + +#: IDF/Issue.php:76 +msgid "owner" +msgstr "propietario" + +#: IDF/Issue.php:84 IDF/Wiki/Page.php:86 +msgid "interested users" +msgstr "usuarios interesados" + +#: IDF/Issue.php:85 +msgid "" +"Interested users will get an email notification when the issue is changed." +msgstr "" +"Los usuarios interesados recibirán una notificación por correo electrónico " +"cuando el ticket cambie." + +#: IDF/Issue.php:92 IDF/Project.php:94 IDF/Review.php:95 IDF/Upload.php:99 +#: IDF/Wiki/Page.php:94 +msgid "labels" +msgstr "etiquetas" + +#: IDF/Issue.php:111 IDF/IssueFile.php:102 IDF/Review.php:114 +#: IDF/Upload.php:118 IDF/Wiki/Page.php:106 IDF/Wiki/Resource.php:101 +msgid "modification date" +msgstr "fecha de modificación" + +#: IDF/Issue.php:212 IDF/IssueComment.php:143 +#, php-format +msgid "" +"Issue %3$d, %4$s" +msgstr "" +"Ticket %3$d, %4$s" + +#: IDF/Issue.php:214 +#, fuzzy, php-format +msgid "Creation of issue %3$d, by %4$s" +msgstr "Creación del ticket %d, por %s" + +#: IDF/Issue.php:224 +#, fuzzy, php-format +msgid "%1$s: Issue %2$d created - %3$s" +msgstr "%s: Ticket %d creado - %s" + +#: IDF/Issue.php:307 +#, fuzzy, php-format +msgid "Issue %1$s - %2$s (%3$s)" +msgstr "Ticket %s - %s (%s)" + +#: IDF/Issue.php:311 +#, fuzzy, php-format +msgid "Updated Issue %1$s - %2$s (%3$s)" +msgstr "Ticket actualizado %s - %s (%s)" + +#: IDF/IssueComment.php:51 IDF/IssueRelation.php:47 +msgid "issue" +msgstr "ticket" + +#: IDF/IssueComment.php:58 IDF/IssueFile.php:49 IDF/Review/Comment.php:62 +#: IDF/Review/FileComment.php:49 IDF/Review/FileComment.php:69 +msgid "comment" +msgstr "comentario" + +#: IDF/IssueComment.php:72 IDF/Review/Comment.php:75 IDF/Upload.php:63 +#: IDF/Wiki/PageRevision.php:85 +msgid "changes" +msgstr "cambios" + +#: IDF/IssueComment.php:73 +msgid "Serialized array of the changes in the issue." +msgstr "Vector serializado con los cambios en los tickets." + +#: IDF/IssueComment.php:180 +#, fuzzy, php-format +msgid "Comment on issue %3$d, by %4$s" +msgstr "Comentario del ticket %d, por %s" + +#: IDF/IssueComment.php:191 +#, fuzzy, php-format +msgid "%1$s: Comment on issue %2$d - %3$s" +msgstr "%s: Comentario del ticket %d - %s" + +#: IDF/IssueFile.php:64 +msgid "file name" +msgstr "nombre del archivo" + +#: IDF/IssueFile.php:70 +msgid "the file" +msgstr "archivo" + +#: IDF/IssueFile.php:76 +msgid "file size" +msgstr "Tamaño del archivo" + +#: IDF/IssueFile.php:84 +msgid "type" +msgstr "tipo" + +#: IDF/IssueFile.php:86 +msgid "Image" +msgstr "Imagen" + +#: IDF/IssueFile.php:87 +msgid "Other" +msgstr "Otros" + +#: IDF/IssueRelation.php:54 +msgid "verb" +msgstr "" + +#: IDF/IssueRelation.php:61 +msgid "other issue" +msgstr "" + +#: IDF/Key.php:55 +msgid "public key" +msgstr "clave pública" + +#: IDF/Key.php:90 +msgid "Invalid or unknown key data detected." +msgstr "Detectada clave de datos no válida o desconocida." + +#: IDF/Plugin/SyncMercurial.php:78 IDF/Plugin/SyncSvn.php:81 +#, php-format +msgid "The repository %s already exists." +msgstr "El repositorio %s ya existe." + +#: IDF/Plugin/SyncMercurial.php:142 +#, php-format +msgid "%s does not exist or is not writable." +msgstr "%s no existe o no se puede escribir." + +#: IDF/Plugin/SyncMonotone.php:107 IDF/Plugin/SyncMonotone.php:492 +msgid "\"mtn_repositories\" must be defined in your configuration file" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:114 IDF/Plugin/SyncMonotone.php:482 +msgid "\"mtn_usher_conf\" does not exist or is not writable" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:121 +#, php-format +msgid "Could not find mtn-post-push script \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:155 +#, php-format +msgid "The configuration file \"%s\" is missing" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:164 +#, php-format +msgid "The project path \"%s\" already exists" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:170 +#, php-format +msgid "The project path \"%s\" could not be created" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:208 +#, php-format +msgid "The key directory \"%s\" could not be created" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:227 +#, php-format +msgid "Could not parse key information: %s" +msgstr "No se puede examinar la información de la clave: %s" + +#: IDF/Plugin/SyncMonotone.php:265 +#, php-format +msgid "Could not create configuration directory \"%s\"" +msgstr "No se pudo crear el directorio de configuración \"%s\"" + +#: IDF/Plugin/SyncMonotone.php:275 +#, php-format +msgid "Could not create symlink for configuration file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:293 +#, php-format +msgid "Could not write configuration file \"%s\"" +msgstr "No se pudo escribir el archivo de configuración \"%s\"" + +#: IDF/Plugin/SyncMonotone.php:309 IDF/Plugin/SyncMonotone.php:525 +#, fuzzy, php-format +msgid "Could not parse usher configuration in \"%1$s\": %2$s" +msgstr "No se puede examinar la configuración usher en \"%s\": %s" + +#: IDF/Plugin/SyncMonotone.php:320 +#, php-format +msgid "usher configuration already contains a server entry named \"%s\"" +msgstr "" +"La configuración usher ya contiene una entrada para el servidor llamada \"%s" +"\"" + +#: IDF/Plugin/SyncMonotone.php:345 IDF/Plugin/SyncMonotone.php:546 +#, php-format +msgid "Could not write usher configuration file \"%s\"" +msgstr "No se puede escribir el fichero de configuración usher \"%s\"" + +#: IDF/Plugin/SyncMonotone.php:395 +#, php-format +msgid "Could not write write-permissions file \"%s\"" +msgstr "No se pudo escribir el fichero write-permissions \"%s\"" + +#: IDF/Plugin/SyncMonotone.php:420 +#, php-format +msgid "Could not write read-permissions file \"%s\"" +msgstr "No se pudo escribir el fichero read-permissions \"%s\"" + +#: IDF/Plugin/SyncMonotone.php:438 +#, php-format +msgid "Could not remove symlink \"%s\"" +msgstr "No se puede eliminar el enlace simbólico \"%s\"" + +#: IDF/Plugin/SyncMonotone.php:446 +#, php-format +msgid "Could not create symlink \"%s\"" +msgstr "No se pudo crear el enlace simbólico \"%s\"" + +#: IDF/Plugin/SyncMonotone.php:500 +#, php-format +msgid "One or more paths underneath %s could not be deleted" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:512 +#, php-format +msgid "Could not delete client private key \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:599 IDF/Plugin/SyncMonotone.php:718 +#, fuzzy, php-format +msgid "Could not parse read-permissions for project \"%1$s\": %2$s" +msgstr "No se pudo analizar read-permissions para el proyecto \"%s\": %s" + +#: IDF/Plugin/SyncMonotone.php:643 IDF/Plugin/SyncMonotone.php:741 +#, php-format +msgid "Could not write read-permissions for project \"%s\"" +msgstr "No se pudo escribir read-permissions para el proyecto \"%s\"" + +#: IDF/Plugin/SyncMonotone.php:657 IDF/Plugin/SyncMonotone.php:760 +#, php-format +msgid "Could not write write-permissions file for project \"%s\"" +msgstr "" +"No se pudo escribir el fichero write-permissions para el proyecto \"%s\"" + +#: IDF/Plugin/SyncMonotone.php:813 +msgid "\"mtn_repositories\" must be defined in your configuration file." +msgstr "\"mtn_repositories\" debe definirse en el fichero de configuración." + +#: IDF/Plugin/SyncMonotone.php:820 +#, php-format +msgid "The project path %s does not exists." +msgstr "La ruta del proyecto %s no existe." + +#: IDF/Plugin/SyncMonotone.php:838 +#, php-format +msgid "The command \"%s\" could not be executed." +msgstr "El comando \"%s\" no se pudo ejecutar." + +#: IDF/Project.php:62 IDF/Tag.php:66 +msgid "name" +msgstr "nombre" + +#: IDF/Project.php:69 +msgid "short name" +msgstr "nombre corto" + +#: IDF/Project.php:70 +#, fuzzy +msgid "" +"Used in the URL to access the project, must be short with only letters and " +"numbers." +msgstr "" +"Se utiliza en la ruta de acceso al proyecto, debe ser corta, con letras y " +"números sólo ." + +#: IDF/Project.php:78 +msgid "short description" +msgstr "descripción corta" + +#: IDF/Project.php:86 IDF/Review/Patch.php:74 +msgid "description" +msgstr "descripción" + +#: IDF/Project.php:87 +#, fuzzy +msgid "The description can be extended using the Markdown syntax." +msgstr "La descripción se puede extender mediante la sintaxis de marcado." + +#: IDF/Project.php:100 +msgid "private" +msgstr "privado" + +#: IDF/Project.php:108 +msgid "current project activity" +msgstr "" + +#: IDF/Project.php:159 +#, php-format +msgid "Project \"%s\" not found." +msgstr "Proyecto \"%s\" no encontrado." + +#: IDF/ProjectActivity.php:56 +#, fuzzy +msgid "date" +msgstr "Actualizado" + +#: IDF/Review/Comment.php:55 IDF/Review/Patch.php:80 +msgid "patch" +msgstr "parche" + +#: IDF/Review/Comment.php:83 +msgid "vote" +msgstr "voto" + +#: IDF/Review/Comment.php:139 IDF/Review/Patch.php:151 +#, php-format +msgid "" +"Review %3$d, %4$s" +msgstr "" +"Revisión %3$d, " +"%4$s" + +#: IDF/Review/Comment.php:141 +#, fuzzy, php-format +msgid "Update of review %3$d, by %4$s" +msgstr "" +"Actualización de revisión %d, por %s" + +#: IDF/Review/Comment.php:151 +#, fuzzy, php-format +msgid "%1$s: Updated review %2$d - %3$s" +msgstr "%s: Revisión Actualizada %d - %s" + +#: IDF/Review/Comment.php:222 +#, fuzzy, php-format +msgid "Updated Code Review %1$s - %2$s (%3$s)" +msgstr "Revisión de código Actualizada %s - %s (%s)" + +#: IDF/Review/Patch.php:52 +msgid "review" +msgstr "revisión" + +#: IDF/Review/Patch.php:67 +msgid "commit" +msgstr "commit" + +#: IDF/Review/Patch.php:153 +#, fuzzy, php-format +msgid "Creation of review %3$d, by %4$s" +msgstr "Creación de revisión %d, por %s" + +#: IDF/Review/Patch.php:163 +#, fuzzy, php-format +msgid "%1$s: Creation of Review %2$d - %3$s" +msgstr "%s: Creación de Revisión %d - %s" + +#: IDF/Review/Patch.php:208 +#, fuzzy, php-format +msgid "New Code Review %1$s - %2$s (%3$s)" +msgstr "Nueva Revisión de Código %s - %s (%s)" + +#: IDF/Scm/Git.php:309 IDF/Scm/Mercurial.php:199 +#, php-format +msgid "Folder %1$s not found in commit %2$s." +msgstr "Directorio %1$s no encontrado in commit %2$s." + +#: IDF/Scm/Git.php:433 IDF/Scm/Mercurial.php:216 +#, php-format +msgid "Not a valid tree: %s." +msgstr "No es un árbol válido: %s." + +#: IDF/Scm/Monotone/Stdio.php:81 +msgid "Monotone client key name or hash not in project conf." +msgstr "" +"El nombre clave del cliente Monotone o el hash no está en la configuración " +"del proyecto." + +#: IDF/Scm/Monotone/Stdio.php:89 +#, php-format +msgid "The key directory %s could not be created." +msgstr "El directorio clave %s no puede ser creado." + +#: IDF/Scm/Monotone/Stdio.php:100 +#, php-format +msgid "Could not write client key \"%s\"" +msgstr "No se pudo escribir la clave del cliente \"%s\"" + +#: IDF/Search/Occ.php:33 +#, fuzzy +msgid "occurrence" +msgstr "ocurrencia" + +#: IDF/Search/Occ.php:49 +msgid "word" +msgstr "palabra" + +#: IDF/Search/Occ.php:75 +#, fuzzy +msgid "occurrences" +msgstr "ocurrencias" + +#: IDF/Search/Occ.php:81 +#, fuzzy +msgid "ponderated occurrence" +msgstr "ocurrencia ponderada" + +#: IDF/Tag.php:59 +msgid "tag class" +msgstr "etiquetas de clase" + +#: IDF/Tag.php:60 +msgid "The class of the tag." +msgstr "Clase de la etiqueta." + +#: IDF/Tag.php:73 +msgid "lcname" +msgstr "lcname" + +#: IDF/Tag.php:74 +msgid "Lower case version of the name for fast searching." +msgstr "Versión del nombre en minúscula para búsqueda rápida." + +#: IDF/Template/Markdown.php:84 +msgid "Create this documentation page" +msgstr "Crear esta página de documentación" + +#: IDF/Template/Markdown.php:97 +msgid "You are not allowed to access the wiki." +msgstr "" + +#: IDF/Template/Markdown.php:106 +#, fuzzy +msgid "The wiki resource has not been found." +msgstr "El proyecto ha sido actualizado." + +#: IDF/Template/Markdown.php:113 +msgid "The wiki resource has not been found. Create it!" +msgstr "" + +#: IDF/Template/Markdown.php:146 +#, fuzzy +msgid "This revision of the resource is no longer available." +msgstr "Este proyecto no está disponible." + +#: IDF/Template/ShowUser.php:51 +msgid "Anonymous" +msgstr "Anónimo" + +#: IDF/Template/ShowUser.php:54 +msgid "Me" +msgstr "Yo" + +#: IDF/Timeline/Paginator.php:49 +msgid "Today" +msgstr "Hoy" + +#: IDF/Upload.php:70 +msgid "file" +msgstr "archivo" + +#: IDF/Upload.php:71 +msgid "The path is relative to the upload path." +msgstr "La ruta es relativa al directorio de subidas." + +#: IDF/Upload.php:78 IDF/Wiki/ResourceRevision.php:71 +msgid "file size in bytes" +msgstr "tamaño del archivo en bytes" + +#: IDF/Upload.php:84 +msgid "MD5" +msgstr "" + +#: IDF/Upload.php:106 +msgid "number of downloads" +msgstr "número de descargas" + +#: IDF/Upload.php:201 +#, php-format +msgid "Download %2$d, %3$s" +msgstr "Descarga %2$d, %3$s" + +#: IDF/Upload.php:204 +#, fuzzy, php-format +msgid "Addition of download %2$d, by %3$s" +msgstr "Agregada la descarga %d, por %s" + +#: IDF/Upload.php:214 +#, fuzzy, php-format +msgid "%1$s: Download %2$d added - %3$s" +msgstr "%s: Descarga %d agregada - %s" + +#: IDF/Upload.php:301 +#, fuzzy, php-format +msgid "New download - %1$s (%2$s)" +msgstr "Nueva descarga - %s (%s)" + +#: IDF/Upload.php:305 +#, fuzzy, php-format +msgid "Updated download - %1$s (%2$s)" +msgstr "Nueva descarga - %s (%s)" + +#: IDF/Views/Admin.php:47 +#, fuzzy +msgid "The forge configuration has been saved." +msgstr "La configuración de las descargas se ha guardado." + +#: IDF/Views/Admin.php:80 +msgid "This table shows the projects in the forge." +msgstr "Esta tabla muestra los proyectos de la forja." + +#: IDF/Views/Admin.php:85 +msgid "Short Name" +msgstr "Nombre corto" + +#: IDF/Views/Admin.php:87 +msgid "Repository Size" +msgstr "Tamaño del Repositorio" + +#: IDF/Views/Admin.php:93 +msgid "No projects were found." +msgstr "No se encontraron proyectos." + +#: IDF/Views/Admin.php:116 +#, fuzzy +msgid "The label configuration has been saved." +msgstr "La configuración de las descargas se ha guardado." + +#: IDF/Views/Admin.php:147 IDF/Views/Admin.php:314 IDF/Views/Wiki.php:484 +#: IDF/Views/Wiki.php:536 +#, php-format +msgid "Update %s" +msgstr "Actualizar %s" + +#: IDF/Views/Admin.php:155 IDF/Views/Project.php:304 +msgid "The project has been updated." +msgstr "El proyecto ha sido actualizado." + +#: IDF/Views/Admin.php:192 +msgid "The project has been created." +msgstr "El proyecto ha sido creado." + +#: IDF/Views/Admin.php:223 +#, php-format +msgid "Delete %s Project" +msgstr "Eliminar Proyecto %s" + +#: IDF/Views/Admin.php:230 +msgid "The project has been deleted." +msgstr "El proyecto ha sido eliminado." + +#: IDF/Views/Admin.php:260 +msgid "Not Validated User List" +msgstr "Lista de usuarios no validados" + +#: IDF/Views/Admin.php:268 +msgid "This table shows the users in the forge." +msgstr "Esta tabla muestra los usuarios de la forja." + +#: IDF/Views/Admin.php:272 +msgid "login" +msgstr "nombre de usuario" + +#: IDF/Views/Admin.php:275 +msgid "Admin" +msgstr "Admin" + +#: IDF/Views/Admin.php:277 +msgid "Last Login" +msgstr "Último inicio de sesión" + +#: IDF/Views/Admin.php:284 +msgid "No users were found." +msgstr "No se han encontrado usuarios." + +#: IDF/Views/Admin.php:321 +msgid "You do not have the rights to update this user." +msgstr "No tiene permisos para actualizar este usuario." + +#: IDF/Views/Admin.php:339 +msgid "The user has been updated." +msgstr "El usuario se ha actualizado." + +#: IDF/Views/Admin.php:372 +#, php-format +msgid "The user %s has been created." +msgstr "El usuario %s se ha creado." + +#: IDF/Views/Admin.php:379 +msgid "Add User" +msgstr "Agregar usuario" + +#: IDF/Views/Admin.php:395 +msgid "Usher management" +msgstr "Configuración Usher" + +#: IDF/Views/Admin.php:432 +msgid "Usher configuration has been reloaded" +msgstr "La configuración Usher ha sido recargada." + +#: IDF/Views/Admin.php:436 +msgid "Usher has been shut down" +msgstr "Usher ha sido apagado." + +#: IDF/Views/Admin.php:441 +msgid "Usher has been started up" +msgstr "Usher ha sido arrancado." + +#: IDF/Views/Admin.php:479 +#, php-format +msgid "The server \"%s\" has been started" +msgstr "El servidor \"%s\" se ha iniciado" + +#: IDF/Views/Admin.php:483 +#, php-format +msgid "The server \"%s\" has been stopped" +msgstr "El servidor \"%s\" ha sido detenido" + +#: IDF/Views/Admin.php:488 +#, php-format +msgid "The server \"%s\" has been killed" +msgstr "El servidor \"%s\" ha sido parado" + +#: IDF/Views/Admin.php:508 +#, php-format +msgid "Open connections for \"%s\"" +msgstr "Conexiones abiertas de \"%s\"" + +#: IDF/Views/Admin.php:513 +#, php-format +msgid "no connections for server \"%s\"" +msgstr "Ninguna conexión para el servidor \"%s\"" + +#: IDF/Views/Admin.php:534 +msgid "Yes" +msgstr "Sí" + +#: IDF/Views/Admin.php:534 +msgid "No" +msgstr "No" + +#: IDF/Views/Download.php:45 +#, php-format +msgid "%s Downloads" +msgstr "%s Descargas" + +#: IDF/Views/Download.php:51 +msgid "This table shows the files to download." +msgstr "Esta tabla muestra los archivos para descargar." + +#: IDF/Views/Download.php:67 IDF/Views/Download.php:349 +msgid "Uploaded" +msgstr "Subido" + +#: IDF/Views/Download.php:71 IDF/Views/Download.php:353 +msgid "No downloads were found." +msgstr "No se encontraron descargas." + +#: IDF/Views/Download.php:94 +#, php-format +msgid "Download %s" +msgstr "Descargar %s" + +#: IDF/Views/Download.php:111 +#, php-format +msgid "The file %2$s has been updated." +msgstr "El archivo %2$s ha sido actualizado." + +#: IDF/Views/Download.php:144 +#, php-format +msgid "Delete Download %s" +msgstr "Eliminar Descarga %s" + +#: IDF/Views/Download.php:177 +msgid "The file has been deleted." +msgstr "El archivo ha sido eliminado." + +#: IDF/Views/Download.php:244 +#, php-format +msgid "The file has been uploaded." +msgstr "El archivo ha sido subido." + +#: IDF/Views/Download.php:271 +#, fuzzy +msgid "New Downloads from Archive" +msgstr "Nueva descarga" + +#: IDF/Views/Download.php:278 +#, fuzzy +msgid "The archive has been uploaded and processed." +msgstr "El proyecto ha sido actualizado." + +#: IDF/Views/Download.php:331 +#, php-format +msgid "%1$s Downloads with Label %2$s" +msgstr "%1$s Descargas con Etiqueta %2$s" + +#: IDF/Views/Download.php:341 +#, php-format +msgid "This table shows the downloads with label %s." +msgstr "Esta tabla muestra las descargas con la etiqueta %s." + +#: IDF/Views/Issue.php:41 +#, php-format +msgid "%s Open Issues" +msgstr "%s Tickets abiertos" + +#: IDF/Views/Issue.php:51 IDF/Views/Issue.php:382 IDF/Views/User.php:75 +msgid "This table shows the open issues." +msgstr "Esta tabla muestra los tickets abiertos." + +#: IDF/Views/Issue.php:61 IDF/Views/Issue.php:220 IDF/Views/Issue.php:301 +#: IDF/Views/Issue.php:390 IDF/Views/Issue.php:542 IDF/Views/Issue.php:765 +#: IDF/Views/Issue.php:824 IDF/Views/Review.php:57 IDF/Views/User.php:81 +msgid "Id" +msgstr "Id" + +#: IDF/Views/Issue.php:64 IDF/Views/Issue.php:223 IDF/Views/Issue.php:305 +#: IDF/Views/Issue.php:393 IDF/Views/Issue.php:545 IDF/Views/Issue.php:768 +#: IDF/Views/Issue.php:827 IDF/Views/Review.php:60 IDF/Views/User.php:85 +msgid "Last Updated" +msgstr "Última actualización" + +#: IDF/Views/Issue.php:68 IDF/Views/Issue.php:227 IDF/Views/Issue.php:309 +#: IDF/Views/Issue.php:397 IDF/Views/Issue.php:549 IDF/Views/Issue.php:772 +#: IDF/Views/Issue.php:831 +msgid "No issues were found." +msgstr "No se han encontrado tickets." + +#: IDF/Views/Issue.php:113 +msgid "Not assigned" +msgstr "" + +#: IDF/Views/Issue.php:149 +#, php-format +msgid "Summary of tracked issues in %s." +msgstr "" + +#: IDF/Views/Issue.php:194 +#, php-format +msgid "Watch List: Closed Issues for %s" +msgstr "Lista de mantenimiento: Tickets Cerrados por %s" + +#: IDF/Views/Issue.php:195 +#, php-format +msgid "This table shows the closed issues in your watch list for %s project." +msgstr "" +"Esta tabla muestra los tickets cerrados en su lista de mantenimiento para el " +"proyecto %s." + +#: IDF/Views/Issue.php:200 +#, php-format +msgid "Watch List: Open Issues for %s" +msgstr "Lista mantenimiento: Tickets Abiertos por %s" + +#: IDF/Views/Issue.php:201 +#, php-format +msgid "This table shows the open issues in your watch list for %s project." +msgstr "" +"Esta tabla muestra los tickets abiertos en su lista de mantenimiento para el " +"proyecto %s." + +#: IDF/Views/Issue.php:277 +msgid "Watch List: Closed Issues" +msgstr "Lista mantenimiento: Tickets Cerrados" + +#: IDF/Views/Issue.php:278 +msgid "This table shows the closed issues in your watch list." +msgstr "Esta tabla muestra los tickets cerrados en su lista de mantenimiento." + +#: IDF/Views/Issue.php:283 +msgid "Watch List: Open Issues" +msgstr "Lista mantenimiento: Tickets Abiertos" + +#: IDF/Views/Issue.php:284 +msgid "This table shows the open issues in your watch list." +msgstr "Esta tabla muestra los tickets abiertos en su lista de mantenimiento." + +#: IDF/Views/Issue.php:303 IDF/Views/User.php:82 +msgid "Project" +msgstr "Proyecto" + +#: IDF/Views/Issue.php:344 +#, fuzzy, php-format +msgid "%1$s %2$s Submitted %3$s Issues" +msgstr "Tickets enviados:" + +#: IDF/Views/Issue.php:348 +#, php-format +msgid "%1$s %2$s Closed Submitted %3$s Issues" +msgstr "" + +#: IDF/Views/Issue.php:352 +#, fuzzy, php-format +msgid "%1$s %2$s Closed Working %3$s Issues" +msgstr "%s Tickets cerrados" + +#: IDF/Views/Issue.php:356 +#, php-format +msgid "%1$s %2$s Working %3$s Issues" +msgstr "" + +#: IDF/Views/Issue.php:417 +msgid "Submit a new issue" +msgstr "Enviar nuevo Ticket" + +#: IDF/Views/Issue.php:433 +#, fuzzy, php-format +msgid "Issue %2$d has been created." +msgstr "El Ticket %d ha sido creado." + +#: IDF/Views/Issue.php:490 +#, php-format +msgid "Search issues - %s" +msgstr "" + +#: IDF/Views/Issue.php:492 +#, php-format +msgid "Search closed issues - %s" +msgstr "" + +#: IDF/Views/Issue.php:539 +msgid "This table shows the found issues." +msgstr "Esta tabla muestra los tickets encontrados." + +#: IDF/Views/Issue.php:604 +#, fuzzy, php-format +msgid "Issue %2$d: %3$s" +msgstr "Ticket %d: %s" + +#: IDF/Views/Issue.php:628 +#, fuzzy, php-format +msgid "Issue %2$d has been updated." +msgstr "El Ticket %d ha sido actualizado." + +#: IDF/Views/Issue.php:718 +#, php-format +msgid "View %s" +msgstr "Ver %s" + +#: IDF/Views/Issue.php:745 +#, php-format +msgid "%s Closed Issues" +msgstr "%s Tickets cerrados" + +#: IDF/Views/Issue.php:755 +msgid "This table shows the closed issues." +msgstr "Esta tabla muestra los tickets cerrados." + +#: IDF/Views/Issue.php:798 +#, php-format +msgid "%1$s Issues with Label %2$s" +msgstr "%1$s Tickets con la Etiqueta %2$s" + +#: IDF/Views/Issue.php:801 +#, php-format +msgid "%1$s Closed Issues with Label %2$s" +msgstr "%1$s Tickets cerrados con la Etiqueta %2$s" + +#: IDF/Views/Issue.php:814 +#, php-format +msgid "This table shows the issues with label %s." +msgstr "Esta tabla muestra los tickets con la etiqueta %s." + +#: IDF/Views/Issue.php:937 +msgid "The issue has been removed from your watch list." +msgstr "El tickets se ha eliminado de su lista." + +#: IDF/Views/Issue.php:940 +msgid "The issue has been added to your watch list." +msgstr "El ticket ha sido añadido a su lista." + +#: IDF/Views/Issue.php:1037 +msgid "On your watch list." +msgstr "En su lista." + +#: IDF/Views/Project.php:95 +msgid "Issues and Comments" +msgstr "Tickets y Comentarios" + +#: IDF/Views/Project.php:99 +msgid "Documents" +msgstr "Documentos" + +#: IDF/Views/Project.php:101 +msgid "Reviews and Patches" +msgstr "Revisiones y parches" + +#: IDF/Views/Project.php:180 +msgid "This table shows the project updates." +msgstr "Esta tabla muestra las actualizaciones del proyecto." + +#: IDF/Views/Project.php:191 +msgid "Change" +msgstr "Cambios" + +#: IDF/Views/Project.php:195 +msgid "No changes were found." +msgstr "No se encontraron cambios." + +#: IDF/Views/Project.php:296 +#, php-format +msgid "%s Project Summary" +msgstr "Resumen del Proyecto %s" + +#: IDF/Views/Project.php:335 +#, php-format +msgid "%s Issue Tracking Configuration" +msgstr "Configuración de Seguimiento de Tickets %s" + +#: IDF/Views/Project.php:344 +msgid "The issue tracking configuration has been saved." +msgstr "La configuración de seguimiento de Tickets se ha guardado." + +#: IDF/Views/Project.php:381 +#, php-format +msgid "%s Downloads Configuration" +msgstr "Configuración de descargas %s" + +#: IDF/Views/Project.php:393 +msgid "The downloads configuration has been saved." +msgstr "La configuración de las descargas se ha guardado." + +#: IDF/Views/Project.php:428 +#, php-format +msgid "%s Documentation Configuration" +msgstr "Configuración de documentación %s" + +#: IDF/Views/Project.php:437 +msgid "The documentation configuration has been saved." +msgstr "La configuración de la documentación ha sido guardada." + +#: IDF/Views/Project.php:471 +#, php-format +msgid "%s Project Members" +msgstr "Miembros del Proyecto %s" + +#: IDF/Views/Project.php:480 +msgid "The project membership has been saved." +msgstr "Los miembros del proyecto se han guardado." + +#: IDF/Views/Project.php:503 +#, php-format +msgid "%s Tabs Access Rights" +msgstr "Pestaña de permisos de acceso %s " + +#: IDF/Views/Project.php:517 +#, fuzzy +msgid "" +"The project tabs access rights and notification settings have been saved." +msgstr "La pestaña de permisos de acceso del proyecto se ha guardado." + +#: IDF/Views/Project.php:566 +#, php-format +msgid "%s Source" +msgstr "Fuente %s" + +#: IDF/Views/Project.php:580 +msgid "The project source configuration has been saved." +msgstr "La configuración de la fuente del proyecto se ha guardado" + +#: IDF/Views/Review.php:41 +#, php-format +msgid "%s Code Reviews" +msgstr "Revisiones del Código %s" + +#: IDF/Views/Review.php:48 +msgid "This table shows the latest reviews." +msgstr "Esta tabla muestra las últimas revisiones." + +#: IDF/Views/Review.php:64 +msgid "No reviews were found." +msgstr "No se encontraron revisiones." + +#: IDF/Views/Review.php:94 +#, fuzzy, php-format +msgid "The code review %2$d has been created." +msgstr "El comentario del código %d ha sido creado." + +#: IDF/Views/Review.php:140 +#, fuzzy, php-format +msgid "Review %2$d: %3$s" +msgstr "Comentario %d: %s" + +#: IDF/Views/Review.php:160 +#, fuzzy, php-format +msgid "Your code review %2$d has been published." +msgstr "Tu comentario del código %d ha sido publicado." + +#: IDF/Views/Source.php:40 +#, php-format +msgid "%s Source Help" +msgstr "Ayuda de fuentes %s" + +#: IDF/Views/Source.php:58 +#, php-format +msgid "%s Invalid Revision" +msgstr "Revisión no válida %s " + +#: IDF/Views/Source.php:82 +#, php-format +msgid "%s Ambiguous Revision" +msgstr "Revisión ambigua %s" + +#: IDF/Views/Source.php:107 +#, php-format +msgid "%1$s %2$s Change Log" +msgstr "Cambios %2$s de %1$s" + +#: IDF/Views/Source.php:153 IDF/Views/Source.php:234 IDF/Views/Source.php:362 +#, php-format +msgid "%1$s %2$s Source Tree" +msgstr "Árbol de fuentes %2$s de %1$s" + +#: IDF/Views/Source.php:310 +#, php-format +msgid "%s Commit Details" +msgstr "Detalles del Commit %s" + +#: IDF/Views/Source.php:311 +#, fuzzy, php-format +msgid "%1$s Commit Details - %2$s" +msgstr "%s Detalles del Commit - %s" + +#: IDF/Views/User.php:59 +msgid "Your Dashboard - Working Issues" +msgstr "Tu Panel de Control - Tickets en Proceso" + +#: IDF/Views/User.php:62 +msgid "Your Dashboard - Submitted Issues" +msgstr "Tu Panel de Control - Tickets Enviados" + +#: IDF/Views/User.php:89 +msgid "No issues are assigned to you, yeah!" +msgstr "No te han asignado tickets, ¡Yeah!" + +#: IDF/Views/User.php:89 +msgid "All the issues you submitted are fixed, yeah!" +msgstr "Todos los tickets que enviastes han sido resueltos, ¡Yeah!" + +#: IDF/Views/User.php:121 +msgid "Your personal information has been updated." +msgstr "Tu información personal se ha actualizado." + +#: IDF/Views/User.php:133 +msgid "Your Account" +msgstr "Tu Cuenta" + +#: IDF/Views/User.php:157 +msgid "The public key has been deleted." +msgstr "La clave pública ha sido eliminada." + +#: IDF/Views/User.php:177 +msgid "The address has been deleted." +msgstr "La dirección ha sido eliminada." + +#: IDF/Views/User.php:200 +msgid "Confirm The Email Change" +msgstr "Confirmar el cambio de correo electrónico" + +#: IDF/Views/User.php:232 +#, php-format +msgid "Your new email address \"%s\" has been validated. Thank you!" +msgstr "" +"Tu nueva dirección de correo electrónico \"%s\" ha sido validada. ¡Gracias!" + +#: IDF/Views/Wiki.php:41 +#, php-format +msgid "%s Documentation" +msgstr "%s Documentación" + +#: IDF/Views/Wiki.php:48 +msgid "This table shows the documentation pages." +msgstr "Esta tabla muestra las páginas de documentación." + +#: IDF/Views/Wiki.php:61 IDF/Views/Wiki.php:144 IDF/Views/Wiki.php:185 +msgid "Page Title" +msgstr "Título de la página" + +#: IDF/Views/Wiki.php:63 IDF/Views/Wiki.php:103 IDF/Views/Wiki.php:146 +#: IDF/Views/Wiki.php:187 +msgid "Updated" +msgstr "Actualizado" + +#: IDF/Views/Wiki.php:67 IDF/Views/Wiki.php:191 +msgid "No documentation pages were found." +msgstr "No se encontraron páginas de documentación." + +#: IDF/Views/Wiki.php:88 +#, fuzzy, php-format +msgid "%s Documentation Resources" +msgstr "%s Documentación" + +#: IDF/Views/Wiki.php:94 +#, fuzzy +msgid "This table shows the resources that can be used on documentation pages." +msgstr "Esta tabla muestra las páginas de documentación." + +#: IDF/Views/Wiki.php:100 +#, fuzzy +msgid "Resource Title" +msgstr "Árbol de las fuentes" + +#: IDF/Views/Wiki.php:107 +#, fuzzy +msgid "No resources were found." +msgstr "No se han encontrado tickets." + +#: IDF/Views/Wiki.php:128 +#, php-format +msgid "Documentation Search - %s" +msgstr "Búsqueda de documentación - %s" + +#: IDF/Views/Wiki.php:139 +msgid "This table shows the pages found." +msgstr "Esta tabla muestra las páginas encontradas." + +#: IDF/Views/Wiki.php:150 +msgid "No pages were found." +msgstr "No se encontraron páginas." + +#: IDF/Views/Wiki.php:169 +#, php-format +msgid "%1$s Documentation Pages with Label %2$s" +msgstr "%1$s Páginas de documentación con la etiqueta %2$s" + +#: IDF/Views/Wiki.php:179 +#, php-format +msgid "This table shows the documentation pages with label %s." +msgstr "Esta tabla muestra las páginas de documentación con la etiqueta %s." + +#: IDF/Views/Wiki.php:222 +#, fuzzy, php-format +msgid "The page %2$s has been created." +msgstr "La página %s se ha creado." + +#: IDF/Views/Wiki.php:265 +#, fuzzy, php-format +msgid "The resource %2$s has been created." +msgstr "La página %s se ha creado." + +#: IDF/Views/Wiki.php:409 IDF/Views/Wiki.php:448 +msgid "The old revision has been deleted." +msgstr "La antigua revisión ha sido eliminado." + +#: IDF/Views/Wiki.php:415 IDF/Views/Wiki.php:454 +#, php-format +msgid "Delete Old Revision of %s" +msgstr "Eliminar Antigua revisión de %s" + +#: IDF/Views/Wiki.php:496 +#, fuzzy, php-format +msgid "The page %2$s has been updated." +msgstr "La página %s se ha actualizado." + +#: IDF/Views/Wiki.php:548 +#, fuzzy, php-format +msgid "The resource %2$s has been updated." +msgstr "El archivo %2$s ha sido actualizado." + +#: IDF/Views/Wiki.php:583 +msgid "The documentation page has been deleted." +msgstr "La página de documentación se ha eliminado." + +#: IDF/Views/Wiki.php:591 +#, php-format +msgid "Delete Page %s" +msgstr "Eliminar Página %s" + +#: IDF/Views/Wiki.php:623 +#, fuzzy +msgid "The documentation resource has been deleted." +msgstr "La página de documentación se ha eliminado." + +#: IDF/Views/Wiki.php:631 +#, fuzzy, php-format +msgid "Delete Resource %s" +msgstr "Eliminar Página %s" + +#: IDF/Views.php:173 IDF/Views.php:199 +msgid "Confirm Your Account Creation" +msgstr "Confirma la creación de tu cuenta" + +#: IDF/Views.php:219 +msgid "Welcome! You can now participate in the life of your project of choice." +msgstr "¡Bienvenido! Ahora puedes participar en el proyecto elegido." + +#: IDF/Views.php:245 IDF/Views.php:269 IDF/Views.php:310 +msgid "Password Recovery" +msgstr "Recuperación de la contraseña" + +#: IDF/Views.php:289 +msgid "" +"Welcome back! Next time, you can use your broswer options to remember the " +"password." +msgstr "" +"¡Bienvenido de nuevo! La próxima vez, puede utilizar la opcione de tu " +"navegador para recordar la contraseña." + +#: IDF/Views.php:331 +msgid "Here to Help You!" +msgstr "¡Aquí para ayudarte!" + +#: IDF/Views.php:347 +msgid "InDefero Upload Archive Format" +msgstr "" + +#: IDF/Views.php:363 +msgid "InDefero API (Application Programming Interface)" +msgstr "InDefero API (Interfaz de Programación de la Aplicación)" + +#: IDF/Wiki/Page.php:62 IDF/Wiki/Resource.php:64 +msgid "title" +msgstr "título" + +#: IDF/Wiki/Page.php:63 +msgid "" +"The title of the page must only contain letters, digits or the dash " +"character. For example: My-new-Wiki-Page." +msgstr "" +"El título de la página sólo puede contener letras, dígitos o el carácter de " +"guión. Por ejemplo: Mi-nueva-Página-Wiki." + +#: IDF/Wiki/Page.php:71 +msgid "A one line description of the page content." +msgstr "Una línea que describa el contenido de la página." + +#: IDF/Wiki/Page.php:196 IDF/Wiki/PageRevision.php:196 +#, php-format +msgid "%2$s, %3$s" +msgstr "%2$s, %3$s" + +#: IDF/Wiki/Page.php:198 +#, fuzzy, php-format +msgid "Creation of page %2$s, by %3$s" +msgstr "Creación de la página %s, por %s" + +#: IDF/Wiki/Page.php:208 +#, fuzzy, php-format +msgid "%1$s: Documentation page %2$s added - %3$s" +msgstr "%s: Página de documentación %s añadida - %s" + +#: IDF/Wiki/PageRevision.php:48 +msgid "page" +msgstr "página" + +#: IDF/Wiki/PageRevision.php:66 IDF/Wiki/ResourceRevision.php:64 +msgid "A one line description of the changes." +msgstr "Una pequeña descripción de los cambios realizados." + +#: IDF/Wiki/PageRevision.php:72 +msgid "content" +msgstr "contenido" + +#: IDF/Wiki/PageRevision.php:218 IDF/Wiki/ResourceRevision.php:311 +#, fuzzy, php-format +msgid "Change of %2$s, by %3$s" +msgstr "Cambio de %s, por %s" + +#: IDF/Wiki/PageRevision.php:231 +#, fuzzy, php-format +msgid "%1$s: Documentation page %2$s updated - %3$s" +msgstr "%s: Página de documentación %s actualizada - %s" + +#: IDF/Wiki/PageRevision.php:293 +#, fuzzy, php-format +msgid "New Documentation Page %1$s - %2$s (%3$s)" +msgstr "Nueva página de documentación %s - %s (%s)" + +#: IDF/Wiki/PageRevision.php:297 +#, fuzzy, php-format +msgid "Documentation Page Changed %1$s - %2$s (%3$s)" +msgstr "Cambios página de documentación %s - %s (%s)" + +#: IDF/Wiki/Resource.php:65 +#, fuzzy +msgid "" +"The title of the resource must only contain letters, digits, dots or the " +"dash character. For example: my-resource.png." +msgstr "" +"El título de la página sólo puede contener letras, dígitos o el carácter de " +"guión. Por ejemplo: Mi-nueva-Página-Wiki." + +#: IDF/Wiki/Resource.php:72 +msgid "MIME media type" +msgstr "" + +#: IDF/Wiki/Resource.php:73 +msgid "The MIME media type of the resource." +msgstr "" + +#: IDF/Wiki/Resource.php:81 +#, fuzzy +msgid "A one line description of the resource." +msgstr "Una línea de descripción del proyecto." + +#: IDF/Wiki/Resource.php:176 IDF/Wiki/ResourceRevision.php:308 +#, fuzzy, php-format +msgid "%2$s, %3$s" +msgstr "%2$s, %3$s" + +#: IDF/Wiki/Resource.php:178 +#, fuzzy, php-format +msgid "Creation of resource %2$s, by %3$s" +msgstr "Creación de la página %s, por %s" + +#: IDF/Wiki/Resource.php:188 +#, fuzzy, php-format +msgid "%1$s: Documentation resource %2$s added - %3$s" +msgstr "%s: Página de documentación %s añadida - %s" + +#: IDF/Wiki/ResourceRevision.php:47 +#, fuzzy +msgid "resource" +msgstr "Fuentes" + +#: IDF/Wiki/ResourceRevision.php:78 +#, fuzzy +msgid "File extension" +msgstr "Diferencias de archivos" + +#: IDF/Wiki/ResourceRevision.php:79 +msgid "The file extension of the uploaded resource." +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:94 +msgid "page usage" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:116 +#, php-format +msgid "id %d: %s" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:263 +#, fuzzy, php-format +msgid "Download (%s)" +msgstr "Descargar %s" + +#: IDF/Wiki/ResourceRevision.php:270 +msgid "View resource details" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:324 +#, fuzzy, php-format +msgid "%1$s: Documentation resource %2$s updated - %3$s" +msgstr "%s: Página de documentación %s actualizada - %s" + +#~ msgid "" +#~ "The master branch is empty or contains illegal characters, please use " +#~ "only letters, digits, dashs and dots as separators." +#~ msgstr "" +#~ "El branch principal está vacío o contiene caracteres no válidos, por " +#~ "favor utiliza solamente letras, digitos, guiones y puntos como " +#~ "separadores." + +#~ msgid "Learn more about the post-commit web hooks." +#~ msgstr "Saber más sobre WebHooks post-commit." + +#~ msgid "Your mail" +#~ msgstr "Su correo electrónico" + +#~ msgid "" +#~ "Notification emails will be sent from the %%from_email%% " +#~ "address, if you send the email to a mailing list, you may need to " +#~ "register this email address. Multiple email addresses must be separated " +#~ "through commas (','). If you do not want to send emails for a given type " +#~ "of changes, simply leave the corresponding field empty." +#~ msgstr "" +#~ "Las notificaciones de mensajes se enviarán desde la dirección %" +#~ "%from_email%%, si envía el mensaje a una lista de correo, puede " +#~ "que tenga que registrar esta dirección de correo electrónico. Varias " +#~ "direcciones de correo electrónico deben separarse por comas (','). Si no " +#~ "desea enviar mensajes de correo electrónico para un determinado tipo de " +#~ "cambio, simplemente deje el correspondiente campo vacío." + +#~ msgid "You have here access to the administration of the forge." +#~ msgstr "Tienes aquí el acceso a la administración de la forja." + +#~ msgid "Forge statistics" +#~ msgstr "Estadísticas de la Forja" + +#~ msgid "Projects:" +#~ msgstr "Proyectos:" diff --git a/indefero/src/IDF/locale/fr/idf.po b/indefero/src/IDF/locale/fr/idf.po new file mode 100644 index 0000000..c36084e --- /dev/null +++ b/indefero/src/IDF/locale/fr/idf.po @@ -0,0 +1,6089 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Benjamin Danon , 2011. +# Jean-Philippe Fleury , 2011. +# tommyd , 2011. +# , 2012. +# William MARTIN , 2011, 2012. +msgid "" +msgstr "" +"Project-Id-Version: Indefero\n" +"Report-Msgid-Bugs-To: http://projects.ceondo.com/p/indefero/issues/\n" +"POT-Creation-Date: 2012-03-22 01:16+0100\n" +"PO-Revision-Date: 2012-04-21 08:44+0000\n" +"Last-Translator: William MARTIN \n" +"Language-Team: French (http://www.transifex.net/projects/p/indefero/language/" +"fr/)\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1)\n" + +#: IDF/Commit.php:55 IDF/Conf.php:54 IDF/Issue.php:52 +#: IDF/ProjectActivity.php:49 IDF/Review.php:65 IDF/Search/Occ.php:69 +#: IDF/Tag.php:52 IDF/Upload.php:49 IDF/Wiki/Page.php:54 +#: IDF/Wiki/Resource.php:56 +msgid "project" +msgstr "projet" + +#: IDF/Commit.php:63 IDF/Issue.php:67 IDF/IssueComment.php:65 +#: IDF/IssueFile.php:57 IDF/IssueRelation.php:69 IDF/Review/Comment.php:69 +#: IDF/Review.php:80 IDF/Upload.php:91 IDF/Wiki/Page.php:78 +#: IDF/Wiki/PageRevision.php:79 IDF/Wiki/Resource.php:88 +#: IDF/Wiki/ResourceRevision.php:86 +msgid "submitter" +msgstr "auteur" + +#: IDF/Commit.php:87 IDF/Issue.php:60 IDF/Review/Patch.php:60 +#: IDF/Review.php:73 IDF/Upload.php:57 IDF/Wiki/Page.php:70 +#: IDF/Wiki/PageRevision.php:65 IDF/Wiki/Resource.php:80 +#: IDF/Wiki/ResourceRevision.php:63 +msgid "summary" +msgstr "résumé" + +#: IDF/Commit.php:93 +msgid "changelog" +msgstr "journal des modifications" + +#: IDF/Commit.php:100 IDF/Issue.php:105 IDF/IssueComment.php:79 +#: IDF/IssueFile.php:96 IDF/IssueRelation.php:75 IDF/Review/Comment.php:90 +#: IDF/Review/FileComment.php:75 IDF/Review/Patch.php:87 IDF/Review.php:108 +#: IDF/Upload.php:112 IDF/Wiki/Page.php:100 IDF/Wiki/PageRevision.php:92 +#: IDF/Wiki/Resource.php:95 IDF/Wiki/ResourceRevision.php:101 +msgid "creation date" +msgstr "date de création" + +#: IDF/Commit.php:238 +#, php-format +msgid "Commit %1$s, by %2$s" +msgstr "Commit %1$s, par %2$s" + +#: IDF/Commit.php:337 +#, php-format +msgid "New Commit %1$s - %2$s (%3$s)" +msgstr "Nouveau Commit %1$s - %2$s (%3$s)" + +#: IDF/Conf.php:61 IDF/Gconf.php:73 +msgid "key" +msgstr "clé" + +#: IDF/Conf.php:67 IDF/Gconf.php:79 IDF/ProjectActivity.php:62 +msgid "value" +msgstr "valeur" + +#: IDF/Diff.php:460 +msgid "Old" +msgstr "Ancien" + +#: IDF/Diff.php:460 +msgid "New" +msgstr "Nouveau" + +#: IDF/EmailAddress.php:49 IDF/Key.php:49 +msgid "user" +msgstr "utilisateur" + +#: IDF/EmailAddress.php:55 +msgid "email" +msgstr "email" + +#: IDF/Form/Admin/ForgeConf.php:34 +msgid "Custom forge page enabled" +msgstr "Page personnalisée de la forge activée" + +#: IDF/Form/Admin/ForgeConf.php:39 IDF/Form/WikiPageCreate.php:80 +#: IDF/Form/WikiPageUpdate.php:72 +msgid "Content" +msgstr "Contenu" + +#: IDF/Form/Admin/LabelConf.php:40 +msgid "Predefined project labels" +msgstr "Étiquettes prédéfinies des projets" + +#: IDF/Form/Admin/LabelConf.php:55 +#, php-format +msgid "" +"The label \"%s\" is invalid: A label must only consist of alphanumeric " +"characters and dashes, and can optionally contain a \":\" with a group " +"prefix." +msgstr "" +"L'étiquette \"%s\" est invalide : Une étiquette ne peut être composée " +"seulement que de caractères alphanumérique et de tirets, et peut " +"éventuellement contenir un \":\" avec un préfixe de groupe." + +#: IDF/Form/Admin/ProjectCreate.php:38 IDF/Views/Project.php:600 +msgid "git" +msgstr "git" + +#: IDF/Form/Admin/ProjectCreate.php:39 IDF/Views/Project.php:601 +msgid "Subversion" +msgstr "Subversion" + +#: IDF/Form/Admin/ProjectCreate.php:40 IDF/Views/Project.php:602 +msgid "mercurial" +msgstr "mercurial" + +#: IDF/Form/Admin/ProjectCreate.php:41 IDF/Views/Project.php:603 +msgid "monotone" +msgstr "monotone" + +#: IDF/Form/Admin/ProjectCreate.php:49 IDF/Form/Admin/ProjectUpdate.php:44 +#: IDF/Form/ProjectConf.php:39 IDF/Views/Admin.php:86 IDF/Views/Admin.php:273 +msgid "Name" +msgstr "Nom" + +#: IDF/Form/Admin/ProjectCreate.php:55 IDF/Form/TabsConf.php:101 +#: IDF/gettexttemplates/idf/base-full.html.php:5 +#: IDF/gettexttemplates/idf/base-full.html~.php:5 +#: IDF/gettexttemplates/idf/base.html.php:5 +#: IDF/gettexttemplates/idf/base.html~.php:5 +#: IDF/gettexttemplates/idf/main-menu.html.php:9 +#: IDF/gettexttemplates/idf/project-list.html.php:5 +#: IDF/gettexttemplates/idf/project-list.html.php:7 +msgid "Private project" +msgstr "Projet privé" + +#: IDF/Form/Admin/ProjectCreate.php:62 +msgid "Shortname" +msgstr "Nom court" + +#: IDF/Form/Admin/ProjectCreate.php:64 +msgid "" +"It must be unique for each project and composed only of letters, digits and " +"dash (-) like \"my-project\"." +msgstr "" +"Il doit être unique pour chaque projet et ne doit contenir que des lettres, " +"des chiffres et le tiret (-), par exemple «mon-projet»." + +#: IDF/Form/Admin/ProjectCreate.php:69 IDF/Form/Admin/ProjectUpdate.php:50 +msgid "Short description" +msgstr "Description courte" + +#: IDF/Form/Admin/ProjectCreate.php:70 IDF/Form/Admin/ProjectUpdate.php:51 +#: IDF/Project.php:79 +msgid "A one line description of the project." +msgstr "Une description d'une ligne du projet." + +#: IDF/Form/Admin/ProjectCreate.php:77 IDF/Form/Admin/ProjectUpdate.php:58 +#: IDF/Form/ProjectConf.php:56 +msgid "External URL" +msgstr "URL externe" + +#: IDF/Form/Admin/ProjectCreate.php:84 +msgid "Repository type" +msgstr "Type de dépôt" + +#: IDF/Form/Admin/ProjectCreate.php:92 +msgid "Remote Subversion repository" +msgstr "Dépôt Subversion distant" + +#: IDF/Form/Admin/ProjectCreate.php:99 IDF/Form/SourceConf.php:40 +msgid "Repository username" +msgstr "Identifiant d'accès au dépôt" + +#: IDF/Form/Admin/ProjectCreate.php:106 IDF/Form/SourceConf.php:47 +msgid "Repository password" +msgstr "Mot de passe du dépôt" + +#: IDF/Form/Admin/ProjectCreate.php:113 IDF/Form/Admin/ProjectUpdate.php:66 +msgid "Master branch" +msgstr "Branche principale" + +#: IDF/Form/Admin/ProjectCreate.php:116 IDF/Form/Admin/ProjectUpdate.php:69 +msgid "" +"This should be a world-wide unique identifier for your project. A reverse " +"DNS notation like \"com.my-domain.my-project\" is a good idea." +msgstr "" +"Cela devrait être un identifiant unique au monde pour votre projet. Une " +"notation DNS inverse comme «com.mon-domaine.mon-projet» est une bonne idée." + +#: IDF/Form/Admin/ProjectCreate.php:121 IDF/Form/Admin/ProjectUpdate.php:95 +#: IDF/Form/MembersConf.php:46 IDF/Form/TabsConf.php:53 +#: IDF/Form/TabsConf.php:72 +msgid "Project owners" +msgstr "Propriétaires du projet" + +#: IDF/Form/Admin/ProjectCreate.php:130 IDF/Form/Admin/ProjectUpdate.php:103 +#: IDF/Form/MembersConf.php:54 IDF/Form/TabsConf.php:52 +#: IDF/Form/TabsConf.php:78 +msgid "Project members" +msgstr "Membres du projet" + +#: IDF/Form/Admin/ProjectCreate.php:140 IDF/Form/Admin/ProjectUpdate.php:85 +#: IDF/Form/IssueCreate.php:168 IDF/Form/IssueUpdate.php:164 +#: IDF/Form/ProjectConf.php:73 IDF/Form/UpdateUpload.php:71 +#: IDF/Form/Upload.php:70 IDF/Form/WikiPageCreate.php:93 +#: IDF/Form/WikiPageUpdate.php:104 +msgid "Labels" +msgstr "Étiquettes" + +#: IDF/Form/Admin/ProjectCreate.php:155 +msgid "Project template" +msgstr "Modèle de projet" + +#: IDF/Form/Admin/ProjectCreate.php:157 +msgid "" +"Use the given project to initialize the new project. Access rights and " +"general configuration will be taken from the template project." +msgstr "" +"Utiliser le projet sélectionné pour démarrer le nouveau projet. Les droits " +"d'accès et la configuration générale seront extraits du modèle de projet." + +#: IDF/Form/Admin/ProjectCreate.php:204 +msgid "" +"Only a remote repository available through HTTP or HTTPS is allowed. For " +"example \"http://somewhere.com/svn/trunk\"." +msgstr "" +"Seulement un dépôt distant utilisant HTTP ou HTTPS est autorisé, par exemple " +"«http://exemple.com/svn/trunk»." + +#: IDF/Form/Admin/ProjectCreate.php:220 IDF/Form/Admin/ProjectUpdate.php:117 +msgid "" +"The master branch is empty or contains illegal characters, please use only " +"letters, digits, dashes and dots as separators." +msgstr "" +"La branche principale est vide ou contient des caractères non autorisés. " +"Veuillez n'utiliser que des lettres, des chiffres, le tiret (-) et le point " +"(.)." + +#: IDF/Form/Admin/ProjectCreate.php:230 IDF/Form/Admin/ProjectUpdate.php:128 +msgid "This master branch is already used. Please select another one." +msgstr "" +"Cette branche principale est déjà utilisée. Veuillez en sélectionner une " +"autre." + +#: IDF/Form/Admin/ProjectCreate.php:241 +msgid "" +"This shortname contains illegal characters, please use only letters, digits " +"and dash (-)." +msgstr "" +"Ce nom court contient des caractères non autorisés. Veuillez n'utiliser que " +"des lettres, des chiffres et le tiret (-)." + +#: IDF/Form/Admin/ProjectCreate.php:244 +msgid "The shortname cannot start with the dash (-) character." +msgstr "Le nom court ne doit pas débuter par un tiret (-)." + +#: IDF/Form/Admin/ProjectCreate.php:247 +msgid "The shortname cannot end with the dash (-) character." +msgstr "Le nom court ne doit pas se terminer par un tiret (-)." + +#: IDF/Form/Admin/ProjectCreate.php:252 +msgid "This shortname is already used. Please select another one." +msgstr "Ce nom court est déjà utilisé. Veuillez en sélectionner un autre." + +#: IDF/Form/Admin/ProjectCreate.php:303 IDF/Form/Admin/ProjectDelete.php:78 +#: IDF/Form/Admin/ProjectUpdate.php:153 IDF/Form/Admin/UserCreate.php:106 +#: IDF/Form/Admin/UserUpdate.php:191 IDF/Form/IssueCreate.php:338 +#: IDF/Form/IssueUpdate.php:329 IDF/Form/MembersConf.php:64 +#: IDF/Form/Password.php:76 IDF/Form/Register.php:112 +#: IDF/Form/ReviewCreate.php:187 IDF/Form/ReviewFileComment.php:143 +#: IDF/Form/TabsConf.php:122 IDF/Form/UpdateUpload.php:126 +#: IDF/Form/Upload.php:149 IDF/Form/UploadArchive.php:137 +#: IDF/Form/UserAccount.php:216 IDF/Form/UserChangeEmail.php:80 +#: IDF/Form/WikiPageCreate.php:167 IDF/Form/WikiPageDelete.php:59 +#: IDF/Form/WikiPageUpdate.php:178 IDF/Form/WikiResourceCreate.php:123 +#: IDF/Form/WikiResourceDelete.php:59 IDF/Form/WikiResourceUpdate.php:124 +msgid "Cannot save the model from an invalid form." +msgstr "Impossible de sauvegarder le modèle depuis un formulaire invalide." + +#: IDF/Form/Admin/ProjectCreate.php:341 +msgid "" +"Click on the Project Management tab to set the description of your project." +msgstr "" +"Cliquez sur l'onglet d'administration du projet pour définir la description " +"du projet." + +#: IDF/Form/Admin/ProjectCreate.php:426 +msgid "This project is not available." +msgstr "Ce projet n'est pas disponible." + +#: IDF/Form/Admin/ProjectDelete.php:41 +msgid "Confirmation code" +msgstr "Code de confirmation" + +#: IDF/Form/Admin/ProjectDelete.php:46 +msgid "I have made a backup of all the important data of this project." +msgstr "" +"J'ai réalisé une copie de sauvegarde des informations importantes de ce " +"projet." + +#: IDF/Form/Admin/ProjectDelete.php:55 +msgid "" +"The confirmation code does not match. Please provide a valid confirmation " +"code to delete the project." +msgstr "" +"Le code de confirmation ne correspond pas. Merci de fournir un code de " +"confirmation valide pour supprimer ce projet." + +#: IDF/Form/Admin/ProjectDelete.php:63 +msgid "Sorry, you really need to backup your data before deletion." +msgstr "" +"Désolé, vous devez vraiment faire une copie de sauvegarde des informations " +"importantes avant de supprimer le projet." + +#: IDF/Form/Admin/UserCreate.php:37 IDF/Form/Admin/UserUpdate.php:38 +#: IDF/Form/RegisterConfirmation.php:50 IDF/Form/UserAccount.php:40 +msgid "First name" +msgstr "Prénom" + +#: IDF/Form/Admin/UserCreate.php:46 IDF/Form/Admin/UserUpdate.php:47 +#: IDF/Form/RegisterConfirmation.php:59 IDF/Form/UserAccount.php:49 +msgid "Last name" +msgstr "Nom de famille" + +#: IDF/Form/Admin/UserCreate.php:56 +msgid "Login" +msgstr "Identifiant" + +#: IDF/Form/Admin/UserCreate.php:60 +msgid "" +"The login must be between 3 and 15 characters long and contains only letters " +"and digits." +msgstr "" +"L'identifiant doit avoir entre 3 et 15 caractères et ne doit contenir que " +"des lettres et des chiffres." + +#: IDF/Form/Admin/UserCreate.php:69 IDF/Form/Admin/UserUpdate.php:57 +msgid "Email" +msgstr "Email" + +#: IDF/Form/Admin/UserCreate.php:71 +msgid "" +"Double check the email address as the password is sent directly to the user." +msgstr "" +"Vérifiez tout particulièrement l'adresse email, car le mot de passe est " +"directement envoyé à l'utilisateur." + +#: IDF/Form/Admin/UserCreate.php:76 IDF/Form/Admin/UserUpdate.php:67 +#: IDF/Form/UserAccount.php:66 +msgid "Language" +msgstr "Langue" + +#: IDF/Form/Admin/UserCreate.php:87 IDF/Form/UserAccount.php:161 +msgid "Add a public key" +msgstr "Ajouter une clé publique" + +#: IDF/Form/Admin/UserCreate.php:92 +msgid "" +"Paste a SSH or monotone public key. Be careful to not provide your private " +"key here!" +msgstr "" +"Copiez une clé publique SSH ou monotone. Faites bien attention à ne pas y " +"mettre votre clé privée!" + +#: IDF/Form/Admin/UserCreate.php:157 +msgid "Your details to access your forge." +msgstr "Vos informations pour accéder à votre forge." + +#: IDF/Form/Admin/UserCreate.php:189 IDF/Form/UserAccount.php:429 +#: IDF/Form/UserAccount.php:438 +#, php-format +msgid "The email \"%s\" is already used." +msgstr "L'adresse email «%s» est déjà utilisée." + +#: IDF/Form/Admin/UserCreate.php:198 IDF/Form/Register.php:72 +#, php-format +msgid "The login \"%s\" can only contain letters and digits." +msgstr "L'identifiant «%s» ne doit contenir que des lettres et des chiffres." + +#: IDF/Form/Admin/UserCreate.php:203 IDF/Form/Register.php:77 +#, php-format +msgid "The login \"%s\" is already used, please find another one." +msgstr "L'identifiant «%s» est déjà utilisé. Merci d'en choisir un autre." + +#: IDF/Form/Admin/UserUpdate.php:78 +msgid "Password" +msgstr "Mot de passe" + +#: IDF/Form/Admin/UserUpdate.php:81 +msgid "Leave blank if you do not want to change the password." +msgstr "Laissez vide si vous ne voulez pas modifier le mot de passe." + +#: IDF/Form/Admin/UserUpdate.php:81 +msgid "" +"The password must be hard for other people to guess, but easy for the user " +"to remember." +msgstr "" +"Le mot de passe doit être difficile à trouver par d'autres, mais simple à " +"retenir pour l'utilisateur." + +#: IDF/Form/Admin/UserUpdate.php:89 +msgid "Confirm password" +msgstr "Confirmer le mot de passe" + +#: IDF/Form/Admin/UserUpdate.php:100 IDF/Form/IssueCreate.php:66 +#: IDF/Form/ProjectConf.php:48 IDF/Form/ReviewCreate.php:54 +#: IDF/Form/UpdateUpload.php:51 IDF/Form/Upload.php:49 +#: IDF/Form/UserAccount.php:101 IDF/Form/WikiPageCreate.php:70 +#: IDF/Form/WikiPageUpdate.php:60 IDF/Form/WikiResourceCreate.php:54 +#: IDF/Form/WikiResourceUpdate.php:46 IDF/Views/Wiki.php:102 +msgid "Description" +msgstr "Description" + +#: IDF/Form/Admin/UserUpdate.php:109 IDF/Form/UserAccount.php:110 +msgid "Twitter username" +msgstr "Nom d'utilisateur Twitter" + +#: IDF/Form/Admin/UserUpdate.php:119 IDF/Form/UserAccount.php:120 +msgid "Public email address" +msgstr "Adresse email publique" + +#: IDF/Form/Admin/UserUpdate.php:129 IDF/Form/UserAccount.php:130 +msgid "Website URL" +msgstr "URL de site Web" + +#: IDF/Form/Admin/UserUpdate.php:139 IDF/Form/UserAccount.php:140 +msgid "Upload custom avatar" +msgstr "Mettre en ligne un avatar personnalisé" + +#: IDF/Form/Admin/UserUpdate.php:146 IDF/Form/UserAccount.php:147 +msgid "" +"An image file with a width and height not larger than 60 pixels (bigger " +"images are scaled down)." +msgstr "" +"Un fichier image dont la largeur et la hauteur ne dépassent pas 60 pixels " +"(les images plus grandes sont redimensionnées)." + +#: IDF/Form/Admin/UserUpdate.php:151 IDF/Form/UserAccount.php:152 +msgid "Remove custom avatar" +msgstr "Supprimer l'avatar personnalisé" + +#: IDF/Form/Admin/UserUpdate.php:155 IDF/Form/UserAccount.php:156 +msgid "Tick this to delete the custom avatar." +msgstr "Cochez cette option pour supprimer l'avatar personnalisé." + +#: IDF/Form/Admin/UserUpdate.php:161 IDF/Views/Admin.php:274 +msgid "Staff" +msgstr "Gestionnaire" + +#: IDF/Form/Admin/UserUpdate.php:164 +msgid "If you give staff rights to a user, you really need to trust him." +msgstr "" +"Si vous donnez des droits de gestionnaire à un utilisateur, vous devez lui " +"faire confiance." + +#: IDF/Form/Admin/UserUpdate.php:172 IDF/Views/Admin.php:276 +msgid "Active" +msgstr "Actif" + +#: IDF/Form/Admin/UserUpdate.php:176 +msgid "" +"If the user is not getting the confirmation email or is abusing the system, " +"you can directly enable or disable their account here." +msgstr "" +"Si l'utilisateur ne reçoit pas l'email de confirmation ou s'il abuse du " +"système, vous pouvez directement activer ou désactiver son compte ici." + +#: IDF/Form/Admin/UserUpdate.php:274 +msgid "--- is not a valid first name." +msgstr "--- n'est pas un prénom valide." + +#: IDF/Form/Admin/UserUpdate.php:290 +msgid "" +"A user with this email already exists, please provide another email address." +msgstr "" +"Un utilisateur avec cet email existe déjà. Merci de fournir une autre " +"adresse email." + +#: IDF/Form/Admin/UserUpdate.php:301 IDF/Form/UserAccount.php:398 +msgid "For security reason, you cannot upload a file with this extension." +msgstr "" +"Pour des raisons de sécurité, vous ne pouvez pas mettre en ligne un fichier " +"ayant cette extension." + +#: IDF/Form/Admin/UserUpdate.php:316 IDF/Form/UserAccount.php:461 +msgid "The passwords do not match. Please give them again." +msgstr "" +"Les mots de passe ne sont pas identiques. Veuillez les saisir à nouveau." + +#: IDF/Form/Field/EmailList.php:45 +msgid "Please enter one or more valid email addresses." +msgstr "Veuillez entrer une ou plusieurs adresses email valides." + +#: IDF/Form/IssueCreate.php:57 IDF/Form/IssueUpdate.php:46 +#: IDF/Form/ReviewCreate.php:45 IDF/Form/ReviewFileComment.php:73 +#: IDF/Form/UpdateUpload.php:42 IDF/Form/Upload.php:40 +#: IDF/gettexttemplates/idf/issues/base.html.php:3 IDF/Views/Download.php:65 +#: IDF/Views/Download.php:347 IDF/Views/Issue.php:62 IDF/Views/Issue.php:221 +#: IDF/Views/Issue.php:302 IDF/Views/Issue.php:391 IDF/Views/Issue.php:543 +#: IDF/Views/Issue.php:766 IDF/Views/Issue.php:825 IDF/Views/Review.php:58 +#: IDF/Views/User.php:83 IDF/Views/Wiki.php:62 IDF/Views/Wiki.php:145 +#: IDF/Views/Wiki.php:186 +msgid "Summary" +msgstr "Résumé" + +#: IDF/Form/IssueCreate.php:76 IDF/Form/IssueUpdate.php:66 +#: IDF/Form/ReviewCreate.php:83 +msgid "The \"upload_issue_path\" configuration variable was not set." +msgstr "La variable de configuration «upload_issue_path» n'a pas été définie." + +#: IDF/Form/IssueCreate.php:86 IDF/Form/IssueUpdate.php:76 +msgid "Attach a file" +msgstr "Joindre un fichier" + +#: IDF/Form/IssueCreate.php:99 IDF/Form/IssueUpdate.php:89 +#: IDF/Form/ReviewCreate.php:103 IDF/Form/ReviewFileComment.php:83 +#: IDF/Views/Issue.php:63 IDF/Views/Issue.php:222 IDF/Views/Issue.php:304 +#: IDF/Views/Issue.php:392 IDF/Views/Issue.php:544 IDF/Views/Issue.php:767 +#: IDF/Views/Issue.php:826 IDF/Views/Review.php:59 IDF/Views/User.php:84 +msgid "Status" +msgstr "Statut" + +#: IDF/Form/IssueCreate.php:108 IDF/Form/IssueUpdate.php:99 +msgid "Owner" +msgstr "Propriétaire" + +#: IDF/Form/IssueCreate.php:118 IDF/Form/IssueUpdate.php:112 +#: IDF/Form/IssueUpdate.php:129 +msgid "This issue" +msgstr "Ce ticket" + +#: IDF/Form/IssueCreate.php:210 +msgid "You cannot add a label with the \"Status\" prefix to an issue." +msgstr "" +"Vous ne pouvez pas ajouter à un ticket une étiquette ayant le préfixe " +"«Status»." + +#: IDF/Form/IssueCreate.php:211 IDF/Form/IssueCreate.php:218 +#: IDF/Form/UpdateUpload.php:110 IDF/Form/Upload.php:121 +#: IDF/Form/WikiPageCreate.php:151 IDF/Form/WikiPageUpdate.php:162 +msgid "You provided an invalid label." +msgstr "Vous avez fourni une étiquette invalide." + +#: IDF/Form/IssueCreate.php:217 IDF/Form/UpdateUpload.php:109 +#, php-format +msgid "You cannot provide more than one label from the %s class to an issue." +msgstr "" +"Vous ne pouvez pas fournir plus d'une étiquette de la classe %s à un ticket." + +#: IDF/Form/IssueCreate.php:228 IDF/Form/IssueUpdate.php:194 +msgid "You need to provide a description of the issue." +msgstr "Vous devez fournir une description du ticket." + +#: IDF/Form/IssueCreate.php:251 IDF/Form/ReviewCreate.php:159 +msgid "You provided an invalid status." +msgstr "Vous avez fourni un statut invalide." + +#: IDF/Form/IssueCreate.php:272 +msgid "You provided an invalid relation type." +msgstr "Vous avez fourni un type de relation invalide." + +#: IDF/Form/IssueCreate.php:294 +#, php-format +msgid "The value \"%s\" is not a valid issue id." +msgstr "La valeur «%s» n'est pas un numéro de ticket valide." + +#: IDF/Form/IssueCreate.php:300 +#, php-format +msgid "The issue \"%s\" does not exist." +msgstr "Le ticket «%s» n'existe pas." + +#: IDF/Form/IssueTrackingConf.php:86 +msgid "is related to" +msgstr "est lié à" + +#: IDF/Form/IssueTrackingConf.php:87 +msgid "blocks" +msgstr "bloque" + +#: IDF/Form/IssueTrackingConf.php:88 +msgid "is blocked by" +msgstr "est bloqué par" + +#: IDF/Form/IssueTrackingConf.php:89 +msgid "duplicates" +msgstr "doublons" + +#: IDF/Form/IssueTrackingConf.php:90 +msgid "is duplicated by" +msgstr "est dupliqué par" + +#: IDF/Form/IssueTrackingConf.php:97 +msgid "" +"Define an issue template to hint the reporter to provide certain information" +msgstr "" +"Définir un modèle de ticket pour suggérer au rapporteur certaines " +"informations à fournir" + +#: IDF/Form/IssueTrackingConf.php:106 +msgid "Open issue status values" +msgstr "Valeurs des statuts des tickets ouverts" + +#: IDF/Form/IssueTrackingConf.php:114 +msgid "Closed issue status values" +msgstr "Valeurs des statuts des tickets fermés" + +#: IDF/Form/IssueTrackingConf.php:123 +msgid "Predefined issue labels" +msgstr "Étiquettes prédéfinies des tickets" + +#: IDF/Form/IssueTrackingConf.php:125 +msgid "" +"The first \"Type:\" and \"Priority:\" entries found in this list are " +"automatically chosen as defaults for new issues." +msgstr "" +"Les premières entrées «Type:» et «Priorité:» de cette liste sont " +"automatiquement choisies par défaut pour les nouveaux tickets." + +#: IDF/Form/IssueTrackingConf.php:133 +msgid "Each issue may have at most one label with each of these classes." +msgstr "" +"Chaque ticket ne peut avoir qu'une seule étiquette pour chacune de ces " +"classes." + +#: IDF/Form/IssueTrackingConf.php:140 +msgid "Issue relations" +msgstr "Relations entre les tickets" + +#: IDF/Form/IssueTrackingConf.php:142 +msgid "" +"You can define bidirectional relations like \"is related to\" or \"blocks, " +"is blocked by\". For standard relations pre-configured translations exist, " +"new relations should however be defined in a language that is understood by " +"all project members." +msgstr "" +"ous pouvez définir des relations bidirectionnelles comme « est lié " +"à » ou « bloque, est bloqué par ». Pour des relations " +"standards pré-configurées, il exite des traductions. De nouvelles relations " +"peuvent cependant être définies dans un vocabulaire compris par tous les " +"membres du projets." + +#: IDF/Form/IssueUpdate.php:56 IDF/Form/ReviewFileComment.php:45 +#: IDF/Form/WikiPageUpdate.php:82 IDF/Form/WikiResourceUpdate.php:66 +msgid "Comment" +msgstr "Commentaire" + +#: IDF/Form/IssueUpdate.php:316 +msgid "No changes were entered." +msgstr "Aucune modification n'a été effectuée." + +#: IDF/Form/MembersConf.php:104 +#, php-format +msgid "The following login is invalid: %s." +msgid_plural "The following logins are invalid: %s." +msgstr[0] "L'identifiant suivant est invalide: %s." +msgstr[1] "Les identifiants suivants sont invalides: %s." + +#: IDF/Form/Password.php:34 +msgid "Your login or email" +msgstr "Votre identifiant ou email" + +#: IDF/Form/Password.php:35 +msgid "Provide either your login or your email to recover your password." +msgstr "" +"Fournissez votre identifiant ou votre email pour récupérer votre mot de " +"passe." + +#: IDF/Form/Password.php:49 IDF/Form/Password.php:64 +msgid "" +"Sorry, we cannot find a user with this email address or login. Feel free to " +"try again." +msgstr "" +"Désolé, nous n'avons pas trouvé d'utilisateur avec cette adresse email ou " +"cet identifiant. Vous pouvez essayer à nouveau." + +#: IDF/Form/Password.php:100 +msgid "Password Recovery - InDefero" +msgstr "Récupération du mot de passe - InDefero" + +#: IDF/Form/PasswordInputKey.php:36 IDF/Form/PasswordReset.php:39 +#: IDF/Form/UserChangeEmail.php:36 +msgid "Your verification key" +msgstr "Votre clé de vérification" + +#: IDF/Form/PasswordInputKey.php:50 IDF/Form/PasswordReset.php:89 +msgid "" +"We are sorry but this validation key is not valid. Maybe you should directly " +"copy/paste it from your validation email." +msgstr "" +"Nous sommes désolés, mais cette clé de validation est invalide. Peut-être " +"devriez-vous faire directement un copier/coller depuis votre email de " +"validation." + +#: IDF/Form/PasswordInputKey.php:61 IDF/Form/PasswordReset.php:100 +msgid "" +"Sorry, but this verification key has expired, please restart the password " +"recovery sequence. For security reasons, the verification key is only valid " +"24h." +msgstr "" +"Désolé, cette clé de vérification a expiré. Merci de recommencer la " +"procédure de récupération du mot de passe. Pour des raisons de sécurité, la " +"clé de vérification n'est valide que 24 heures." + +#: IDF/Form/PasswordInputKey.php:76 IDF/Form/PasswordReset.php:108 +#: IDF/Form/RegisterConfirmation.php:137 IDF/Form/RegisterInputKey.php:72 +msgid "Cannot save an invalid form." +msgstr "Impossible de sauvegarder un formulaire invalide." + +#: IDF/Form/PasswordReset.php:45 IDF/Form/RegisterConfirmation.php:69 +#: IDF/Form/UserAccount.php:77 +msgid "Your password" +msgstr "Votre mot de passe" + +#: IDF/Form/PasswordReset.php:48 IDF/Form/UserAccount.php:80 +msgid "" +"Your password must be hard for other people to find it, but easy for you to " +"remember." +msgstr "" +"Votre mot de passe doit être difficile à trouver par d'autres, mais simple à " +"retenir pour vous." + +#: IDF/Form/PasswordReset.php:56 IDF/Form/RegisterConfirmation.php:80 +#: IDF/Form/UserAccount.php:89 +msgid "Confirm your password" +msgstr "Confirmez votre mot de passe" + +#: IDF/Form/PasswordReset.php:74 IDF/Form/RegisterConfirmation.php:122 +msgid "The two passwords must be the same." +msgstr "Les deux mots de passe doivent être identiques." + +#: IDF/Form/PasswordReset.php:77 +msgid "" +"This account is not active. Please contact the forge administrator to " +"activate it." +msgstr "" +"Ce compte n'est pas actif. Veuillez contacter l'administrateur de la forge " +"pour l'activer." + +#: IDF/Form/ProjectConf.php:43 +msgid "Short Description" +msgstr "Description courte" + +#: IDF/Form/ProjectConf.php:85 +msgid "The \"upload_path\" configuration variable was not set." +msgstr "La variable de configuration «upload_path» n'a pas été définie." + +#: IDF/Form/ProjectConf.php:90 +msgid "Update the logo" +msgstr "Mettre à jour le logo" + +#: IDF/Form/ProjectConf.php:92 +msgid "The logo must be a picture with a size of 32 by 32." +msgstr "Le logo doit être une image de 32 × 32 pixels." + +#: IDF/Form/ProjectConf.php:103 +msgid "Remove the current logo" +msgstr "Supprimer le logo actuel" + +#: IDF/Form/ProjectConf.php:139 +msgid "Could not determine the size of the uploaded picture." +msgstr "Impossible de déterminer la taille de l'image mise en ligne." + +#: IDF/Form/ProjectConf.php:143 +msgid "The picture must have a size of 32 by 32." +msgstr "L'image doit avoir une taille de 32 × 32 pixels." + +#: IDF/Form/ProjectConf.php:164 +msgid "The entered URL is invalid. Only http and https URLs are allowed." +msgstr "" +"L'adresse entrée est invalide. Seul les sites \"http\" et \"https\" sont " +"autorisés." + +#: IDF/Form/Register.php:41 +msgid "Your login" +msgstr "Votre identifiant" + +#: IDF/Form/Register.php:45 +msgid "" +"The login must be between 3 and 15 characters long and contain only letters " +"and digits." +msgstr "" +"L'identifiant doit avoir entre 3 et 15 caractères et ne doit contenir que " +"des lettres et des chiffres." + +#: IDF/Form/Register.php:53 IDF/Form/UserAccount.php:59 +msgid "Your email" +msgstr "Votre email" + +#: IDF/Form/Register.php:55 +msgid "We will never send you any unsolicited emails. We hate spam too!" +msgstr "" +"Nous ne vous enverrons aucun message non sollicité. Comme vous, nous avons " +"ras-le-bol du spam." + +#: IDF/Form/Register.php:60 +msgid "I agree to the terms and conditions." +msgstr "J'accepte les conditions d'usage du service." + +#: IDF/Form/Register.php:88 +msgid "" +"We know, this is boring, but you need to agree with the terms and conditions." +msgstr "" +"Nous savons que c'est inintéressant, mais vous devez accepter les conditions " +"d'usage du service." + +#: IDF/Form/Register.php:97 +#, php-format +msgid "" +"The email \"%1$s\" is already used. If you need to, you can recover your password." +msgstr "" +"L'email \"%1$s\" est déjà utilisé. Si vous le voulez, vous pouvez récupérer votre mot de passe." + +#: IDF/Form/Register.php:148 +msgid "Confirm the creation of your account." +msgstr "Confirmez la création de votre compte." + +#: IDF/Form/RegisterConfirmation.php:40 IDF/Form/RegisterInputKey.php:36 +msgid "Your confirmation key" +msgstr "Votre clé de confirmation" + +#: IDF/Form/RegisterConfirmation.php:72 +msgid "" +"Your password must be hard for other people to guess, but easy for you to " +"remember." +msgstr "" +"Votre mot de passe doit être difficile à trouver par d'autres, mais simple à " +"retenir pour vous." + +#: IDF/Form/RegisterConfirmation.php:99 IDF/Form/RegisterInputKey.php:50 +msgid "" +"We are sorry but this confirmation key is not valid. Maybe you should " +"directly copy/paste it from your confirmation email." +msgstr "" +"Nous sommes désolés, mais cette clé de confirmation est invalide. Peut-être " +"devriez-vous faire directement un copier/coller depuis votre email de " +"confirmation." + +#: IDF/Form/RegisterConfirmation.php:110 +#, php-format +msgid "" +"This account has already been confirmed. Maybe should you try to recover your password." +msgstr "" +"Ce compte à déjà été validé. Vous voulez peut-être récupérer " +"votre mot de passe." + +#: IDF/Form/ReviewCreate.php:74 +#: IDF/gettexttemplates/idf/source/base.html.php:5 +#: IDF/gettexttemplates/idf/source/changelog.html.php:7 +msgid "Commit" +msgstr "Commit" + +#: IDF/Form/ReviewCreate.php:92 +msgid "Patch" +msgstr "Patch" + +#: IDF/Form/ReviewCreate.php:119 +msgid "We were not able to parse your patch. Please provide a valid patch." +msgstr "" +"Nous n'avons pas réussi à interpréter votre patch. Merci de fournir un patch " +"valide." + +#: IDF/Form/ReviewCreate.php:128 +msgid "You provided an invalid commit." +msgstr "Vous avez fourni un commit invalide." + +#: IDF/Form/ReviewCreate.php:202 +msgid "Initial patch to be reviewed." +msgstr "Patch initial à discuter." + +#: IDF/Form/ReviewFileComment.php:56 +msgid "General comment" +msgstr "Commentaire général" + +#: IDF/Form/ReviewFileComment.php:113 +msgid "" +"You need to provide your general comment about the proposal, or comments on " +"at least one file." +msgstr "" +"Vous devez faire un commentaire général sur la revue de code, ou des " +"commentaires sur au moins un des fichiers." + +#: IDF/Form/ReviewFileComment.php:124 +msgid "The status have been updated." +msgstr "Le statut a été mis à jour." + +#: IDF/Form/ReviewFileComment.php:130 +msgid "This field is required." +msgstr "Ce champ est obligatoire." + +#: IDF/Form/SourceConf.php:54 IDF/Form/UploadConf.php:70 +msgid "Webhook URL" +msgstr "URL de notification" + +#: IDF/Form/TabsConf.php:38 IDF/gettexttemplates/idf/admin/base.html.php:4 +#: IDF/gettexttemplates/idf/base-full.html.php:8 +#: IDF/gettexttemplates/idf/base-full.html~.php:7 +#: IDF/gettexttemplates/idf/base.html.php:8 +#: IDF/gettexttemplates/idf/base.html~.php:7 +#: IDF/gettexttemplates/idf/downloads/base.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:14 +#: IDF/Views/Project.php:97 +msgid "Downloads" +msgstr "Téléchargements" + +#: IDF/Form/TabsConf.php:39 IDF/gettexttemplates/idf/base-full.html.php:12 +#: IDF/gettexttemplates/idf/base-full.html~.php:11 +#: IDF/gettexttemplates/idf/base.html.php:12 +#: IDF/gettexttemplates/idf/base.html~.php:11 +msgid "Code Review" +msgstr "Revue de code" + +#: IDF/Form/TabsConf.php:40 IDF/gettexttemplates/idf/admin/base.html.php:5 +#: IDF/gettexttemplates/idf/base-full.html.php:9 +#: IDF/gettexttemplates/idf/base-full.html~.php:8 +#: IDF/gettexttemplates/idf/base.html.php:9 +#: IDF/gettexttemplates/idf/base.html~.php:8 +msgid "Documentation" +msgstr "Documentation" + +#: IDF/Form/TabsConf.php:41 IDF/gettexttemplates/idf/admin/base.html.php:7 +#: IDF/gettexttemplates/idf/base-full.html.php:11 +#: IDF/gettexttemplates/idf/base-full.html~.php:10 +#: IDF/gettexttemplates/idf/base.html.php:11 +#: IDF/gettexttemplates/idf/base.html~.php:10 +msgid "Source" +msgstr "Source" + +#: IDF/Form/TabsConf.php:42 IDF/gettexttemplates/idf/base-full.html.php:10 +#: IDF/gettexttemplates/idf/base-full.html~.php:9 +#: IDF/gettexttemplates/idf/base.html.php:10 +#: IDF/gettexttemplates/idf/base.html~.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:17 +msgid "Issues" +msgstr "Tickets" + +#: IDF/Form/TabsConf.php:50 +msgid "Open to all" +msgstr "Ouvert à tous" + +#: IDF/Form/TabsConf.php:51 +msgid "Signed in users" +msgstr "Utilisateurs authentifiés" + +#: IDF/Form/TabsConf.php:54 +msgid "Closed" +msgstr "Fermé" + +#: IDF/Form/TabsConf.php:84 +msgid "Others" +msgstr "Autres" + +#: IDF/Form/TabsConf.php:107 +msgid "Extra authorized users" +msgstr "Utilisateurs autorisés supplémentaires" + +#: IDF/Form/Upload.php:59 IDF/Form/WikiResourceCreate.php:65 +#: IDF/Form/WikiResourceUpdate.php:56 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:7 +#: IDF/Views/Download.php:64 IDF/Views/Download.php:346 +msgid "File" +msgstr "Fichier" + +#: IDF/Form/Upload.php:87 IDF/Form/WikiResourceCreate.php:96 +#: IDF/Form/WikiResourceUpdate.php:83 +msgid "For security reasons, you cannot upload a file with this extension." +msgstr "" +"Pour des raisons de sécurité, vous ne pouvez pas mettre en ligne un fichier " +"ayant cette extension." + +#: IDF/Form/Upload.php:120 +#, php-format +msgid "You cannot provide more than one label from the %s class to a download." +msgstr "" +"Vous ne pouvez pas fournir plus d'une étiquette de la classe %s pour un " +"téléchargement." + +#: IDF/Form/UploadArchive.php:41 +msgid "Archive file" +msgstr "Fichier archivé" + +#: IDF/Form/UploadArchive.php:67 +#, php-format +msgid "" +"For security reasons, you cannot upload a file (%s) with this extension." +msgstr "" +"Pour des raisons de sécurité, vous ne pouvez pas uploader une fichier (%s) " +"sans son extension." + +#: IDF/Form/UploadArchive.php:98 +#, php-format +msgid "" +"You cannot provide more than label from the %1$s class to a download (%2$s)." +msgstr "" +"Vous ne pouvez pas fournir plus d'une étiquette de la classe %1$s pour un " +"téléchargement (%2$s)." + +#: IDF/Form/UploadArchive.php:109 +#, php-format +msgid "" +"A file with the name \"%s\" has already been uploaded and is not marked to " +"be replaced." +msgstr "" +"Un fichier avec ce nom \"%s\" à été déjà été envoyé et n'a pas été signalé " +"comme un fichier qui devait être remplacé." + +#: IDF/Form/UploadArchiveHelper.php:41 +msgid "The archive does not exist." +msgstr "L'archive n'existe pas." + +#: IDF/Form/UploadArchiveHelper.php:48 +#, php-format +msgid "The archive could not be read (code %d)." +msgstr "L'archive ne peut pas être lue (code %d)." + +#: IDF/Form/UploadArchiveHelper.php:53 +msgid "The archive does not contain a manifest.xml." +msgstr "L'archive ne contient pas de fichier \"manifest.xml\"." + +#: IDF/Form/UploadArchiveHelper.php:61 +#, php-format +msgid "The archive's manifest is invalid: %s" +msgstr "Le manifeste de l'archive est invalide : %s." + +#: IDF/Form/UploadArchiveHelper.php:77 +#, php-format +msgid "The entry %d in the manifest is missing a file name." +msgstr "Il manque le nom du fichier dans l'entrée %d du manifeste." + +#: IDF/Form/UploadArchiveHelper.php:82 +#, php-format +msgid "The entry %d in the manifest is missing a summary." +msgstr "Il manque une résumé dans l'entrée %d du manifeste." + +#: IDF/Form/UploadArchiveHelper.php:86 +msgid "The manifest must not reference itself." +msgstr "Le manifeste ne doit pas se faire référence à lui même." + +#: IDF/Form/UploadArchiveHelper.php:91 +#, php-format +msgid "The entry %s in the manifest does not exist in the archive." +msgstr "L'entrée %s du manifeste n'existe pas dans l'archive." + +#: IDF/Form/UploadArchiveHelper.php:96 +#, php-format +msgid "The entry %s in the manifest is referenced more than once." +msgstr "L'entrée %s du manifeste est référencée plus d'une fois." + +#: IDF/Form/UploadArchiveHelper.php:108 +#, php-format +msgid "The entry %s in the manifest has more than the six allowed labels set." +msgstr "" +"L'entrée %s du manifeste contient plus que le maximum des 6 étiquettes " +"autorisées." + +#: IDF/Form/UploadConf.php:53 +msgid "Predefined download labels" +msgstr "Étiquettes prédéfinies des téléchargements" + +#: IDF/Form/UploadConf.php:62 +msgid "Each download may have at most one label with each of these classes" +msgstr "" +"Chaque téléchargement ne peut avoir qu'une seule étiquette pour chacune de " +"ces classes" + +#: IDF/Form/UserAccount.php:61 +msgid "" +"If you change your email address, an email will be sent to the new address " +"to confirm it." +msgstr "" +"Si vous changez votre adresse email, un message sera envoyé à la nouvelle " +"adresse pour confirmation." + +#: IDF/Form/UserAccount.php:80 +msgid "Leave blank if you do not want to change your password." +msgstr "Laissez vide si vous ne voulez pas modifier votre mot de passe." + +#: IDF/Form/UserAccount.php:166 +msgid "" +"Paste an SSH or monotone public key. Be careful to not provide your private " +"key here!" +msgstr "" +"Copiez une clé publique SSH ou monotone. Faites bien attention à ne pas y " +"mettre votre clé privée!" + +#: IDF/Form/UserAccount.php:171 +msgid "Add a secondary email address" +msgstr "Ajouter une adresse email secondaire" + +#: IDF/Form/UserAccount.php:173 +msgid "You will get an email to confirm that you own the address you specify." +msgstr "" +"Vous allez recevoir un email de confirmation à l'adresse que vous avez " +"spécifié." + +#: IDF/Form/UserAccount.php:200 +msgid "Confirm your new email address." +msgstr "Confirmez votre nouvelle adresse email." + +#: IDF/Form/UserAccount.php:203 +#, php-format +msgid "" +"A validation email has been sent to \"%s\" to validate the email address " +"change." +msgstr "Un email a été envoyé à «%s» pour valider le changement d'adresse." + +#: IDF/Form/UserAccount.php:341 +msgid "" +"Please check the key as it does not appear to be a valid SSH public key." +msgstr "" +"Veuillez vérifier la clé, car elle ne semble pas être une clé publique SSH " +"valide." + +#: IDF/Form/UserAccount.php:363 +msgid "" +"Please check the key as it does not appear to be a valid monotone public key." +msgstr "" +"Veuillez vérifier la clé, car elle ne semble pas être une clé publique " +"monotone valide." + +#: IDF/Form/UserAccount.php:371 +msgid "Public key looks like neither an SSH nor monotone public key." +msgstr "" +"La clé publique ne ressemble pas à une clé publique SSH ni à une clé " +"publique monotone." + +#: IDF/Form/UserAccount.php:383 +msgid "You already have uploaded this key." +msgstr "Vous avez déjà mis en ligne cette clé." + +#: IDF/Form/UserChangeEmail.php:63 +msgid "" +"The validation key is not valid. Please copy/paste it from your confirmation " +"email." +msgstr "" +"La clé de validation est invalide. Veuillez la copier/coller depuis votre " +"email de confirmation." + +#: IDF/Form/WikiConf.php:49 +msgid "Predefined documentation page labels" +msgstr "Étiquettes prédéfinies des pages de documentation" + +#: IDF/Form/WikiConf.php:58 +msgid "" +"Each documentation page may have at most one label with each of these classes" +msgstr "" +"Chaque page de documentation ne peut avoir qu'une seule étiquette pour " +"chacune de ces classes" + +#: IDF/Form/WikiPageCreate.php:38 +msgid "" +"# Introduction\n" +"\n" +"Add your content here.\n" +"\n" +"\n" +"# Details\n" +"\n" +"Add your content here. Format your content with:\n" +"\n" +"* Text in **bold** or *italic*.\n" +"* Headings, paragraphs, and lists.\n" +"* Links to other [[WikiPage]].\n" +msgstr "" +"# Introduction\n" +"\n" +"Ajoutez votre contenu ici.\n" +"\n" +"# Détails\n" +"\n" +"Ajoutez votre contenu ici. Vous pouvez utiliser:\n" +"\n" +"* du texte en **gras** ou en *italique*;\n" +"* des titres, des paragraphes ou des listes;\n" +"* des liens vers d'autres [[PageDeDocumentation]].\n" + +#: IDF/Form/WikiPageCreate.php:57 +msgid "PageName" +msgstr "NomDeLaPage" + +#: IDF/Form/WikiPageCreate.php:60 IDF/Form/WikiPageUpdate.php:50 +msgid "Page title" +msgstr "Titre de la page" + +#: IDF/Form/WikiPageCreate.php:66 IDF/Form/WikiPageUpdate.php:56 +msgid "" +"The page name must contains only letters, digits and the dash (-) character." +msgstr "" +"Le nom de la page ne doit contenir que des lettres, des chiffres et le tiret " +"(-)." + +#: IDF/Form/WikiPageCreate.php:71 IDF/Form/WikiPageUpdate.php:61 +msgid "This one line description is displayed in the list of pages." +msgstr "Cette description d'une ligne est affichée dans la liste des pages." + +#: IDF/Form/WikiPageCreate.php:108 IDF/Form/WikiPageUpdate.php:119 +#: IDF/Form/WikiResourceCreate.php:78 +msgid "The title contains invalid characters." +msgstr "Le titre contient des caractères invalides." + +#: IDF/Form/WikiPageCreate.php:114 IDF/Form/WikiPageUpdate.php:125 +msgid "A page with this title already exists." +msgstr "Une page avec ce titre existe déjà." + +#: IDF/Form/WikiPageCreate.php:150 IDF/Form/WikiPageUpdate.php:161 +#, php-format +msgid "You cannot provide more than one label from the %s class to a page." +msgstr "" +"Vous ne pouvez pas fournir plus d'une étiquette de la classe %s pour une " +"page." + +#: IDF/Form/WikiPageCreate.php:200 +msgid "Initial page creation" +msgstr "Création de la page initiale" + +#: IDF/Form/WikiPageDelete.php:39 +msgid "Yes, I understand that the page and all its revisions will be deleted." +msgstr "" +"Oui, je comprends que la page ainsi que toutes ses révisions vont être " +"supprimées." + +#: IDF/Form/WikiPageDelete.php:50 IDF/Form/WikiResourceDelete.php:50 +msgid "You need to confirm the deletion." +msgstr "Vous devez confirmer la suppression." + +#: IDF/Form/WikiPageUpdate.php:83 IDF/Form/WikiResourceUpdate.php:67 +msgid "One line to describe the changes you made." +msgstr "Une ligne pour décrire les modifications que vous avez effectuées." + +#: IDF/Form/WikiResourceCreate.php:40 +msgid "ResourceName" +msgstr "Nom de la ressource" + +#: IDF/Form/WikiResourceCreate.php:44 +msgid "Resource title" +msgstr "Titre de la ressource" + +#: IDF/Form/WikiResourceCreate.php:50 +msgid "" +"The resource name must contains only letters, digits and the dash (-) " +"character." +msgstr "" +"Le nom de la ressource ne peut contenir que des lettre, des chiffres, et des " +"tirets (-)." + +#: IDF/Form/WikiResourceCreate.php:55 IDF/Form/WikiResourceUpdate.php:47 +msgid "This one line description is displayed in the list of resources." +msgstr "Cette ligne de description est affichée dans la liste des ressources." + +#: IDF/Form/WikiResourceCreate.php:84 +msgid "A resource with this title already exists." +msgstr "Une ressource avec ce titre existe déjà." + +#: IDF/Form/WikiResourceCreate.php:142 +msgid "Initial resource creation" +msgstr "Création initiale de la ressource" + +#: IDF/Form/WikiResourceDelete.php:39 +msgid "" +"Yes, I understand that the resource and all its revisions will be deleted." +msgstr "Oui, je comprend cette ressource et cette révision va être supprimée." + +#: IDF/Form/WikiResourceUpdate.php:89 +#, php-format +msgid "" +"The mime type of the uploaded file \"%1$s\" does not match the mime type of " +"this resource \"%2$s\"" +msgstr "" +"Le type MIME du fichier envoyé \"%1$s\" ne correspond pas avec le type MIME " +"de cette ressource \"%2$s\"" + +#: IDF/Form/WikiResourceUpdate.php:97 +msgid "The current version of the resource and the uploaded file are equal." +msgstr "" +"La version actuelle de la ressource et du fichier envoyé sont les mêmes" + +#: IDF/Gconf.php:60 IDF/Search/Occ.php:56 +msgid "model class" +msgstr "classe du modèle" + +#: IDF/Gconf.php:66 IDF/Search/Occ.php:62 +msgid "model id" +msgstr "id du modèle" + +#: IDF/gettexttemplates/idf/admin/base.html.php:3 +msgid "Project Summary" +msgstr "Résumé du projet" + +#: IDF/gettexttemplates/idf/admin/base.html.php:6 +msgid "Issue Tracking" +msgstr "Gestionnaire de tickets" + +#: IDF/gettexttemplates/idf/admin/base.html.php:8 +msgid "Project Members" +msgstr "Membres du projet" + +#: IDF/gettexttemplates/idf/admin/base.html.php:9 +msgid "Tabs Access and Notifications" +msgstr "Accès aux onglets et notifications" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:3 +#: IDF/gettexttemplates/idf/admin/issue-tracking.html.php:3 +#: IDF/gettexttemplates/idf/admin/wiki.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/labels.html.php:3 +msgid "" +"\n" +"

Instructions:

\n" +"

List one status value per line in desired sort-order.

\n" +"

Optionally, use an equals-sign to document the meaning of each status " +"value.

\n" +msgstr "" +"\n" +"

Instructions:

\n" +"

Listez un statut par ligne dans l'ordre de tri désiré.

\n" +"

Vous pouvez optionnellement utiliser le signe égal (=) pour ajouter la " +"signification de chaque statut.

\n" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:8 +msgid "" +"

The webhook URL setting specifies an URL to which a HTTP PUT\n" +"request is sent after a new download has been added or to which a HTTP " +"POST\n" +"request is sent after an existing download has been updated.\n" +"If this field is empty, notifications are disabled.

\n" +"\n" +"

Only properly-escaped HTTP URLs are supported, for " +"example:

\n" +"\n" +"
    \n" +"
  • http://domain.com/upload
  • \n" +"
  • http://domain.com/upload?my%20param
  • \n" +"
\n" +"\n" +"

In addition, the URL may contain the following \"%\" notation, which\n" +"will be replaced with specific project values for each download:

\n" +"\n" +"
    \n" +"
  • %p - project name
  • \n" +"
  • %d - download id
  • \n" +"
\n" +"\n" +"

For example, updating download 123 of project 'my-project' with\n" +"web hook URL http://mydomain.com/%p/%d would send a POST " +"request to\n" +"http://mydomain.com/my-project/123.

" +msgstr "" +"

Il est possible de mettre en place l'envoie de méta-information à l'aide " +"d'une requête HTTP PUT lors de la création, ou POST lors de la mise a jour " +"d'un téléchargement. Laisser ce champs vide pour désactiver les " +"notifications.

\n" +"\n" +"

Le lien ne doit pas contenir de caractères spéciaux, par exemple :

\n" +"\n" +"
    \n" +"
  • http://domain.com/upload
  • \n" +"
  • http://domain.com/upload?my%20param
  • \n" +"
\n" +"\n" +"

De plus, il peut contenir les séquences suivantes qui seront remplacer " +"par les valeurs spécifiques au projet et au téléchargement en question.

\n" +"\n" +"
    \n" +"
  • %p - le nom du projet
  • \n" +"
  • %d - l'identifiant du téléchargement
  • \n" +"
\n" +"\n" +"

Par exemple, la mise a jour du téléchargement 123 dans le projet 'my-" +"project', avec le lien suivant http://mydomain.com/%p/%d\n" +"enverra une requête POST à l’adresse suivante http://mydomain.com/my-" +"project/123.

" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:31 +#: IDF/gettexttemplates/idf/admin/source.html.php:30 +msgid "Web-Hook authentication key:" +msgstr "Clé d’authentification du Web-Hook :" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:32 +#: IDF/gettexttemplates/idf/admin/issue-tracking.html.php:8 +#: IDF/gettexttemplates/idf/admin/members.html.php:13 +#: IDF/gettexttemplates/idf/admin/source.html.php:31 +#: IDF/gettexttemplates/idf/admin/summary.html.php:11 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:12 +#: IDF/gettexttemplates/idf/admin/wiki.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/forge/index.html.php:13 +#: IDF/gettexttemplates/idf/gadmin/projects/labels.html.php:8 +msgid "Save Changes" +msgstr "Enregistrer les modifications" + +#: IDF/gettexttemplates/idf/admin/members.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:3 +msgid "" +"\n" +"

Instructions:

\n" +"

Specify each person by its login. Each person must have already " +"registered with the given login.

\n" +"

Separate the logins with commas and/or new lines.

\n" +msgstr "" +"\n" +"

Instructions:

\n" +"

Indiquez chaque personne à l'aide de son identifiant. Chaque personne " +"doit avoir préalablement créé son compte.

\n" +"

Séparez les identifiants par des virgules ou des sauts de ligne.

\n" + +#: IDF/gettexttemplates/idf/admin/members.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:8 +msgid "" +"\n" +"

Notes:

\n" +"

A project owner may make any change to this project, including removing " +"other project owners. You need to be carefull when you give owner rights.\n" +"

A project member will not have access to the administration area but will " +"have more options available in the use of the project.

\n" +msgstr "" +"\n" +"

Notes:

\n" +"

Le propriétaire d'un projet peut effectuer n'importe quelle modification " +"au projet, incluant la suppression d'autres propriétaires. Soyez donc " +"prudent quand vous ajoutez un propriétaire.

\n" +"

Un membre du projet n'aura pas accès à la zone d'administration, mais " +"aura plus d'options dans l'utilisation du projet.

\n" + +#: IDF/gettexttemplates/idf/admin/source.html.php:3 +msgid "You can find here the current repository configuration of your project." +msgstr "Vous trouverez ici la configuration du dépôt actuel de votre projet." + +#: IDF/gettexttemplates/idf/admin/source.html.php:4 +msgid "" +"

The webhook URL setting specifies an URL to which a HTTP \n" +"%%hook_request_method%% request is sent after each " +"repository\n" +"commit. If this field is empty, notifications are disabled.

\n" +"\n" +"

Only properly-escaped HTTP URLs are supported, for " +"example:

\n" +"\n" +"
    \n" +"
  • http://domain.com/commit
  • \n" +"
  • http://domain.com/commit?my%20param
  • \n" +"
\n" +"\n" +"

In addition, the URL may contain the following \"%\" notation, which\n" +"will be replaced with specific project values for each commit:

\n" +"\n" +"
    \n" +"
  • %p - project name
  • \n" +"
  • %r - revision number
  • \n" +"
\n" +"\n" +"

For example, committing revision 123 to project 'my-project' with\n" +"post-commit URL http://mydomain.com/%p/%r would send a request " +"to\n" +"http://mydomain.com/my-project/123.

" +msgstr "" +"

Il est possible de mettre en place l'envoie de méta-information à l'aide " +"d'une requête HTTP %%hook_request_method%% lors de la " +"réception de commit dans le dépôt .Laisser ce champs vide pour désactiver " +"les notifications.

\n" +"\n" +"

Le lien ne doit pas contenir de caractères spéciaux, par exemple :

\n" +"\n" +"
    \n" +"
  • http://domain.com/commit
  • \n" +"
  • http://domain.com/commit?my%20param
  • \n" +"
\n" +"\n" +"

De plus, il peut contenir les séquences suivantes qui seront remplacer " +"par les valeurs spécifiques au projet et au téléchargement en question.

\n" +"\n" +"
    \n" +"
  • %p - le nom du projet
  • \n" +"
  • %r - l'identifiant du commit
  • \n" +"
\n" +"\n" +"

Par exemple, la réception du commit 123 dans le projet 'my-project', avec " +"le lien suivant http://mydomain.com/%p/%renverra une requête à " +"l’adresse suivante \n" +"http://mydomain.com/my-project/123.

" + +#: IDF/gettexttemplates/idf/admin/source.html.php:26 +msgid "" +"The form contains some errors. Please correct them to update the source " +"configuration." +msgstr "" +"Le formulaire contient des erreurs. Veuillez les corriger pour mettre à jour " +"la configuration du code source." + +#: IDF/gettexttemplates/idf/admin/source.html.php:27 +msgid "Repository type:" +msgstr "Type de dépôt:" + +#: IDF/gettexttemplates/idf/admin/source.html.php:28 +msgid "Repository access:" +msgstr "Accès au dépôt:" + +#: IDF/gettexttemplates/idf/admin/source.html.php:29 +msgid "Repository size:" +msgstr "Taille du dépôt:" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

The description of the project can be improved using the Markdown syntax.

\n" +msgstr "" +"\n" +"

Instructions:

\n" +"

La description du projet peut être enrichie à l'aide de la syntaxe Markdown.

\n" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:7 +msgid "" +"The form contains some errors. Please correct them to update the summary." +msgstr "" +"Le formulaire contient des erreurs. Veuillez les corriger pour mettre à jour " +"le résumé." + +#: IDF/gettexttemplates/idf/admin/summary.html.php:8 +msgid "Current logo" +msgstr "Logo actuel" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:9 +#: IDF/gettexttemplates/idf/base-full.html.php:4 +#: IDF/gettexttemplates/idf/base-full.html~.php:4 +#: IDF/gettexttemplates/idf/base.html.php:4 +#: IDF/gettexttemplates/idf/base.html~.php:4 +#: IDF/gettexttemplates/idf/main-menu.html.php:8 +#: IDF/gettexttemplates/idf/project-list.html.php:4 +msgid "Project logo" +msgstr "Logo du projet" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:10 +msgid "Your project does not have a logo configured yet." +msgstr "Votre projet ne dispose pas encore d'un logo." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:3 +msgid "" +"This section allows you to configure project tabs access rights and " +"notifications." +msgstr "" +"Cette section vous autorise à configurer les droits d'accès et les " +"notifications des onglets de projets." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:4 +msgid "" +"Tab access controls whether a single user can navigate into a particular " +"section of your project via the main menu or automatically generated object " +"links." +msgstr "" +"L'onglet d'accès contrôle si un seul utilisateur peut naviguer dans une " +"section particulière de votre projet à partir du menu principal où des liens " +"d'objets automatiquement générés." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:5 +msgid "" +"If you mark a project as private, only the project members and " +"administrators, together with the extra authorized users you provide will " +"have access to the project as a whole. You will still be able to define " +"further access rights for the different tabs but the \"Open to all\" and " +"\"Signed in users\" will default to authorized users only." +msgstr "" +"Si vous indiquer que votre projet est privé, seul les administrateurs et les " +"membres du projet, ainsi que les autres utilisateurs auxquels vous en aurez " +"donné l'accès, auront accès au projet dans son ensemble. Vous serez toujours " +"capable de définir d'autres droits d'accès pour d'autres onglets, mais les " +"onglets \"Ouvert à tous\" et \"Utilisateurs authentifiés\" ne seront, par " +"défaut, accessible qu'aux utilisateur autorisés." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:6 +msgid "" +"For the extra authorized user list, specify each person by its login. Each " +"person must have already registered with the given login. Separate the " +"logins with commas and/or new lines." +msgstr "" +"Pour remplir la liste des autres utilisateurs, spécifié chacun des " +"utilisateurs par son identifiant. Chaque utilisateur doit déjà être " +"enregistrer avec l'identifiant donné. Séparer chaque identifiant avec des " +"virgules et/ou avec des nouvelles lignes." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:7 +msgid "" +"Only project members and admins have write access to the source. If you " +"restrict the access to the source, anonymous access is not provided and the " +"users must authenticate themselves with their password or SSH key." +msgstr "" +"Seul les membres et les administrateurs ont les accès en écriture à cette " +"ressource. Si vous restreignez l’accès à la source, les accès anonyme ne " +"seront pas disponible et les utilisateurs devront s'authentifier avec leur " +"mot de passe ou leur clé SSH." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:8 +#, php-format +msgid "" +"Here you can configure who should be notified about changes in a particular " +"section. You can also configure additional addresses, like the one of a " +"mailing list, that should be notified. (Keep in mind that you might have to " +"register the sender address %%from_email%% to let the " +"mailing list actually accept notification emails.) Multiple email addresses " +"must be separated through commas (',')." +msgstr "" +"Ici, vous pouvez configurer qui va être notifier lors d'un changement dans " +"une section spécifique. Vous pouvez aussi configurer des adresses " +"supplémentaires, comme celle d'une liste de diffusion (mailling list), qui " +"doit être avertie. (Rappelez vous que vous pouvez avoir enregistrer une " +"adresse email d'envoi %%from_email%% pour que la liste de " +"diffusion (mailling list) puisse accepter les mails de notifications.) Quand " +"plusieurs adresses email sont spécifiés, elles doivent être séparées par des " +"virgules (',')." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:9 +msgid "" +"The form contains some errors. Please correct them to update the access " +"rights." +msgstr "" +"Le formulaire contient des erreurs. Veuillez les corriger pour mettre à jour " +"les droits d'accès." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:10 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:13 +msgid "Access Rights" +msgstr "Droits d'accès" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:11 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:14 +msgid "Notifications" +msgstr "Notifications" + +#: IDF/gettexttemplates/idf/base-full.html.php:3 +#: IDF/gettexttemplates/idf/base-full.html~.php:3 +#: IDF/gettexttemplates/idf/base.html.php:3 +#: IDF/gettexttemplates/idf/base.html~.php:3 +#, php-format +msgid "" +"Sign in or create your account to create issues or " +"add comments" +msgstr "" +"Connectez-vous ou créez votre compte pour soumettre " +"des tickets ou ajouter des commentaires" + +#: IDF/gettexttemplates/idf/base-full.html.php:6 +#: IDF/gettexttemplates/idf/base.html.php:6 +#: IDF/gettexttemplates/idf/project-list.html.php:6 +msgid "External link to project" +msgstr "Liens externe vers le projet" + +#: IDF/gettexttemplates/idf/base-full.html.php:7 +#: IDF/gettexttemplates/idf/base-full.html~.php:6 +#: IDF/gettexttemplates/idf/base.html.php:7 +#: IDF/gettexttemplates/idf/base.html~.php:6 +msgid "Project Home" +msgstr "Page d'accueil" + +#: IDF/gettexttemplates/idf/base-full.html.php:13 +#: IDF/gettexttemplates/idf/base-full.html~.php:12 +#: IDF/gettexttemplates/idf/base.html.php:13 +#: IDF/gettexttemplates/idf/base.html~.php:12 +msgid "Project Management" +msgstr "Administration du projet" + +#: IDF/gettexttemplates/idf/downloads/base.html.php:4 +#: IDF/gettexttemplates/idf/downloads/index.html.php:4 +#: IDF/Views/Download.php:235 +msgid "New Download" +msgstr "Nouveau téléchargement" + +#: IDF/gettexttemplates/idf/downloads/base.html.php:5 +msgid "Upload Archive" +msgstr "Ajouter une archive" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:3 +msgid "" +"Each file must have a distinct name and file contents\n" +"cannot be changed, so be sure to include release numbers in each file\n" +"name." +msgstr "" +"Chaque fichier doit avoir un nom unique et le contenu des fichiers\n" +"ne peut pas être modifié. Faites attention de bien inclure le numéro\n" +"de révision dans le nom de chaque fichier." + +#: IDF/gettexttemplates/idf/downloads/create.html.php:6 +#, php-format +msgid "" +"You can use the Markdown syntax for the description." +msgstr "" +"Vous pouvez utiliser la syntaxe Markdown pour la " +"description." + +#: IDF/gettexttemplates/idf/downloads/create.html.php:7 +msgid "The form contains some errors. Please correct them to submit the file." +msgstr "" +"Le formulaire contient des erreurs. Veuillez les corriger pour envoyer le " +"fichier." + +#: IDF/gettexttemplates/idf/downloads/create.html.php:8 +msgid "Submit File" +msgstr "Envoyer le fichier" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:9 +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:8 +#: IDF/gettexttemplates/idf/downloads/delete.html.php:7 +#: IDF/gettexttemplates/idf/downloads/view.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:21 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:14 +#: IDF/gettexttemplates/idf/issues/create.html.php:14 +#: IDF/gettexttemplates/idf/issues/view.html.php:27 +#: IDF/gettexttemplates/idf/register/confirmation.html.php:7 +#: IDF/gettexttemplates/idf/register/index.html.php:8 +#: IDF/gettexttemplates/idf/register/inputkey.html.php:5 +#: IDF/gettexttemplates/idf/review/create.html.php:12 +#: IDF/gettexttemplates/idf/review/view.html.php:41 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:5 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:13 +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:7 +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:9 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:5 +msgid "Cancel" +msgstr "Annuler" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:10 +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:9 +#: IDF/gettexttemplates/idf/register/inputkey.html.php:6 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:6 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:6 +msgid "Instructions" +msgstr "Instructions" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:3 +msgid "" +"The archive must include a manifest.xml file with meta " +"information about the\n" +"files to process inside the archive. All processed files must be unique or " +"replace existing files explicitely." +msgstr "" +"L'archive doit inclure un fichier manifest.xml comportant des " +"méta-informations à propos du fichier à traiter à l’intérieur de l'archive.\n" +"Tous les fichiers traiter doivent être unique ou doivent remplacer des " +"fichiers existant explicitement." + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:5 +#, php-format +msgid "" +"You can learn more about the archive format here." +msgstr "" +"Vous pouvez en lire d'avantage à propos du format de l'archive ici." + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:6 +msgid "" +"The form contains some errors. Please correct them to submit the archive." +msgstr "" +"La forme contient quelques erreurs. Corrigez les pour pouvoir soumettre " +"l'archive." + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:7 +msgid "Submit Archive" +msgstr "Soumettre archive" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:3 +msgid "" +"Attention! If you want to delete a specific version of your " +"software, maybe, someone is depending on this specific version to run his " +"systems. Are you sure, you will not affect anybody when removing this file?" +msgstr "" +"Attention! Si vous voulez supprimer une version spécifique " +"de votre logiciel, peut-être que quelqu'un dépend encore de cette version. " +"Êtes-vous certain que supprimer ce fichier ne va pas importuner certaines " +"personnes?" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:4 +#, php-format +msgid "" +"Instead of deleting the file, you could mark it as " +"deprecated." +msgstr "" +"Au lieu de supprimer le fichier, vous pouvez le marquer " +"comme obsolète." + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:5 +#: IDF/gettexttemplates/idf/downloads/view.html.php:4 +#: IDF/gettexttemplates/idf/issues/attachment.html.php:4 +#: IDF/gettexttemplates/idf/issues/view.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:5 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:7 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:7 +#, php-format +msgid "by %%submitter%%" +msgstr "par %%submitter%%" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:6 +msgid "Delete File" +msgstr "Supprimer le fichier" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:8 +#: IDF/gettexttemplates/idf/downloads/view.html.php:14 +msgid "Uploaded:" +msgstr "Mis en ligne:" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:9 +#: IDF/gettexttemplates/idf/downloads/view.html.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:29 +#: IDF/gettexttemplates/idf/review/view.html.php:27 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:12 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:14 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:14 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:15 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:17 +msgid "Updated:" +msgstr "Mis à jour:" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:10 +#: IDF/gettexttemplates/idf/downloads/view.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:6 +#: IDF/gettexttemplates/idf/listProjects.html.php:17 +msgid "Downloads:" +msgstr "Téléchargements:" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:11 +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:7 +#: IDF/gettexttemplates/idf/downloads/view.html.php:17 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:6 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:6 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:11 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:16 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:10 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:21 +#: IDF/gettexttemplates/idf/issues/view.html.php:33 +#: IDF/gettexttemplates/idf/project-list.html.php:8 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:6 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:13 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:16 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:12 +#: IDF/IssueComment.php:157 IDF/Wiki/PageRevision.php:204 +msgid "Labels:" +msgstr "Étiquettes:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:3 +msgid "A new file is available for download:" +msgstr "Un nouveau fichier est disponible en téléchargement:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:4 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:6 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:5 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:8 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:4 +msgid "Hello," +msgstr "Bonjour," + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:6 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:5 +msgid "Project:" +msgstr "Projet:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:6 +msgid "Submitted by:" +msgstr "Soumis par:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:8 +msgid "Download:" +msgstr "Téléchargement:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/view.html.php:31 +#: IDF/gettexttemplates/idf/user/public.html.php:4 +msgid "Description:" +msgstr "Description:" + +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:3 +msgid "A file download was updated:" +msgstr "Un fichier télécharger à été mis à jour :" + +#: IDF/gettexttemplates/idf/downloads/feedfragment.xml.php:3 +msgid "Details" +msgstr "Détails" + +#: IDF/gettexttemplates/idf/downloads/index.html.php:3 +#, php-format +msgid "See the deprecated files." +msgstr "Voir les fichiers obsolètes." + +#: IDF/gettexttemplates/idf/downloads/index.html.php:5 +msgid "Number of files:" +msgstr "Nombre de fichiers:" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:3 +msgid "" +"Attention! This file is marked as deprecated, download it " +"only if you are sure you need this specific version." +msgstr "" +"Attention! Ce fichier est marqué comme obsolète. " +"Téléchargez-le uniquement si vous avez vraiment besoin de cette version." + +#: IDF/gettexttemplates/idf/downloads/view.html.php:5 +msgid "md5:" +msgstr "md5:" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:6 +msgid "Changes" +msgstr "Modifications" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:7 +msgid "The form contains some errors. Please correct them to update the file." +msgstr "" +"Le formulaire contient des erreurs. Veuillez les corriger pour mettre à jour " +"le fichier." + +#: IDF/gettexttemplates/idf/downloads/view.html.php:8 +msgid "Update File" +msgstr "Mettre à jour le fichier" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:10 +#: IDF/gettexttemplates/idf/downloads/view.html.php:12 +msgid "Remove this file" +msgstr "Supprimer ce fichier" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:11 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:18 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:7 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:12 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:12 +msgid "Trash" +msgstr "Corbeille" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:13 +msgid "Delete this file" +msgstr "Supprimer ce fichier" + +#: IDF/gettexttemplates/idf/faq-api.html.php:3 +#: IDF/gettexttemplates/idf/faq-archive-format.html.php:3 +#: IDF/gettexttemplates/idf/faq.html.php:65 +msgid "Here we are, just to help you." +msgstr "Nous sommes là, juste pour vous aider." + +#: IDF/gettexttemplates/idf/faq-api.html.php:4 +#: IDF/gettexttemplates/idf/faq-archive-format.html.php:4 +#: IDF/gettexttemplates/idf/faq.html.php:66 +#: IDF/gettexttemplates/idf/gadmin/base.html.php:4 +#: IDF/gettexttemplates/idf/index.html.php:4 IDF/Views/Admin.php:77 +#: IDF/Views.php:91 +msgid "Projects" +msgstr "Projets" + +#: IDF/gettexttemplates/idf/faq.html.php:3 +msgid "" +"

This is simple:

\n" +"
    \n" +"
  1. Write in the comments \"This is a duplicate of issue 123\" or - if you " +"are a member of the crew -\n" +"directly add the \"duplicates\" relation with the value \"123\" below the " +"comment field. Change \"123\"\n" +"with the corresponding issue number.
  2. \n" +"
  3. Change the status of the current issue to Duplicate.
  4. \n" +"
  5. Submit the changes.
  6. \n" +"
" +msgstr "" +"

C'est simple :

\n" +"
    \n" +"
  1. Ajouter un commentaire \"C'est un doublon du ticket 123\" ou - si vous " +"faite partit de l'équipe - ajouter la relation \"Duplicates\" avec " +"l'identifiant du ticket en question.
  2. \n" +"
  3. Changer le statut du ticket a Duplicate.
  4. \n" +"
  5. Valider
  6. \n" +"
" + +#: IDF/gettexttemplates/idf/faq.html.php:11 +msgid "" +"You need to create an account on Gravatar, this takes about 5 minutes and is free." +msgstr "" +"Vous devez créer un compte sur Gravatar. Cela prend environ 5 minutes et c'est gratuit." + +#: IDF/gettexttemplates/idf/faq.html.php:12 +msgid "" +"\n" +"

To embed any previously uploaded resource into your wiki page, you can " +"use the [[!ResourceName]] syntax.

\n" +"\n" +"

The rendering of the resource can then be further fine-tuned:\n" +"

    \n" +"
  • [[!ImageResource, align=right, width=200]] renders " +"\"ImageResource\" right-aligned and scale its width to 200
  • \n" +"
  • [[!TextResource, align=center, width=300, height=300]] " +"renders \"TextResource\" in a centered, 300 by 300 px iframe
  • \n" +"
  • [[!AnyResource, preview=no]] does not render a preview of " +"the resource, but only provides a download link (default for binary " +"resources)
  • \n" +"
  • [[!BinaryResource, title=Download]] renders the download " +"link of \"BinaryResource\" with an alternative title
  • \n" +"
\n" +"

\n" +"\n" +"Resources are versioned, just like wiki pages. If you update a resource, old " +"wiki pages still show the state of the resource\n" +"at the time when the wiki page was edited. If you specifically want to " +"update a resource on a page, you therefor need to update\n" +"the resource at first and then also the page where it is referenced, " +"otherwise the change won't be visible until the next regular edit. \n" +msgstr "" +"\n" +"

Pour insérer des ressources dans votre page de Wiki, vous pouvez utiliser " +"la syntaxe suivante [[!ResourceName]].

\n" +"\n" +"

Vous pouvez ajuster l'affichage des resources avec les paramètres " +"suivants :\n" +"

    \n" +"
  • [[!ImageResource, align=right, width=200]] affiche " +"\"ImageResource\" aligné a droite, et mit a l'échelle pour avoir une largeur " +"de 200 pixels.
  • \n" +"
  • [[!TextResource, align=center, width=300, height=300]] " +"affiche \"TextResource\" aligné au centre de la page avec une taille de 300 " +"par 300 pixels.
  • \n" +"
  • [[!AnyResource, preview=no]] permet de fournir uniquement " +"un lien de téléchargement vers la ressource.
  • \n" +"
  • [[!BinaryResource, title=Download]] affiche le lien " +"téléchargement \"BinaryResource\" avec un `title` alternatif
  • \n" +"
\n" +"

\n" +"\n" +"Les resources sont versionnées, comme les pages de Wiki. Si vous mettez a " +"jour une ressource, les pages de wiki continueront d'afficher la resource " +"dans l'état ou elle était lors de la dernière édition. Une simple édition de " +"la page mettra a jour les ressources contenu dans celle ci.\n" + +#: IDF/gettexttemplates/idf/faq.html.php:28 +msgid "" +"

If you have to publish many files at once for a new release, it is a very " +"tedious task\n" +"to upload them one after another and enter meta information like a summary, " +"a description or additional\n" +"labels for each of them.

\n" +"

InDefero therefore supports a special archive format that is basically a " +"standard zip file which comes with\n" +"some meta information. These meta information are kept in a special manifest " +"file, which is distinctly kept from\n" +"the rest of the files in the archive that should be published.

\n" +"

Once this archive has been uploaded, InDefero reads in the meta " +"information, unpacks the other files from\n" +"the archive and creates new individual downloads for each of them.

" +msgstr "" +"

Si vous avez a publié de nombreux fichiers à la fois, il peut être long " +"et ennuyeux de les envoyés un par un, de leur mettre un nom, une description " +"et des labels.

\n" +"

InDefero supporte l'envoie d'une archive au format ZIP qui contient des " +"meta-informations. Ces informations sont contenu dans un fichier de " +"manifest, qui est a part des autres fichiers a publier.

\n" +"

Lors de l'envoie de cette archive, InDefero va créer un nouveau " +"téléchargement pour chaque fichier contenu dans l'archive et remplira les " +"meta-information de ceux-ci à l'aide du fichier manifest.

" + +#: IDF/gettexttemplates/idf/faq.html.php:36 +#, php-format +msgid "
Learn more about the archive format." +msgstr "" +"En apprendre d'avantage à propos du format des archives." + +#: IDF/gettexttemplates/idf/faq.html.php:37 +msgid "" +"The API (Application Programming Interface) is used to interact with " +"InDefero with another program. For example, this can be used to create a " +"desktop program to submit new tickets easily." +msgstr "" +"L'API (interface de programmation applicative) est utilisée pour communiquer " +"avec InDefero depuis d'autres programmes. Par exemple, cela peut être " +"utilisé pour créer une application de bureau permettant de soumettre " +"facilement de nouveaux tickets." + +#: IDF/gettexttemplates/idf/faq.html.php:38 +#, php-format +msgid "Learn more about the API." +msgstr "En apprendre plus à propos de l'API." + +#: IDF/gettexttemplates/idf/faq.html.php:39 +#: IDF/gettexttemplates/idf/faq.html.php:45 +msgid "What are the keyboard shortcuts?" +msgstr "Quels sont les raccourcis clavier?" + +#: IDF/gettexttemplates/idf/faq.html.php:40 +#: IDF/gettexttemplates/idf/faq.html.php:60 +msgid "How to mark an issue as duplicate?" +msgstr "Comment marquer un ticket comme doublon?" + +#: IDF/gettexttemplates/idf/faq.html.php:41 +#: IDF/gettexttemplates/idf/faq.html.php:61 +msgid "How can I display my head next to my comments?" +msgstr "Comment puis-je afficher mon visage à côté de mes commentaires?" + +#: IDF/gettexttemplates/idf/faq.html.php:42 +#: IDF/gettexttemplates/idf/faq.html.php:62 +msgid "How can I embed images and other resources in my documentation pages?" +msgstr "" +"Comment puis-je intégrés des images et d'autres ressources dans ma page de " +"documentations ?" + +#: IDF/gettexttemplates/idf/faq.html.php:43 +#: IDF/gettexttemplates/idf/faq.html.php:63 +msgid "What is this \"Upload Archive\" functionality about?" +msgstr "Quelle est l’utilité de cette \"Archive envoyée\" ?" + +#: IDF/gettexttemplates/idf/faq.html.php:44 +#: IDF/gettexttemplates/idf/faq.html.php:64 +msgid "What is the API and how is it used?" +msgstr "Qu'est-ce que l'API et comment l'utiliser?" + +#: IDF/gettexttemplates/idf/faq.html.php:46 +msgid "Shift+h: This help page." +msgstr "Maj+h: cette page d'aide." + +#: IDF/gettexttemplates/idf/faq.html.php:47 +msgid "If you are in a project, you have the following shortcuts:" +msgstr "Si vous êtes dans un projet, vous disposez des raccourcis suivants:" + +#: IDF/gettexttemplates/idf/faq.html.php:48 +msgid "Shift+u: Project updates." +msgstr "Maj+u: mises à jour du projet." + +#: IDF/gettexttemplates/idf/faq.html.php:49 +msgid "Shift+d: Downloads." +msgstr "Maj+d: téléchargements." + +#: IDF/gettexttemplates/idf/faq.html.php:50 +msgid "Shift+o: Documentation." +msgstr "Maj+o: documentation." + +#: IDF/gettexttemplates/idf/faq.html.php:51 +msgid "Shift+a: Create a new issue." +msgstr "Maj+a: créer un nouveau ticket." + +#: IDF/gettexttemplates/idf/faq.html.php:52 +msgid "Shift+i: List of open issues." +msgstr "Maj+i: liste des tickets ouverts." + +#: IDF/gettexttemplates/idf/faq.html.php:53 +msgid "Shift+m: The issues you submitted." +msgstr "Maj+m: les tickets que vous avez soumis." + +#: IDF/gettexttemplates/idf/faq.html.php:54 +msgid "Shift+w: The issues assigned to you." +msgstr "Maj+w: les tickets qui vous sont assignés." + +#: IDF/gettexttemplates/idf/faq.html.php:55 +msgid "Shift+s: Source." +msgstr "Maj+s: source." + +#: IDF/gettexttemplates/idf/faq.html.php:56 +msgid "You also have the standard access keys:" +msgstr "Vous avez aussi les touches d'accès standard:" + +#: IDF/gettexttemplates/idf/faq.html.php:57 +msgid "Alt+1: Home." +msgstr "Alt+1: accueil." + +#: IDF/gettexttemplates/idf/faq.html.php:58 +msgid "Alt+2: Skip the menus." +msgstr "Alt+2: aller au contenu." + +#: IDF/gettexttemplates/idf/faq.html.php:59 +msgid "Alt+4: Search (when available)." +msgstr "Alt+4: rechercher (si disponible)." + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:3 +msgid "Forge" +msgstr "Forge" + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:5 +msgid "People" +msgstr "Utilisateurs" + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:6 +msgid "Usher" +msgstr "Usher" + +#: IDF/gettexttemplates/idf/gadmin/forge/base.html.php:3 +msgid "Frontpage" +msgstr "Frontpage" + +#: IDF/gettexttemplates/idf/gadmin/forge/index.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

You can set up a custom forge page that is used as entry page for the " +"forge instead of the plain project listing. This page is then also " +"accessible via the 'Home' link in main menu bar.

\n" +"

The content of the page can use the Markdown syntax with the Extra extension.

\n" +"

Additionally, the following macros are available:
\n" +"

    \n" +"
  • {projectlist, label=..., order=(name|activity), limit=...} - Renders a project list that can optionally be filtered by label, " +"ordered by 'name' or 'activity' and / or limited to a specific number of " +"projects.
  • \n" +"
\n" +"

\n" +msgstr "" +"\n" +"

Procédure :

\n" +"

Vous pouvez définir une page personnalisée qui sera utilisé à la place de " +"la page ou sont listés les projets.Cette page est aussi accessible par le " +"lien 'Home', dans la bar de menu principale.

\n" +"\n" +"

Le contenu de cette page peut utilisé la syntaxe " +"Markdown avec cette Extra extension.\n" +"\n" +"

Les macros suivantes sont aussi disponibles :
\n" +"

    \n" +"
  • {projectlist, label=..., order=(name|activity), limit=...} - Affiche la liste des projets qui peut être filtrée par labels, et " +"ordonnées par nom ou activité, le nombre de résultat affiché peut être " +"limité.
  • \n" +"
\n" +"

\n" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:3 +#: IDF/gettexttemplates/idf/main-menu.html.php:7 +msgid "Project List" +msgstr "Liste des projets" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:4 +#: IDF/Views/Admin.php:110 +msgid "Project Labels" +msgstr "Étiquettes de projet." + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:16 +#: IDF/gettexttemplates/idf/listProjects.html.php:6 IDF/Views/Admin.php:186 +msgid "Create Project" +msgstr "Créer un projet" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:6 +msgid "Change Project Details" +msgstr "Modifier les détails du projet" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:3 +msgid "" +"You can select the type of repository you want. In the case of subversion, " +"you can use optionally a remote repository instead of the local one." +msgstr "" +"Vous pouvez sélectionner le type de dépôt souhaité. Dans le cas d'un dépôt " +"Subversion, vous pouvez optionnellement choisir un dépôt distant au lieu de " +"celui local." + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:4 +msgid "" +"Once you have defined the repository type, you cannot change it." +msgstr "" +"Une fois que vous avez défini le type de dépôt, vous ne pouvez pas " +"le modifier." + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:5 +msgid "" +"\n" +"

Specify each person by its login. Each person must have already " +"registered with the given login.

\n" +"

Separate the logins with commas and/or new lines.

\n" +msgstr "" +"\n" +"

Indiquez chaque personne à l'aide de son identifiant. Chaque personne " +"doit avoir préalablement créé son compte.

\n" +"

Séparez les identifiants par des virgules ou des sauts de ligne.

\n" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:14 +msgid "" +"The form contains some errors. Please correct them to create the project." +msgstr "" +"Le formulaire contient des erreurs. Veuillez les corriger pour créer le " +"projet." + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:15 +msgid "Provide at least one owner for the project or use a template." +msgstr "" +"Fournissez au moins un propriétaire pour le projet ou utilisez un modèle." + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:15 +msgid "Instructions:" +msgstr "Instructions:" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:3 +#, php-format +msgid "" +"Confirmation code to confirm the deletion of the project: \n" +"%%code%%." +msgstr "" +"Code de confirmation pour supprimer le projet:\n" +"%%code%%." + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:5 +msgid "" +"\n" +"Attention! Deleting a project is a one second operation\n" +"with the consequences that all the data related to the \n" +"project will be deleted.\n" +msgstr "" +"\n" +"Attention! Supprimer un projet est une opération\n" +"rapide qui a pour conséquence la suppression de toutes les données\n" +"relatives au projet.\n" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:10 +msgid "" +"The form contains some errors. Please correct them to delete the project." +msgstr "" +"Le formulaire contient des erreurs. Veuillez les corriger pour supprimer le " +"projet." + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:11 +msgid "Project Statistics" +msgstr "Statistiques du projet" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:12 +msgid "Tab" +msgstr "Onglet" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:13 +msgid "Number" +msgstr "Nombre" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:15 +msgid "Code reviews" +msgstr "Revues de code" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:16 +#: IDF/Views/Project.php:93 +msgid "Commits" +msgstr "Commits" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:18 +msgid "Documentation pages" +msgstr "Pages de documentation" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:19 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:20 +msgid "Delete Project" +msgstr "Supprimer le projet" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:22 +msgid "" +"For large projects, the suppression can take a while, please be patient." +msgstr "" +"Pour de gros projets, la suppression peut durer un moment. Merci de " +"patienter." + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:3 +msgid "Space Usage Statistics" +msgstr "Statistiques d'utilisation de l'espace disque" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:4 +msgid "Repositories:" +msgstr "Dépôts:" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:5 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:11 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:18 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:16 +msgid "Attachments:" +msgstr "Pièces jointes:" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:7 +msgid "Database:" +msgstr "Base de données:" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:8 +msgid "Total Forge:" +msgstr "Total de la forge:" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:13 +msgid "" +"The form contains some errors. Please correct them to update the project." +msgstr "" +"Le formulaire contient des erreurs. Veuillez les corriger pour mettre à jour " +"le projet." + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:14 +msgid "Provide at least one owner for the project." +msgstr "Fournissez au moins un propriétaire pour le projet." + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:15 +msgid "Update Project" +msgstr "Mettre à jour le projet" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:19 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:20 +msgid "Delete this project" +msgstr "Supprimer ce projet" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:21 +msgid "You will be asked to confirm." +msgstr "Confirmation demandée." + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:3 +#: IDF/Views/Admin.php:264 +msgid "User List" +msgstr "Liste des utilisateurs" + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:13 +msgid "Update User" +msgstr "Mettre à jour l'utilisateur" + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:4 +msgid "Create User" +msgstr "Créer un utilisateur" + +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:3 +msgid "The form contains some errors. Please correct them to create the user." +msgstr "" +"Le formulaire contient des erreurs. Veuillez les corriger pour créer " +"l'utilisateur." + +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:6 +msgid "The user password will be sent by email to the user." +msgstr "Le mot de passe sera envoyé par email à l'utilisateur." + +#: IDF/gettexttemplates/idf/gadmin/users/createuser-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"An account on the forge has been created for you by\n" +"the administrator %%admin%%.\n" +"\n" +"Please find here your details to access the forge:\n" +"\n" +" Address: %%url%%\n" +" Login: %%user.login%%\n" +" Password: %%password%%\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" +"Bonjour %%user%%,\n" +"\n" +"Un compte a été créé pour vous sur la forge par\n" +"l'administrateur %%admin%%.\n" +"\n" +"Vous trouverez ci-dessous les informations pour\n" +"vous connecter:\n" +"\n" +" Adresse: %%url%%\n" +" Identifiant: %%user.login%%\n" +" Mot de passe: %%password%%\n" +"\n" +"Cordialement,\n" +"\n" +"L'équipe de développement\n" + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:3 +#, php-format +msgid "See not validated users." +msgstr "Voir les utilisateurs non confirmés." + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:4 +msgid "

You have here an overview of the users registered in the forge.

" +msgstr "" +"

Vous avez ici une vue d'ensemble des utilisateurs enregistrés sur la " +"forge.

" + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:5 +msgid "Number of users:" +msgstr "Nombre d'utilisateurs:" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:3 +msgid "" +"If you are changing the email address of the user, you\n" +"need to ensure that you are providing a valid email\n" +"address" +msgstr "" +"Si vous changez l'adresse email de l'utilisateur,\n" +"vous devez vous assurer que l'adresse est bien valide." + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:6 +msgid "" +"If you give the user staff rights, the user will be\n" +"able to create new projects and update other non staff users.\n" +msgstr "" +"Si vous donnez des droits de gestionnaire à l'utilisateur,\n" +"ce dernier pourra créer de nouveaux projets et éditer les\n" +"informations des utilisateurs non gestionnaires.\n" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:9 +msgid "The form contains some errors. Please correct them to update the user." +msgstr "" +"Le formulaire contient des erreurs. Veuillez les corriger pour mettre à jour " +"l'utilisateur." + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:10 +#: IDF/gettexttemplates/idf/register/confirmation.html.php:4 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:4 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:4 +msgid "Login:" +msgstr "Identifiant:" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:11 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:5 +msgid "Public Profile" +msgstr "Profil public" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:12 +msgid "Administrative" +msgstr "Administratif" + +#: IDF/gettexttemplates/idf/gadmin/usher/base.html.php:3 +msgid "Configured servers" +msgstr "Serveurs configurés" + +#: IDF/gettexttemplates/idf/gadmin/usher/base.html.php:4 +#: IDF/Views/Admin.php:421 +msgid "Usher control" +msgstr "Contrôle d'usher" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html~.php:3 +msgid "address" +msgstr "adresse" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html~.php:4 +msgid "port" +msgstr "port" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:5 +msgid "No connections found." +msgstr "Aucune connexion trouvée." + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:3 +msgid "current server status:" +msgstr "statut actuel du serveur:" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:4 +msgid "startup" +msgstr "démarrage" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:5 +msgid "shutdown" +msgstr "arrêt" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:6 +msgid "reload server configuration:" +msgstr "recharger la configuration du serveur:" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:7 +msgid "reload" +msgstr "recharger" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:11 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:11 +msgid "Status explanation" +msgstr "Explication du statut" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:9 +msgid "active with n total open connections" +msgstr "actif avec n connexions actives au total" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:10 +msgid "waiting for new connections" +msgstr "en attente de nouvelles connexions" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:11 +msgid "usher is being shut down, not accepting connections" +msgstr "usher est en cours d'arrêt, n'acceptant plus de connexion" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:12 +msgid "" +"usher is shut down, all local servers are stopped and not accepting " +"connections" +msgstr "" +"usher est éteint, tous les serveurs locaux sont arrêtés et n'acceptent " +"aucune connexion" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:3 +msgid "server name" +msgstr "nom du serveur" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:4 IDF/Issue.php:99 +#: IDF/Review.php:102 +msgid "status" +msgstr "statut" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:5 +msgid "action" +msgstr "action" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:6 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:6 +msgid "No monotone servers configured." +msgstr "Aucun serveur monotone configuré." + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:7 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:7 +msgid "stop" +msgstr "arrêter" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:8 +msgid "start" +msgstr "démarrer" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:9 +msgid "kill" +msgstr "tuer" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:10 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:10 +msgid "active connections" +msgstr "connexions actives" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:12 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:12 +msgid "remote server without open connections" +msgstr "serveur distant sans connexion active" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:13 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:13 +msgid "server with n open connections" +msgstr "serveur avec n connexions actives" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:14 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:14 +msgid "local server running, without open connections" +msgstr "serveur local en service, sans connexion active" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:15 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:15 +msgid "local server not running, waiting for connections" +msgstr "serveur local non en service, en attente de connexions" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:16 +msgid "local server is about to stop, n connections still open" +msgstr "serveur local sur le point d'arrêter, n connexions encore ouvertes" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:17 +msgid "local server not running, not accepting connections" +msgstr "serveur local non en service, n'acceptant aucune connexion" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:18 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:18 +msgid "usher is shut down, not running and not accepting connections" +msgstr "usher éteint, non en service et n'acceptant aucune connexion" + +#: IDF/gettexttemplates/idf/index.atom.php:3 +#, php-format +msgid "Personal project feed for %%user%%." +msgstr "Flux personnel de %%user%% pour ce projet." + +#: IDF/gettexttemplates/idf/index.html.php:3 +#: IDF/gettexttemplates/idf/main-menu.html.php:6 +msgid "Home" +msgstr "Accueil" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:3 +#, php-format +msgid "Attachment to issue %%issue.id%%" +msgstr "Pièce jointe au ticket %%issue.id%%" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:5 +#: IDF/gettexttemplates/idf/review/view.html.php:35 +#: IDF/gettexttemplates/idf/source/commit.html.php:23 +#: IDF/gettexttemplates/idf/source/commit.html~.php:22 +#: IDF/gettexttemplates/idf/source/git/file.html.php:6 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:7 +msgid "Archive" +msgstr "Archive" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:6 +#: IDF/gettexttemplates/idf/source/git/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:12 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:12 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:10 +msgid "Download this file" +msgstr "Télécharger ce fichier" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:7 +#: IDF/gettexttemplates/idf/issues/view.html.php:28 +#: IDF/gettexttemplates/idf/review/view.html.php:26 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:13 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:14 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:16 +msgid "Created:" +msgstr "Créé:" + +#: IDF/gettexttemplates/idf/issues/base.html.php:4 +msgid "All Issues" +msgstr "Tous les tickets" + +#: IDF/gettexttemplates/idf/issues/base.html.php:5 +msgid "My Issues" +msgstr "Mes tickets" + +#: IDF/gettexttemplates/idf/issues/base.html.php:6 +msgid "My watch list" +msgstr "Ma liste de surveillance" + +#: IDF/gettexttemplates/idf/issues/base.html.php:7 +#: IDF/gettexttemplates/idf/issues/by-label.html.php:6 +#: IDF/gettexttemplates/idf/issues/index.html.php:5 +#: IDF/gettexttemplates/idf/issues/project-watchlist.html.php:5 +#: IDF/gettexttemplates/idf/issues/search.html.php:8 +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:5 +msgid "New Issue" +msgstr "Nouveau ticket" + +#: IDF/gettexttemplates/idf/issues/base.html.php:8 +#: IDF/gettexttemplates/idf/wiki/base.html.php:9 +msgid "Search" +msgstr "Rechercher" + +#: IDF/gettexttemplates/idf/issues/base.html.php:9 +msgid "Back to the issue" +msgstr "Retour au ticket" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:3 +#, php-format +msgid "" +"

Open issues: %%open%%

\n" +"

Closed issues: %%closed%%

\n" +msgstr "" +"

Tickets ouverts: %%open%%\n" +"

Tickets fermés: %%closed%%

\n" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:7 +msgid "Label:" +msgstr "Étiquette:" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:8 +msgid "Completion:" +msgstr "Achèvement:" + +#: IDF/gettexttemplates/idf/issues/create.html.php:3 +msgid "" +"

When you submit the issue do not forget to provide the following " +"information:

\n" +"
    \n" +"
  • The steps to reproduce the problem.
  • \n" +"
  • The version of the software and your operating system.
  • \n" +"
  • Any information that can help the developers to solve the issue.
  • \n" +"
  • Do not provide any password or confidential information!
  • \n" +"
" +msgstr "" +"

Quand vous soumettez un ticket, n'oubliez de fournir les informations " +"suivantes:

\n" +"
    \n" +"
  • Les étapes pour reproduire le problème.
  • \n" +"
  • La version du logiciel et de votre système d'exploitation.
  • \n" +"
  • Toute information susceptible d'aider les développeurs à régler le " +"problème.
  • \n" +"
  • Ne fournissez aucun mot de passe ou information confidentielle!
  • \n" +"
" + +#: IDF/gettexttemplates/idf/issues/create.html.php:10 +msgid "The form contains some errors. Please correct them to submit the issue." +msgstr "" +"Le formulaire contient des erreurs. Veuillez les corriger pour soumettre le " +"ticket." + +#: IDF/gettexttemplates/idf/issues/create.html.php:11 +#: IDF/gettexttemplates/idf/issues/create.html.php:13 +#: IDF/gettexttemplates/idf/issues/view.html.php:24 +#: IDF/gettexttemplates/idf/issues/view.html.php:26 +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:5 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:5 +msgid "Preview" +msgstr "Prévisualisation" + +#: IDF/gettexttemplates/idf/issues/create.html.php:12 +msgid "Submit Issue" +msgstr "Soumettre le ticket" + +#: IDF/gettexttemplates/idf/issues/create.html.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:34 +msgid "Attach file" +msgstr "Joindre un fichier" + +#: IDF/gettexttemplates/idf/issues/create.html.php:16 +#: IDF/gettexttemplates/idf/issues/create.html.php:17 +#: IDF/gettexttemplates/idf/issues/view.html.php:35 +#: IDF/gettexttemplates/idf/issues/view.html.php:36 +msgid "Attach another file" +msgstr "Joindre un autre fichier" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:3 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:3 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:13 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:12 +#: IDF/gettexttemplates/idf/issues/view.html.php:18 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:3 +#: IDF/gettexttemplates/idf/review/view.html.php:38 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:11 +#: IDF/IssueComment.php:151 +msgid "Summary:" +msgstr "Résumé:" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:4 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:4 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:8 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:14 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:13 +#: IDF/gettexttemplates/idf/issues/view.html.php:19 +#: IDF/gettexttemplates/idf/issues/view.html.php:30 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:4 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/view.html.php:39 IDF/IssueComment.php:153 +msgid "Status:" +msgstr "Statut:" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:5 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:15 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:14 +#: IDF/gettexttemplates/idf/issues/view.html.php:20 +#: IDF/gettexttemplates/idf/issues/view.html.php:31 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:5 +#: IDF/IssueComment.php:155 +msgid "Owner:" +msgstr "Propriétaire:" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:17 +#: IDF/gettexttemplates/idf/issues/view.html.php:22 IDF/IssueComment.php:159 +msgid "Relations:" +msgstr "Relations:" + +#: IDF/gettexttemplates/idf/issues/forge-watchlist.html.php:3 +#: IDF/gettexttemplates/idf/issues/index.html.php:3 +#: IDF/gettexttemplates/idf/issues/project-watchlist.html.php:3 +#, php-format +msgid "" +"

Open issues: %%open%%

\n" +"

Closed issues: %%closed%%

" +msgstr "" +"

Tickets ouverts: %%open%%\n" +"

Tickets fermés: %%closed%%

" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:3 +msgid "A new issue has been created and assigned to you:" +msgstr "Un nouveau ticket à été crée et vous à été assigné :" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:4 +msgid "A new issue has been created:" +msgstr "Un nouveau ticket à été crée :" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:8 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:11 +msgid "Reported by:" +msgstr "Rapporté par:" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:12 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:19 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:17 +msgid "Issue:" +msgstr "Ticket:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:3 +msgid "The following issue you are owning has been updated:" +msgstr "Ce ticket que vous avez crée à été mis à jour :" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:4 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:3 +msgid "The following issue has been updated:" +msgstr "Le ticket suivant a été mis à jour:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:4 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:4 +#, php-format +msgid "By %%who%%, %%c.creation_dtime%%:" +msgstr "Par %%who%%, %%c.creation_dtime%%" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:10 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:9 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:12 +msgid "URL:" +msgstr "URL:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:12 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:11 +msgid "Comments (last first):" +msgstr "Commentaires (le plus récent en premier):" + +#: IDF/gettexttemplates/idf/issues/search.html.php:3 +#, php-format +msgid "" +"\n" +"

Found open issues: %%open%%

\n" +"

Found closed issues: %%closed" +"%%

" +msgstr "" +"\n" +"

Tickets ouverts trouvés: %%open" +"%%

\n" +"

Tickets fermés trouvés: " +"%%closed%%

" + +#: IDF/gettexttemplates/idf/issues/search.html.php:6 +#, php-format +msgid "" +"

Label:\n" +"%%tag.class%%:" +"%%tag.name%%

" +msgstr "" +"

Étiquette:\n" +"%%tag.class%%:" +"%%tag.name%%

" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:3 +msgid "View all open issues." +msgstr "Voir tous les tickets ouvert." + +#: IDF/gettexttemplates/idf/issues/summary.html.php:4 +msgid "Create an issue." +msgstr "Créer un ticket." + +#: IDF/gettexttemplates/idf/issues/summary.html.php:5 +#, php-format +msgid "" +"The issue tracker is empty.
Create your " +"first issue." +msgstr "" +"Le répertoire des tickets est vide.
Créer " +"votre premier ticket." + +#: IDF/gettexttemplates/idf/issues/summary.html.php:6 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:4 +#, php-format +msgid "Unresolved: By %%key%%" +msgstr "Non résolus: par %%key%%" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:7 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:5 +msgid "Status Summary" +msgstr "Résumé par statut" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:8 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:6 +msgid "Unresolved: By Assignee" +msgstr "Non résolus: par assignation" + +#: IDF/gettexttemplates/idf/issues/summary.html~.php:3 +#, php-format +msgid "" +"The issue tracker is empty.
You can create your first issue here." +msgstr "" +"Le gestionnaire de tickets est vide.
Vous pouvez créer votre premier " +"ticket ici." + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:3 +#, php-format +msgid "" +"See the %%nb_submit_closed%% closed." +msgid_plural "" +"See the %%nb_submit_closed%% closed." +msgstr[0] "Voir le ticket fermé." +msgstr[1] "" +"Voir les %%nb_submit_closed%% fermés." + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:4 +#, php-format +msgid "" +"See the %%nb_owner_closed%% closed." +msgid_plural "" +"See the %%nb_owner_closed%% closed." +msgstr[0] "Voir le ticket fermé." +msgstr[1] "" +"Voir les %%nb_owner_closed%% fermés." + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:6 +#: IDF/gettexttemplates/idf/user/dashboard.html.php:7 +msgid "Submitted issues:" +msgstr "Tickets soumis:" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:7 +#: IDF/gettexttemplates/idf/user/dashboard.html.php:6 +msgid "Working issues:" +msgstr "Tickets assignés:" + +#: IDF/gettexttemplates/idf/issues/view.html.php:3 +#, php-format +msgid "Reported by %%submitter%%, %%c.creation_dtime%%" +msgstr "Soumis par %%submitter%%, %%c.creation_dtime%%" + +#: IDF/gettexttemplates/idf/issues/view.html.php:4 +#: IDF/gettexttemplates/idf/review/view.html.php:22 +#, php-format +msgid "" +"Comment %%i%% by %%submitter%%, %%c.creation_dtime%%" +msgstr "" +"Commentaire %%i%% par %%submitter%%, %%c." +"creation_dtime%%" + +#: IDF/gettexttemplates/idf/issues/view.html.php:5 +#, php-format +msgid "Sign in to reply to this comment." +msgstr "Connectez-vous pour répondre à ce commentaire." + +#: IDF/gettexttemplates/idf/issues/view.html.php:6 +msgid "" +"This issue is marked as closed, add a comment only if you think this issue " +"is still valid and more work is needed to fully fix it." +msgstr "" +"Ce ticket est marqué comme fermé. N'ajoutez un commentaire que si vous " +"pensez que ce ticket est toujours valide et qu'un travail supplémentaire est " +"nécessaire pour corriger le problème." + +#: IDF/gettexttemplates/idf/issues/view.html.php:8 +#, php-format +msgid "%%interested%% person" +msgid_plural "%%interested%% persons" +msgstr[0] "%%interested%% personne" +msgstr[1] "%%interested%% personnes" + +#: IDF/gettexttemplates/idf/issues/view.html.php:9 +#, php-format +msgid "This issue %%verb%%" +msgstr "Ce ticket %%verb%%" + +#: IDF/gettexttemplates/idf/issues/view.html.php:10 +msgid "Remove this issue from your watch list" +msgstr "Supprimer ce ticket de votre liste de surveillance" + +#: IDF/gettexttemplates/idf/issues/view.html.php:11 +msgid "Add this issue to your watch list" +msgstr "Ajouter ce ticket à votre liste de surveillance" + +#: IDF/gettexttemplates/idf/issues/view.html.php:12 +msgid "View the previous closed issue" +msgstr "Voir le dernier ticket fermée" + +#: IDF/gettexttemplates/idf/issues/view.html.php:13 +msgid "View the previous open issue" +msgstr "Voir le dernier ticket ouvert" + +#: IDF/gettexttemplates/idf/issues/view.html.php:14 +msgid "View the next closed issue" +msgstr "Voir le ticket fermé suivant." + +#: IDF/gettexttemplates/idf/issues/view.html.php:15 +msgid "View the next open issue" +msgstr "Voir le ticket ouvert suivant." + +#: IDF/gettexttemplates/idf/issues/view.html.php:16 +msgid "download" +msgstr "télécharger" + +#: IDF/gettexttemplates/idf/issues/view.html.php:17 +msgid "view" +msgstr "voir" + +#: IDF/gettexttemplates/idf/issues/view.html.php:23 +msgid "The form contains some errors. Please correct them to change the issue." +msgstr "" +"Le formulaire contient des erreurs. Veuillez les corriger pour modifier le " +"ticket." + +#: IDF/gettexttemplates/idf/issues/view.html.php:25 +msgid "Submit Changes" +msgstr "Soumettre les modifications" + +#: IDF/gettexttemplates/idf/issues/view.html.php:32 +msgid "Followed by:" +msgstr "Suivi par:" + +#: IDF/gettexttemplates/idf/listProjects.html.php:3 +#, php-format +msgid "1 project" +msgid_plural "%%label.project_count%% projects" +msgstr[0] "1 projet" +msgstr[1] "%%label.project_count%% projets" + +#: IDF/gettexttemplates/idf/listProjects.html.php:4 +#, php-format +msgid "Remove filter for %%tag%%" +msgstr "Enlever le filtre pour %%tag%%" + +#: IDF/gettexttemplates/idf/listProjects.html.php:5 +msgid "No projects managed with InDefero were found." +msgstr "Aucun projet géré avec InDefero n'a été trouvé." + +#: IDF/gettexttemplates/idf/listProjects.html.php:7 +msgid "Filter projects by label" +msgstr "Filtrer les projet par étiquettes" + +#: IDF/gettexttemplates/idf/listProjects.html.php:8 +msgid "No projects with labels found." +msgstr "Aucun projet possédant une étiquette n'a été trouvé." + +#: IDF/gettexttemplates/idf/listProjects.html.php:9 +msgid "Order" +msgstr "Ordre" + +#: IDF/gettexttemplates/idf/listProjects.html.php:10 +msgid "By name" +msgstr "Par nom" + +#: IDF/gettexttemplates/idf/listProjects.html.php:11 +msgid "By activity" +msgstr "Par activité" + +#: IDF/gettexttemplates/idf/listProjects.html.php:12 +msgid "Filtered project stats" +msgstr "Statistiques du projet filtrée. " + +#: IDF/gettexttemplates/idf/listProjects.html.php:13 +msgid "Members:" +msgstr "Membres:" + +#: IDF/gettexttemplates/idf/listProjects.html.php:14 +msgid "Issues:" +msgstr "Tickets:" + +#: IDF/gettexttemplates/idf/listProjects.html.php:15 +msgid "Commits:" +msgstr "Commits:" + +#: IDF/gettexttemplates/idf/listProjects.html.php:16 +msgid "Documentations:" +msgstr "Documentation:" + +#: IDF/gettexttemplates/idf/listProjects.html.php:18 +msgid "Code reviews:" +msgstr "Revues de code:" + +#: IDF/gettexttemplates/idf/login_form.html.php:3 +#, php-format +msgid "" +"You can create an account if you don't have one yet." +msgstr "" +"Vous pouvez crée un compte si vous n'en n'avez pas." + +#: IDF/gettexttemplates/idf/login_form.html.php:4 +msgid "What is your account information?" +msgstr "Quelles sont les informations relatives à votre compte?" + +#: IDF/gettexttemplates/idf/login_form.html.php:5 +msgid "My login is" +msgstr "Mon identifiant est" + +#: IDF/gettexttemplates/idf/login_form.html.php:6 +msgid "My password is" +msgstr "Mon mot de passe est" + +#: IDF/gettexttemplates/idf/login_form.html.php:7 +msgid "Sign in" +msgstr "Vous identifier" + +#: IDF/gettexttemplates/idf/login_form.html.php:8 +msgid "I lost my password!" +msgstr "J'ai perdu mon mot de passe!" + +#: IDF/gettexttemplates/idf/login_form.html.php:9 +msgid "Welcome." +msgstr "Bienvenue." + +#: IDF/gettexttemplates/idf/login_form.html.php:10 +msgid "It takes less than a minute to create your account." +msgstr "La création d'un compte prend moins d'une minute." + +#: IDF/gettexttemplates/idf/main-menu.html.php:3 +#, php-format +msgid "" +"Welcome, %%user%%." +msgstr "" +"Bienvenue, %%user%%." + +#: IDF/gettexttemplates/idf/main-menu.html.php:4 +msgid "Sign Out" +msgstr "Se déconnecter" + +#: IDF/gettexttemplates/idf/main-menu.html.php:5 +msgid "Sign in or create your account" +msgstr "Identifiez-vous ou créez votre compte" + +#: IDF/gettexttemplates/idf/main-menu.html.php:10 IDF/Views/Admin.php:40 +msgid "Forge Management" +msgstr "Administration de la forge" + +#: IDF/gettexttemplates/idf/main-menu.html.php:11 +msgid "Help and accessibility features" +msgstr "Aide et accessibilité" + +#: IDF/gettexttemplates/idf/main-menu.html.php:12 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:14 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:14 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:15 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:13 +msgid "Help" +msgstr "Aide" + +#: IDF/gettexttemplates/idf/project/home.html.php:3 +#: IDF/gettexttemplates/idf/project/timeline.html.php:4 IDF/Views.php:46 +msgid "Welcome" +msgstr "Bienvenue" + +#: IDF/gettexttemplates/idf/project/home.html.php:4 +#: IDF/gettexttemplates/idf/project/timeline.html.php:5 +msgid "Latest Updates" +msgstr "Dernières mises à jour" + +#: IDF/gettexttemplates/idf/project/home.html.php:5 +msgid "Featured Downloads" +msgstr "Téléchargements recommandés" + +#: IDF/gettexttemplates/idf/project/home.html.php:6 +msgid "Show more featured downloads" +msgstr "Montrer plus de téléchargements." + +#: IDF/gettexttemplates/idf/project/home.html.php:7 +#: IDF/gettexttemplates/idf/project/home.html.php:10 +msgid "show more..." +msgstr "plus..." + +#: IDF/gettexttemplates/idf/project/home.html.php:8 +msgid "Featured Documentation" +msgstr "Documentation recommandée" + +#: IDF/gettexttemplates/idf/project/home.html.php:9 +msgid "Show more featured documentation" +msgstr "Montrer plus de documentations." + +#: IDF/gettexttemplates/idf/project/home.html.php:11 +msgid "Development Team" +msgstr "Équipe de développement" + +#: IDF/gettexttemplates/idf/project/home.html.php:12 +msgid "Admins" +msgstr "Administrateurs" + +#: IDF/gettexttemplates/idf/project/home.html.php:13 +msgid "Happy Crew" +msgstr "Équipe sympa" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:3 +msgid "Latest updates" +msgstr "Dernières mises à jour" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:6 +#: IDF/Views/Project.php:90 +msgid "All Updates" +msgstr "Toutes les mises à jour" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:7 +msgid "Filter by type" +msgstr "Filtrer par type" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:8 +msgid "Subscribe to this timeline" +msgstr "Abonnez-vous à ce flux" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:9 +msgid "RSS" +msgstr "RSS" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:10 +msgid "Atom feed" +msgstr "Atom" + +#: IDF/gettexttemplates/idf/project-list.html.php:3 +msgid "Project activity: %%activity%%%" +msgstr "Activité du projet : %%activity%%%" + +#: IDF/gettexttemplates/idf/project-list.html.php:9 +msgid "n/a" +msgstr "n/d" + +#: IDF/gettexttemplates/idf/register/confirmation-email.txt.php:3 +#, php-format +msgid "" +"Hello,\n" +"\n" +"You have requested the creation of an account to\n" +"participate in the life of a software project.\n" +"\n" +"To confirm the account please follow this link:\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following confirmation key:\n" +"\n" +"%%key%%\n" +"\n" +"If you are not interested any longer in taking\n" +"part in the life of the software project or if\n" +"you can't remember having requested the creation\n" +"of an account, please excuse us and simply ignore\n" +"this email. \n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" +"Bonjour,\n" +"\n" +"Vous avez demandé la création d'un compte pour\n" +"participer à la vie d'un projet logiciel.\n" +"\n" +"Pour confirmer votre compte, suivez ce lien:\n" +"\n" +"%%url%%\n" +"\n" +"Vous pouvez également vous rendre sur cette page:\n" +"\n" +"%%urlik%%\n" +"\n" +"et fournir la clé de confirmation suivante:\n" +"\n" +"%%key%%\n" +"\n" +"Si vous n'êtes plus intéressé à participer\n" +"à la vie de ce projet logiciel ou si vous ne\n" +"vous souvenez pas d'avoir fait cette demande,\n" +"veuillez accepter nos excuses et ignorer ce\n" +"message.\n" +"\n" +"Cordialement,\n" +"\n" +"L'équipe de développement\n" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:3 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:3 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:3 +msgid "Oops, please check the form for errors." +msgstr "Oups, veuillez corriger les erreurs dans le formulaire." + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:5 +msgid "Email:" +msgstr "Email:" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:6 +msgid "Enable Your Account" +msgstr "Activez votre compte" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:8 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:8 +msgid "" +"This is the last step, but just be sure to have the cookies enabled to log in afterwards." +msgstr "" +"C'est la dernière étape, mais assurez-vous que les témoins (cookies) " +"soient activés dans votre navigateur pour vous connecter par la " +"suite." + +#: IDF/gettexttemplates/idf/register/index.html.php:3 +msgid "" +"Read the terms and conditions – " +"basically \"Please be nice, we respect you\"." +msgstr "" +"Lire les <a id=\"showterms\" href=\"#theterms\">conditions " +"d'utilisation –</a>en gros <em>Soyez sympa, on vous respecte</" +"em>." + +#: IDF/gettexttemplates/idf/register/index.html.php:4 +#, php-format +msgid "" +"If you have just forgotten your login information, then there is no need to " +"create a new account. You can just recover your login " +"name and password." +msgstr "" +"Si vous avez oublié vos informations de connexions, alors il n'y as pas " +"besoin de créer un nouveau compte. Vous pouvez juste récupérer votre identifiant et votre mot de passe." + +#: IDF/gettexttemplates/idf/register/index.html.php:5 +#, php-format +msgid "" +"With your account, you will able to participate in the life of all the " +"projects hosted here. Participating in a software project must be fun, so if " +"you have troubles, you can let us know about your issues " +"at anytime!" +msgstr "" +"Avec votre compte, vous pourrez participer à la vie de tous les projets " +"administrés ici. Participer à la vie d'un logiciel doit être sympa, alors si " +"vous rencontrez des problèmes, vous pouvez nous le faire " +"savoir à tout instant!" + +#: IDF/gettexttemplates/idf/register/index.html.php:6 +msgid "Oops, please check the provided login and email address to register." +msgstr "" +"Oups, veuillez vérifier l'identifiant et l'adresse email pour vous " +"enregistrer." + +#: IDF/gettexttemplates/idf/register/index.html.php:7 IDF/Views.php:137 +msgid "Create Your Account" +msgstr "Créez votre compte" + +#: IDF/gettexttemplates/idf/register/index.html.php:9 +msgid "" +"Be sure to provide a valid email address, as we are sending a validation " +"link by email." +msgstr "" +"Faites attention de bien fournir une adresse email valide, car nous vous " +"enverrons un email de confirmation." + +#: IDF/gettexttemplates/idf/register/index.html.php:10 +msgid "Did you know?" +msgstr "Le saviez-vous?" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:3 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:3 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:3 +msgid "Oops, we found an error in the form." +msgstr "Oups, nous avons trouvé une erreur dans le formulaire." + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:4 +msgid "Confirm Your Account" +msgstr "Confirmez votre compte" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:7 +msgid "" +"Use your email software to read your emails and open your confirmation " +"email. Either click directly on the confirmation link or copy/paste the " +"confirmation key in the box and submit the form." +msgstr "" +"Utilisez votre logiciel de messagerie pour lire votre email de confirmation. " +"Vous pouvez cliquer sur le lien fourni ou copier/coller la clé de " +"confirmation dans le formulaire et le soumettre." + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:8 +msgid "" +"Just after providing the confirmation key, you will be able to set your " +"password and start using this website fully." +msgstr "" +"Tout de suite après avoir fourni la clé de confirmation, vous pourrez " +"définir votre mot de passe et utiliser pleinement le site." + +#: IDF/gettexttemplates/idf/review/base-full.html.php:3 +#: IDF/gettexttemplates/idf/review/base.html.php:3 +msgid "Open Reviews" +msgstr "Revues ouvertes" + +#: IDF/gettexttemplates/idf/review/base.html.php:4 +#: IDF/gettexttemplates/idf/review/create.html.php:11 +#: IDF/gettexttemplates/idf/review/index.html.php:3 IDF/Views/Review.php:83 +msgid "Start Code Review" +msgstr "Nouvelle revue de code" + +#: IDF/gettexttemplates/idf/review/create.html.php:3 +msgid "" +"

To start a code review, you need to provide:

\n" +"
    \n" +"
  • A commit or revision of the current code in the repository from which " +"you started your work.
  • \n" +"
  • A patch describing your changes with respect to the reference commit.\n" +"
  • Check your patch does not provide any password or confidential " +"information!
  • \n" +"
" +msgstr "" +"

Pour démarrer une revue de code, vous devez fournir:

\n" +"
    \n" +"
  • La révision ou le commit de référence qui a servi de base à votre " +"travail.
  • \n" +"
  • Un patch décrivant les modifications par rapport à la référence.
  • \n" +"
  • Vérifiez votre patch pour ne fournir aucun mot de passe ou " +"information confidentielle!
  • \n" +"
" + +#: IDF/gettexttemplates/idf/review/create.html.php:9 +msgid "" +"The form contains some errors. Please correct them to submit the code review." +msgstr "" +"Le formulaire contient des erreurs. Veuillez les corriger pour soumettre la " +"revue de code." + +#: IDF/gettexttemplates/idf/review/create.html.php:10 +msgid "" +"Select the commit against which you created your patch to be sure it applies " +"correctly." +msgstr "" +"Sélectionnez le commit correspondant à votre patch pour être certain qu'il " +"puisse s'appliquer correctement." + +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:3 +msgid "The following review has been created:" +msgstr "La revue suivante a été créée:" + +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:16 +msgid "Review:" +msgstr "Revue:" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:3 +msgid "The following review has been updated:" +msgstr "La revue suivante a été mise à jour:" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:5 +#, php-format +msgid "" +"By %%who%%, %%c.creation_dtime%%, on file:\n" +"%%c.cfile%%\n" +msgstr "" +"Par %%who%%, %%c.creation_dtime%%, à propos\n" +"du fichier:\n" +"%%c.cfile%%\n" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:14 +msgid "General comments (last first):" +msgstr "Commentaires généraux (le plus récent en premier):" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:15 +msgid "Detailed file comments (last first):" +msgstr "Commentaires détaillés des fichiers (le plus récent en premier):" + +#: IDF/gettexttemplates/idf/review/view.html.php:3 +msgid "" +"Code review is a process in which\n" +"after or before changes are commited into the code repository,\n" +"different people discuss the code changes. The goal is\n" +"to improve the quality of the code and the\n" +"contributions, as such, you must be pragmatic when writing\n" +"your review. Correctly mention the line numbers (in the old or in the\n" +"new file) and try to keep a good balance between seriousness and fun.\n" +msgstr "" +"La revue de code est une discussion\n" +"sur des modifications du code (déjà intégrées ou non dans le dépôt).\n" +"Le but est d'améliorer la qualité du code et des\n" +"contributions. Pour cela, vous devez être pragmatique quand\n" +"vous écrivez votre analyse. Mentionnez bien les numéros de ligne\n" +"(dans l'ancien ou le nouveau fichier) et essayez de garder un bon\n" +"équilibre entre sérieux et humour dans vos remarques.\n" + +#: IDF/gettexttemplates/idf/review/view.html.php:11 +msgid "" +"\n" +"Proposing code for review is intimidating, you know\n" +"you will receive critics, so please, as a reviewer, keep this\n" +"process fun, use it to help your contributor learn your\n" +"coding standards and the structure of the code and make them want\n" +"to propose more contributions.\n" +msgstr "" +"\n" +"Proposer du code pour revue est intimidant, vous savez\n" +"que vous allez recevoir des critiques. Comme participant à la revue,\n" +"gardez une bonne ambiance et aidez le contributeur à\n" +"apprendre la structure de votre code et vos exigences de qualité.\n" +"Donnez-lui envie de proposer de nouvelles contributions.\n" + +#: IDF/gettexttemplates/idf/review/view.html.php:18 +#: IDF/gettexttemplates/idf/source/commit.html.php:3 +#: IDF/gettexttemplates/idf/source/commit.html~.php:3 +#, php-format +msgid "%%ndiff%% diff" +msgid_plural "%%ndiff%% diffs" +msgstr[0] "%%ndiff%% diff" +msgstr[1] "%%ndiff%% diffs" + +#: IDF/gettexttemplates/idf/review/view.html.php:19 +#, php-format +msgid "%%nc%% comment" +msgid_plural "%%nc%% comments" +msgstr[0] "%%nc%% commentaire" +msgstr[1] "%%nc%% commentaires" + +#: IDF/gettexttemplates/idf/review/view.html.php:20 +#, php-format +msgid "" +"Comment %%i%% by %%who%%, " +"%%c.creation_dtime%%" +msgstr "" +"Commentaire %%i%% par %%who" +"%%, %%c.creation_dtime%%" + +#: IDF/gettexttemplates/idf/review/view.html.php:21 +#, php-format +msgid "Your comments on the changes in file %%file%%:" +msgstr "Vos commentaires sur les modifications du fichier %%file%%:" + +#: IDF/gettexttemplates/idf/review/view.html.php:23 +#, php-format +msgid "Sign in to participate in the review." +msgstr "Connectez-vous pour participer à la revue." + +#: IDF/gettexttemplates/idf/review/view.html.php:24 +msgid "" +"The form contains some errors. Please correct them to submit your review." +msgstr "" +"Le formulaire contient des erreurs. Veuillez les corriger pour soumettre " +"votre revue." + +#: IDF/gettexttemplates/idf/review/view.html.php:25 +msgid "How to Participate in a Code Review" +msgstr "Comment participer à une revue de code" + +#: IDF/gettexttemplates/idf/review/view.html.php:28 +#: IDF/gettexttemplates/idf/source/commit.html.php:5 +#: IDF/gettexttemplates/idf/source/commit.html~.php:5 +msgid "Author:" +msgstr "Auteur:" + +#: IDF/gettexttemplates/idf/review/view.html.php:29 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/source/commit.html.php:7 +#: IDF/gettexttemplates/idf/source/commit.html~.php:7 +msgid "Commit:" +msgstr "Commit:" + +#: IDF/gettexttemplates/idf/review/view.html.php:30 +#: IDF/gettexttemplates/idf/source/commit.html.php:8 +#: IDF/gettexttemplates/idf/source/commit.html~.php:8 +msgid "View corresponding source tree" +msgstr "Voir l'arbre des sources correspondant" + +#: IDF/gettexttemplates/idf/review/view.html.php:32 +msgid "Reviewers:" +msgstr "Participants:" + +#: IDF/gettexttemplates/idf/review/view.html.php:33 +msgid "No reviewers at the moment." +msgstr "Aucun participant à la revue pour le moment." + +#: IDF/gettexttemplates/idf/review/view.html.php:34 +msgid "Files:" +msgstr "Fichiers:" + +#: IDF/gettexttemplates/idf/review/view.html.php:36 +#: IDF/gettexttemplates/idf/source/commit.html.php:24 +#: IDF/gettexttemplates/idf/source/commit.html~.php:23 +msgid "Download the corresponding diff file" +msgstr "Télécharger le fichier diff correspondant" + +#: IDF/gettexttemplates/idf/review/view.html.php:37 +msgid "General Comments" +msgstr "Commentaires généraux" + +#: IDF/gettexttemplates/idf/review/view.html.php:40 +msgid "Submit Code Review" +msgstr "Soumettre la revue de code" + +#: IDF/gettexttemplates/idf/source/base.html.php:3 +msgid "Source Tree" +msgstr "Arbre des sources" + +#: IDF/gettexttemplates/idf/source/base.html.php:4 +msgid "Change Log" +msgstr "Journal des modifications" + +#: IDF/gettexttemplates/idf/source/base.html.php:6 +msgid "How To Get The Code" +msgstr "Comment obtenir le code" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:3 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:8 +#: IDF/Views/Project.php:190 +msgid "Age" +msgstr "Âge" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:4 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:10 +msgid "Message" +msgstr "Message" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:5 +msgid "Parent:" +msgstr "Parent:" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:6 +#: IDF/gettexttemplates/idf/source/commit.html.php:10 +#: IDF/gettexttemplates/idf/source/commit.html~.php:10 +msgid "View corresponding commit" +msgstr "Voir le commit correspondant" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:8 +msgid "by" +msgstr "par" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:3 +msgid "A new commit has been created:" +msgstr "Un nouveau commit a été créée:" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:8 +msgid "Created by:" +msgstr "Créé par:" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:8 +msgid "Created at:" +msgstr "Créé le:" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:8 +msgid "Content:" +msgstr "Contenu:" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:10 +msgid "Commit details:" +msgstr "Détails du commit:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:4 +#: IDF/gettexttemplates/idf/source/commit.html~.php:4 +msgid "Date:" +msgstr "Date:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:6 +#: IDF/gettexttemplates/idf/source/commit.html~.php:6 +msgid "Branch:" +msgstr "Branche:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:9 +#: IDF/gettexttemplates/idf/source/commit.html~.php:9 +msgid "Parents:" +msgstr "Parents:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:11 +#: IDF/gettexttemplates/idf/source/commit.html~.php:11 +msgid "Message:" +msgstr "Message:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:12 +#: IDF/gettexttemplates/idf/source/commit.html~.php:12 +#: IDF/gettexttemplates/idf/wiki/feedfragment-page.xml.php:3 +#: IDF/gettexttemplates/idf/wiki/feedfragment-resource.xml.php:3 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:10 +msgid "Changes:" +msgstr "Modifications:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:13 +#: IDF/gettexttemplates/idf/source/commit.html~.php:13 +msgid "deleted" +msgstr "supprimé" + +#: IDF/gettexttemplates/idf/source/commit.html.php:14 +#: IDF/gettexttemplates/idf/source/commit.html.php:18 +#: IDF/gettexttemplates/idf/source/commit.html~.php:14 +#: IDF/gettexttemplates/idf/source/commit.html~.php:17 +msgid "full" +msgstr "complet" + +#: IDF/gettexttemplates/idf/source/commit.html.php:15 +#: IDF/gettexttemplates/idf/source/commit.html~.php:15 +msgid "renamed" +msgstr "renommé" + +#: IDF/gettexttemplates/idf/source/commit.html.php:16 +msgid "copied" +msgstr "copié" + +#: IDF/gettexttemplates/idf/source/commit.html.php:17 +#: IDF/gettexttemplates/idf/source/commit.html~.php:16 +msgid "added" +msgstr "ajouté" + +#: IDF/gettexttemplates/idf/source/commit.html.php:19 +#: IDF/gettexttemplates/idf/source/commit.html~.php:18 +msgid "modified" +msgstr "modifié" + +#: IDF/gettexttemplates/idf/source/commit.html.php:20 +msgid "properties changed" +msgstr "Propriétés changées." + +#: IDF/gettexttemplates/idf/source/commit.html.php:21 +#: IDF/gettexttemplates/idf/source/commit.html~.php:20 +msgid "removed" +msgstr "supprimé" + +#: IDF/gettexttemplates/idf/source/commit.html.php:22 +#: IDF/gettexttemplates/idf/source/commit.html~.php:21 +msgid "File differences" +msgstr "Différences entre fichiers" + +#: IDF/gettexttemplates/idf/source/commit.html~.php:19 +msgid "properies changed" +msgstr "propriétés modifiées" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:3 +#, php-format +msgid "" +"The revision identifier %%commit%% is ambiguous and can be\n" +"expanded to multiple valid revisions - please choose one:" +msgstr "" +"L'identifiant de révision %%commit%% est ambigu et peut être\n" +"associé à différentes révisions valides. Choisissez-en une:" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:5 +msgid "Title" +msgstr "Titre" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:6 +msgid "Author" +msgstr "Auteur" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:7 +msgid "Date" +msgstr "Date" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:8 +msgid "Branch" +msgstr "Branche" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:9 +msgid "Revision" +msgstr "Révision" + +#: IDF/gettexttemplates/idf/source/feedfragment.xml.php:3 +#, php-format +msgid "%%cproject.name%%: Commit %%c.scm_id%%" +msgstr "%%cproject.name%%: commit %%c.scm_id%%" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:3 +msgid "Branches" +msgstr "Branches" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:4 +msgid "filter branches" +msgstr "filtrer les branches" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:5 +msgid "Tags" +msgstr "Étiquettes" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:6 +msgid "filter tags" +msgstr "filtrer les étiquettes" + +#: IDF/gettexttemplates/idf/source/git/file.html.php:3 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:4 +#, php-format +msgid "" +"Source at commit %%commit%% created " +"%%cobject.date%%." +msgstr "" +"Source au commit %%commit%% créé " +"%%cobject.date%%." + +#: IDF/gettexttemplates/idf/source/git/file.html.php:4 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:5 +#, php-format +msgid "By %%cobject.author%%, %%cobject.title%%" +msgstr "Par %%cobject.author%%, %%cobject.title%%" + +#: IDF/gettexttemplates/idf/source/git/file.html.php:5 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:6 +msgid "Root" +msgstr "Racine" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the git software to manage the source\n" +"code." +msgstr "" +"L'équipe de développement du projet %%project%%\n" +"utilise Git pour gérer le code source." + +#: IDF/gettexttemplates/idf/source/git/help.html.php:6 +#, php-format +msgid "" +"You may need to provide your SSH key. The " +"synchronization of your SSH key can take a couple of minutes. You can learn " +"more about SSH key authentication." +msgstr "" +"Vous devrez peut-être fournir votre clé SSH. La " +"synchronisation de votre clé SSH peut prendre quelques minutes. Vous pouvez " +"en apprendre plus sur l'authentification avec une clé " +"SSH publique." + +#: IDF/gettexttemplates/idf/source/git/help.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:6 +msgid "To make a first commit in the repository, perform the following steps:" +msgstr "Pour effectuer le premier commit dans le dépôt, procédez comme suit:" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:8 +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:7 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:7 +#, php-format +msgid "Find here more details on how to access %%project%% source code." +msgstr "" +"Trouvez ici plus de détails pour accéder au code du projet %%project%%." + +#: IDF/gettexttemplates/idf/source/git/help.html.php:9 +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:8 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:8 +msgid "Command-Line Access" +msgstr "Accès en ligne de commande" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:10 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:9 +msgid "First Commit" +msgstr "Premier commit" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:11 +#: IDF/Views/Download.php:66 IDF/Views/Download.php:348 +msgid "Size" +msgstr "Taille" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:12 +msgid ":" +msgstr ":" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:13 +msgid "Download this version" +msgstr "Téléchargez cette version" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:13 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:13 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:14 +msgid "or" +msgstr "ou" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:3 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:3 +#, php-format +msgid "" +"The branch or revision %%commit%% is not valid or does not exist\n" +"in this repository." +msgstr "" +"La branche ou la révision %%commit%% n'est pas valide ou n'existe " +"pas\n" +"dans le dépôt." + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:5 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:5 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:5 +msgid "The following list shows all available branches:" +msgstr "Les branches disponibles sont listées ci-dessous:" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:6 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:6 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:6 +#, php-format +msgid "" +"If this is a new repository, the reason for this error\n" +"could be that you have not committed and / or pushed any change so far.\n" +"In this case please take a look at the Help page\n" +"how to access your repository." +msgstr "" +"S'il s'agit d'un nouveau dépôt, la raison de cette erreur peut être\n" +"que vous n'avez pas encore effectué de commit ou envoyé de modification.\n" +"Dans ce cas, veuillez lire la page d'aide sur\n" +"comment accéder au dépôt." + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the Mercurial software to manage the source\n" +"code." +msgstr "" +"L'équipe de développement du projet %%project%%\n" +"utilise Mercurial pour gérer le code source." + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:6 +#, php-format +msgid "" +"To get write access to the repository, you need to use your username and " +"your extra password." +msgstr "" +"Pour avoir accès en écriture au dépôt, vous devez utiliser votre identifiant " +"et votre mot de passe supplémentaire." + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:9 +msgid "Write Access Authentication" +msgstr "Authentification d'accès en écriture" + +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:3 +#, php-format +msgid "Property %%prop%% set to %%val%%" +msgstr "Propriété %%prop%% définie à %%val%%" + +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the monotone software to manage the source\n" +"code." +msgstr "" +"L'équipe de développement du projet %%project%%\n" +"utilise Monotone pour gérer le code source." + +#: IDF/gettexttemplates/idf/source/svn/changelog.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/commit.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/commit.html~.php:3 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:14 +msgid "Revision:" +msgstr "Révision:" + +#: IDF/gettexttemplates/idf/source/svn/changelog.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/commit.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/commit.html~.php:4 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:10 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:15 +msgid "Switch" +msgstr "Basculer" + +#: IDF/gettexttemplates/idf/source/svn/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the subversion software to manage the source\n" +"code." +msgstr "" +"L'équipe de développement du projet %%project%%\n" +"utilise Subversion pour gérer le code source." + +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:3 +#, php-format +msgid "" +"The revision %%commit%% is not valid or does not exist\n" +"in this repository." +msgstr "" +"La révision %%commit%% n'est pas valide ou n'existe pas\n" +"dans ce dépôt." + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:9 +msgid "Rev" +msgstr "Rév" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:16 +msgid "Branches:" +msgstr "Branches:" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:17 +msgid "Tags:" +msgstr "Étiquettes:" + +#: IDF/gettexttemplates/idf/user/changeemail-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"To confirm that you want %%email%%\n" +"to be your new email address, just follow this link:\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following verification key:\n" +"\n" +"%%key%%\n" +"\n" +"If you do not want to change your email address, \n" +"just ignore this message.\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" +"Bonjour %%user%%,\n" +"\n" +"Pour confirmer l'utilisation de %%email%%\n" +"comme nouvelle adresse email, suivez le lien suivant:\n" +"\n" +"%%url%%\n" +"\n" +"Vous pouvez également vous rendre sur cette page:\n" +"\n" +"%%urlik%%\n" +"\n" +"et fournir la clé de vérification suivante:\n" +"\n" +"%%key%%\n" +"\n" +"Si vous ne voulez pas changer votre adresse email,\n" +"ignorez simplement ce message.\n" +"\n" +"Cordialement,\n" +"\n" +"L'équipe de développement\n" + +#: IDF/gettexttemplates/idf/user/changeemail.html.php:4 +msgid "Confirm Your New Email Address" +msgstr "Confirmez votre nouvelle adresse email" + +#: IDF/gettexttemplates/idf/user/changeemail.html.php:7 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:7 +msgid "" +"Use your email software to read your emails and open your verification " +"email. Either click directly on the verification link or copy/paste the " +"verification key in the box and submit the form." +msgstr "" +"Utilisez votre logiciel de messagerie pour lire votre email de vérification. " +"Vous pouvez cliquer sur le lien fourni ou copier/coller la clé de " +"vérification dans le formulaire et le soumettre." + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:3 +#, php-format +msgid "Update your account." +msgstr "Mettre à jour votre compte." + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:4 +#, php-format +msgid "See your public profile." +msgstr "Voir votre profil public." + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:5 +#, php-format +msgid "See your forge issue watch list." +msgstr "" +"Voir votre liste de surveillance de tickets sur la " +"forge." + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:6 +msgid "Key Management" +msgstr "Administration des clés" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:7 +msgid "Secondary Emails" +msgstr "Emails secondaires" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:8 +msgid "Extra password" +msgstr "Mot de passe supplémentaire" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:9 +msgid "" +"This password is used to access some of the external systems managed by our " +"infrastructure. It will be regenerated if you change your password." +msgstr "" +"Ce mot de passe est utilisé pour accéder à certains systèmes externes gérés " +"par notre infrastructure. Il sera régénéré si vous modifiez votre mot de " +"passe." + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:10 +msgid "API key" +msgstr "Clé d'API" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:11 +msgid "" +"Your API key will be regenerated automatically if you change your password." +msgstr "" +"Votre clé d'API sera régénérée automatiquement si vous modifiez votre mot de " +"passe." + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:12 +msgid "Update Your Account" +msgstr "Mettre à jour votre compte" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:14 +msgid "Your Current Public Keys" +msgstr "Vos clés publiques actuelles" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:15 +msgid "Delete this key" +msgstr "Supprimer cette clé" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:16 +msgid "Your additional email addresses" +msgstr "Vos adresses emails secondaires" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:17 +msgid "Delete this address" +msgstr "Supprimer cette adresse" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:18 +msgid "" +"If possible, use your real name. By using your real name, people will have " +"more trust in your comments and remarks." +msgstr "" +"Si possible, utilisez votre vrai nom. En utilisant votre vrai nom, les " +"personnes participant à ce site auront naturellement plus confiance en vos " +"commentaires et remarques." + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:19 +msgid "" +"The extra password is used to access some of the external systems and the " +"API key is used to interact with this website using a program." +msgstr "" +"Le mot de passe supplémentaire est utilisé pour accéder à certains systèmes " +"externes et la clé d'API est utilisée pour communiquer avec le site au moyen " +"d'un programme." + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:20 +msgid "Show API key and extra password" +msgstr "Montrer la clé d'API et le mot de passe supplémentaire" + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:3 +msgid "" +"Oops, please check the provided login or email address to recover your " +"password." +msgstr "" +"Oups, veuillez vérifier l'identifiant ou l'adresse email pour récupérer " +"votre mot de passe." + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:4 +msgid "Recover My Password" +msgstr "Récupérer mon mot de passe" + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:6 +msgid "" +"Provide either your login or email address, if a corresponding user is found " +"in the database, we will send you an email with the details on how to reset " +"your password." +msgstr "" +"Fournissez votre identifiant ou votre adresse email. Si un utilisateur " +"correspondant est trouvé dans la base de données, nous vous enverrons un " +"email avec les informations nécessaires pour réinitialiser votre mot de " +"passe." + +#: IDF/gettexttemplates/idf/user/passrecovery-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"You lost your password and wanted to recover it.\n" +"To provide a new password for your account, you\n" +"just have to follow the provided link. You will\n" +"get a simple form to provide a new password.\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following verification key:\n" +"\n" +"%%key%%\n" +"\n" +"If you are not the one who requested to reset\n" +"your password, simply ignore this email, your\n" +"password will not be changed.\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" +"Bonjour %%user%%,\n" +"\n" +"Vous avez perdu votre mot de passe et voulez le retrouver.\n" +"Pour définir un nouveau mot de passe pour votre compte, vous\n" +"devez simplement suivre le lien suivant, et un formulaire\n" +"vous permettra de fournir un nouveau mot de passe:\n" +"\n" +"%%url%%\n" +"\n" +"Vous pouvez également vous rendre sur cette page:\n" +"\n" +"%%urlik%%\n" +"\n" +"et fournir la clé de vérification suivante:\n" +"\n" +"%%key%%\n" +"\n" +"Si vous n'êtes pas la personne ayant fait la demande de\n" +"réinitialisation de votre mot de passe, ignorez simplement\n" +"cet email et votre mot de passe restera inchangé.\n" +"\n" +"Cordialement,\n" +"\n" +"L'équipe de développement\n" + +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:4 +msgid "Recover Your Password" +msgstr "Récupérer votre mot de passe" + +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:8 +msgid "" +"Just after providing the confirmation key, you will be able to reset your " +"password and use this website fully." +msgstr "" +"Tout de suite après avoir fourni la clé de confirmation, vous pourrez " +"réinitialiser votre mot de passe et utiliser pleinement le site." + +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:6 +msgid "Reset Your Password" +msgstr "Réinitialiser votre mot de passe" + +#: IDF/gettexttemplates/idf/user/public.html.php:3 +#, php-format +msgid "You are looking at the public profile of %%member%%." +msgstr "Vous consultez le profil public de %%member%%." + +#: IDF/gettexttemplates/idf/user/public.html.php:5 +msgid "Twitter:" +msgstr "Twitter:" + +#: IDF/gettexttemplates/idf/user/public.html.php:6 +msgid "Public Email:" +msgstr "Email public:" + +#: IDF/gettexttemplates/idf/user/public.html.php:7 +msgid "Website:" +msgstr "Site Web:" + +#: IDF/gettexttemplates/idf/user/public.html.php:8 +msgid "Last time seen:" +msgstr "Vu la dernière fois:" + +#: IDF/gettexttemplates/idf/user/public.html.php:9 +msgid "Member since:" +msgstr "Membre depuis:" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:3 +msgid "List Pages" +msgstr "Liste des pages" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:4 +msgid "List Resources" +msgstr "Liste des ressources" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:5 +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:4 +#: IDF/gettexttemplates/idf/wiki/search.html.php:3 IDF/Views/Wiki.php:211 +msgid "New Page" +msgstr "Nouvelle page" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:6 +#: IDF/gettexttemplates/idf/wiki/listResources.html.php:3 +#: IDF/Views/Wiki.php:256 +msgid "New Resource" +msgstr "Nouvelle ressource" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:7 +msgid "Update This Page" +msgstr "Mettre à jour cette page" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:8 +msgid "Update This Resource" +msgstr "Mettre à jour cette ressource" + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:3 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:3 +msgid "Preview of the Page" +msgstr "Prévisualisation de la page" + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:7 +msgid "The form contains some errors. Please correct them to create the page." +msgstr "" +"Le formulaire contient des erreurs. Veuillez les corriger pour créer la page." + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:6 +msgid "Create Page" +msgstr "Créer une page" + +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:3 +msgid "" +"\n" +"Wiki resources are later addressed in wiki pages by their title, so ensure " +"that you\n" +"give your resource a unique and an easy to remember name.\n" +msgstr "" +"\n" +"Les ressources du Wiki sont accessibles par leurs titres. Utilisez des " +"titres simple et unique.\n" + +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:8 +msgid "Create Resource" +msgstr "Créer une ressource" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:3 +msgid "" +"If you delete this documentation page, it will be removed from the database " +"with all the associated revisions and you will not be able to " +"recover it." +msgstr "" +"Si vous supprimez cette page de documentation, elle sera supprimée de la " +"base de données tout comme les révisions associées, et vous ne " +"pourrez pas les récupérer ultérieurement." + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:6 +msgid "Delete Page" +msgstr "Supprimer la page" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:14 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:15 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:15 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:17 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:18 +msgid "Old Revisions" +msgstr "Anciennes révisions" + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:3 +#, php-format +msgid "" +"You are looking at an old revision (%%oldrev.summary%%) of the " +"page \n" +"%%page.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" +"Vous consultez une ancienne révision (%%oldrev.summary%%) de la " +"page\n" +"%%page.title%%. Cette révision a été créée\n" +"par %%submitter%%." + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:5 +msgid "" +"If you delete this old revision, it will be removed from the database and " +"you will not be able to recover it." +msgstr "" +"Si vous supprimez cette ancienne révision, elle sera supprimée de la base de " +"données et vous ne pourrez pas la récupérer ultérieurement." + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:8 +msgid "Delete Revision" +msgstr "Supprimer cette révision" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:3 +msgid "" +"If you delete this documentation resource, it will be removed from the " +"database with all the associated revisions \n" +"and you will not be able to recover it. Any documentation " +"pages that reference this resource,\n" +"will no longer be able to render it, but won't be deleted." +msgstr "" +"Si vous supprimer cette documentation de ressource, elle sera enlever de la " +"basse de donnée avec toutes les versions qui lui sont associées\n" +"et vous ne pourrez pas les récupérer. Caque page de " +"documentation qui fait référence à cette ressource ne seront plus capable de " +"s'y rendre, mais elles ne seront pas supprimé." + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:8 +msgid "Delete Resource" +msgstr "Supprimer une ressource." + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:10 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:8 +msgid "File size" +msgstr "Taille du fichier" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:9 +#: IDF/Views/Wiki.php:101 +msgid "MIME type" +msgstr "Type MIME" + +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:3 +#, php-format +msgid "" +"You are looking at an old revision (%%oldrev.summary%%) of the " +"resource \n" +"%%resource.title%%. This revision was created by " +"%%submitter%%." +msgstr "" +"Vous être en train de consulter une vielle version (%%oldrev.summary%%) de la ressource \n" +"%%resource.title%%. Cette version à été créée par " +"%%submitter%%." + +#: IDF/gettexttemplates/idf/wiki/edit-info.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

The content of the page can use the Markdown syntax with the Extra extension.

\n" +"

Website addresses are automatically linked and you can link to another " +"page in the documentation using double square brackets like that " +"[[AnotherPage]].

\n" +"

If you want to embed uploaded resources, use the [[!ResourceName]] syntax for that. This is described more in detail in the FAQ.

\n" +"

To directly include a file content from the repository, embrace its path " +"with triple square brackets: [[[my/file.txt]]].

\n" +msgstr "" +"\n" +"

Instructions :

\n" +"

Le contenue de la page peut utiliser le syntaxe " +"Markdown with the Extra extension.\n" +"

Les adresses de site internet sont automatiquement liées et vous pouvez " +"définir un lien vers une autre page dans la documentation en utilisant des " +"doubles crochets, comme ceci [[AnotherPage]].

\n" +"

Si vous voulez embarquer des ressources envoyées, utilisez cette [[!" +"ResourceName]] syntaxe. Pour plus de détails, consulter la FAQ.

\n" +"

Pour inclure directement un fichier dans le dépôt, indiquez son chemin " +"entre triples : [[[my/file.txt]]].

\n" + +#: IDF/gettexttemplates/idf/wiki/feedfragment-resource.xml.php:4 +msgid "Initial creation" +msgstr "Création initiale" + +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:3 +#, php-format +msgid "See the deprecated pages." +msgstr "Voir les pages obsolètes." + +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:5 +msgid "Number of pages:" +msgstr "Nombre de pages:" + +#: IDF/gettexttemplates/idf/wiki/listResources.html.php:4 +msgid "Number of resources:" +msgstr "Nombre de ressources :" + +#: IDF/gettexttemplates/idf/wiki/search.html.php:4 +msgid "Pages found:" +msgstr "Pages trouvées:" + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:3 +msgid "The form contains some errors. Please correct them to update the page." +msgstr "" +"Le formulaire contient des erreurs. Veuillez les corriger pour mettre à jour " +"la page." + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:6 +msgid "Update Page" +msgstr "Mettre à jour la page" + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:10 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:11 +msgid "Delete this page" +msgstr "Supprimer cette page" + +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:4 +msgid "Update Resource" +msgstr "Mettre à jour la ressource" + +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:8 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:9 +msgid "Delete this resource" +msgstr "Supprimer cette ressource" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:3 +msgid "" +"Attention! This page is marked as deprecated, \n" +"use it as reference only if you are sure you need these specific information." +msgstr "" +"Attention! Cette page est marquée comme obsolète.\n" +"Utilisez ces informations comme référence uniquement si vous avez vraiment\n" +"besoin de cette version." + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:5 +#, php-format +msgid "" +"You are looking at an old revision of the page \n" +"%%page.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" +"Vous consultez une ancienne révision de la page\n" +"%%page.title%%. Cette révision a été créée\n" +"par %%submitter%%." + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:10 +msgid "Table of Content" +msgstr "Sommaire" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:13 +msgid "Delete this revision" +msgstr "Supprimer cette révision" + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:3 +#, php-format +msgid "" +"You are looking at an old revision of the resource \n" +"%%resource.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" +"Vous consultez actuellement une ancienne version de la ressource \n" +"%%resource.title%%. Cette version à été créée par " +"%%submitter%%." + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:14 +msgid "Page Usage" +msgstr "Utilisation de la page" + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:15 +msgid "This resource is not used on any pages yet." +msgstr "Cette ressource n'est toujours pas utilisée sur une page." + +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:3 +msgid "A new documentation page has been created:" +msgstr "Une nouvelle page de documentation a été créée:" + +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:14 +msgid "Documentation page:" +msgstr "Page de documentation:" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:3 +msgid "The following documentation page has been updated:" +msgstr "La page de documentation suivante a été mise à jour:" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:7 +msgid "Updated by:" +msgstr "Mise à jour par:" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:13 +msgid "New content:" +msgstr "Nouveau contenu:" + +#: IDF/Issue.php:76 +msgid "owner" +msgstr "propriétaire" + +#: IDF/Issue.php:84 IDF/Wiki/Page.php:86 +msgid "interested users" +msgstr "utilisateurs intéressés" + +#: IDF/Issue.php:85 +msgid "" +"Interested users will get an email notification when the issue is changed." +msgstr "" +"Les utilisateurs intéressés vont recevoir une notification par email lorsque " +"le ticket est modifié." + +#: IDF/Issue.php:92 IDF/Project.php:94 IDF/Review.php:95 IDF/Upload.php:99 +#: IDF/Wiki/Page.php:94 +msgid "labels" +msgstr "étiquettes" + +#: IDF/Issue.php:111 IDF/IssueFile.php:102 IDF/Review.php:114 +#: IDF/Upload.php:118 IDF/Wiki/Page.php:106 IDF/Wiki/Resource.php:101 +msgid "modification date" +msgstr "date de modification" + +#: IDF/Issue.php:212 IDF/IssueComment.php:143 +#, php-format +msgid "" +"Issue %3$d, %4$s" +msgstr "" +"Ticket %3$d, " +"%4$s" + +#: IDF/Issue.php:214 +#, php-format +msgid "Creation of issue %3$d, by %4$s" +msgstr "Création du ticket %3$d, par %4$s" + +#: IDF/Issue.php:224 +#, php-format +msgid "%1$s: Issue %2$d created - %3$s" +msgstr "%1$s: Création du ticket %2$d - %3$s" + +#: IDF/Issue.php:307 +#, php-format +msgid "Issue %1$s - %2$s (%3$s)" +msgstr "Ticket %1$s - %2$s (%3$s)" + +#: IDF/Issue.php:311 +#, php-format +msgid "Updated Issue %1$s - %2$s (%3$s)" +msgstr "Ticket mis à jour %1$s - %2$s (%3$s)" + +#: IDF/IssueComment.php:51 IDF/IssueRelation.php:47 +msgid "issue" +msgstr "ticket" + +#: IDF/IssueComment.php:58 IDF/IssueFile.php:49 IDF/Review/Comment.php:62 +#: IDF/Review/FileComment.php:49 IDF/Review/FileComment.php:69 +msgid "comment" +msgstr "commentaire" + +#: IDF/IssueComment.php:72 IDF/Review/Comment.php:75 IDF/Upload.php:63 +#: IDF/Wiki/PageRevision.php:85 +msgid "changes" +msgstr "modifications" + +#: IDF/IssueComment.php:73 +msgid "Serialized array of the changes in the issue." +msgstr "Tableau sérialisé des modifications du ticket." + +#: IDF/IssueComment.php:180 +#, php-format +msgid "Comment on issue %3$d, by %4$s" +msgstr "" +"Commentaire sur le ticket %3$d, par %4$s" + +#: IDF/IssueComment.php:191 +#, php-format +msgid "%1$s: Comment on issue %2$d - %3$s" +msgstr "%1$s: Commentaire sur le ticket %2$d - %3$s" + +#: IDF/IssueFile.php:64 +msgid "file name" +msgstr "nom du fichier" + +#: IDF/IssueFile.php:70 +msgid "the file" +msgstr "le fichier" + +#: IDF/IssueFile.php:76 +msgid "file size" +msgstr "taille du fichier" + +#: IDF/IssueFile.php:84 +msgid "type" +msgstr "type" + +#: IDF/IssueFile.php:86 +msgid "Image" +msgstr "Image" + +#: IDF/IssueFile.php:87 +msgid "Other" +msgstr "Autre" + +#: IDF/IssueRelation.php:54 +msgid "verb" +msgstr "verbe" + +#: IDF/IssueRelation.php:61 +msgid "other issue" +msgstr "autre ticket" + +#: IDF/Key.php:55 +msgid "public key" +msgstr "clé publique" + +#: IDF/Key.php:90 +msgid "Invalid or unknown key data detected." +msgstr "Format de clé invalide ou inconnu." + +#: IDF/Plugin/SyncMercurial.php:78 IDF/Plugin/SyncSvn.php:81 +#, php-format +msgid "The repository %s already exists." +msgstr "Le dépôt %s existe déjà." + +#: IDF/Plugin/SyncMercurial.php:142 +#, php-format +msgid "%s does not exist or is not writable." +msgstr "%s n'existe pas ou n'est pas accessible en écriture." + +#: IDF/Plugin/SyncMonotone.php:107 IDF/Plugin/SyncMonotone.php:492 +msgid "\"mtn_repositories\" must be defined in your configuration file" +msgstr "" +"«mtn_repositories» doit être défini dans votre fichier de configuration" + +#: IDF/Plugin/SyncMonotone.php:114 IDF/Plugin/SyncMonotone.php:482 +msgid "\"mtn_usher_conf\" does not exist or is not writable" +msgstr "«mtn_usher_conf» n'existe pas ou n'est pas accessible en écriture" + +#: IDF/Plugin/SyncMonotone.php:121 +#, php-format +msgid "Could not find mtn-post-push script \"%s\"" +msgstr "Impossible de trouver le script mtn-post-push «%s»" + +#: IDF/Plugin/SyncMonotone.php:155 +#, php-format +msgid "The configuration file \"%s\" is missing" +msgstr "Le fichier de configuration «%s» est manquant" + +#: IDF/Plugin/SyncMonotone.php:164 +#, php-format +msgid "The project path \"%s\" already exists" +msgstr "Le chemin de projet «%s» existe déjà" + +#: IDF/Plugin/SyncMonotone.php:170 +#, php-format +msgid "The project path \"%s\" could not be created" +msgstr "Impossible de créer le chemin de projet «%s»" + +#: IDF/Plugin/SyncMonotone.php:208 +#, php-format +msgid "The key directory \"%s\" could not be created" +msgstr "Impossible de créer le dossier des clés «%s»" + +#: IDF/Plugin/SyncMonotone.php:227 +#, php-format +msgid "Could not parse key information: %s" +msgstr "Impossible de parcourir l'information de la clé: %s" + +#: IDF/Plugin/SyncMonotone.php:265 +#, php-format +msgid "Could not create configuration directory \"%s\"" +msgstr "Impossible de créer le dossier de configuration «%s»" + +#: IDF/Plugin/SyncMonotone.php:275 +#, php-format +msgid "Could not create symlink for configuration file \"%s\"" +msgstr "" +"Impossible de créer un lien symbolique pour le fichier de configuration «%s»" + +#: IDF/Plugin/SyncMonotone.php:293 +#, php-format +msgid "Could not write configuration file \"%s\"" +msgstr "Impossible d'écrire le fichier de configuration «%s»" + +#: IDF/Plugin/SyncMonotone.php:309 IDF/Plugin/SyncMonotone.php:525 +#, php-format +msgid "Could not parse usher configuration in \"%1$s\": %2$s" +msgstr "Impossible de parcourir la configuration d'usher dans «%1$s»: %2$s" + +#: IDF/Plugin/SyncMonotone.php:320 +#, php-format +msgid "usher configuration already contains a server entry named \"%s\"" +msgstr "La configuration d'usher contient déjà une entrée serveur nommée «%s»" + +#: IDF/Plugin/SyncMonotone.php:345 IDF/Plugin/SyncMonotone.php:546 +#, php-format +msgid "Could not write usher configuration file \"%s\"" +msgstr "Impossible d'écrire le fichier de configuration d'usher «%s»" + +#: IDF/Plugin/SyncMonotone.php:395 +#, php-format +msgid "Could not write write-permissions file \"%s\"" +msgstr "Impossible d'écrire le fichier de permissions en écriture «%s»" + +#: IDF/Plugin/SyncMonotone.php:420 +#, php-format +msgid "Could not write read-permissions file \"%s\"" +msgstr "Impossible d'écrire le fichier de permissions en lecture «%s»" + +#: IDF/Plugin/SyncMonotone.php:438 +#, php-format +msgid "Could not remove symlink \"%s\"" +msgstr "Impossible de supprimer le lien symbolique «%s»" + +#: IDF/Plugin/SyncMonotone.php:446 +#, php-format +msgid "Could not create symlink \"%s\"" +msgstr "Impossible de créer le lien symbolique «%s»" + +#: IDF/Plugin/SyncMonotone.php:500 +#, php-format +msgid "One or more paths underneath %s could not be deleted" +msgstr "Un ou plusieurs chemins sous %s n'ont pu être supprimés" + +#: IDF/Plugin/SyncMonotone.php:512 +#, php-format +msgid "Could not delete client private key \"%s\"" +msgstr "Impossible de supprimer la clé privée cliente «%s»" + +#: IDF/Plugin/SyncMonotone.php:599 IDF/Plugin/SyncMonotone.php:718 +#, php-format +msgid "Could not parse read-permissions for project \"%1$s\": %2$s" +msgstr "" +"N'a pas pu consulter les permissions de lecture pour le projet \"%1$s\": %2$s" + +#: IDF/Plugin/SyncMonotone.php:643 IDF/Plugin/SyncMonotone.php:741 +#, php-format +msgid "Could not write read-permissions for project \"%s\"" +msgstr "Impossible d'écrire les permissions en lecture pour le projet «%s»" + +#: IDF/Plugin/SyncMonotone.php:657 IDF/Plugin/SyncMonotone.php:760 +#, php-format +msgid "Could not write write-permissions file for project \"%s\"" +msgstr "Impossible d'écrire les permissions en écriture pour le projet «%s»" + +#: IDF/Plugin/SyncMonotone.php:813 +msgid "\"mtn_repositories\" must be defined in your configuration file." +msgstr "" +"«mtn_repositories» doit être défini dans votre fichier de configuration." + +#: IDF/Plugin/SyncMonotone.php:820 +#, php-format +msgid "The project path %s does not exists." +msgstr "Le chemin de projet %s n'existe pas." + +#: IDF/Plugin/SyncMonotone.php:838 +#, php-format +msgid "The command \"%s\" could not be executed." +msgstr "La commande «%s» n'a pu être exécutée." + +#: IDF/Project.php:62 IDF/Tag.php:66 +msgid "name" +msgstr "nom" + +#: IDF/Project.php:69 +msgid "short name" +msgstr "nom court" + +#: IDF/Project.php:70 +msgid "" +"Used in the URL to access the project, must be short with only letters and " +"numbers." +msgstr "" +"Utilisé dans l'adresse URL pour accéder au projet, doit être court et ne " +"comportant que des lettres et des chiffres." + +#: IDF/Project.php:78 +msgid "short description" +msgstr "Description courte" + +#: IDF/Project.php:86 IDF/Review/Patch.php:74 +msgid "description" +msgstr "description" + +#: IDF/Project.php:87 +msgid "The description can be extended using the Markdown syntax." +msgstr "La description peut être complété en utilisant la syntaxe Markdown." + +#: IDF/Project.php:100 +msgid "private" +msgstr "privé" + +#: IDF/Project.php:108 +msgid "current project activity" +msgstr "Activité du projet actuel" + +#: IDF/Project.php:159 +#, php-format +msgid "Project \"%s\" not found." +msgstr "Projet «%s» non trouvé." + +#: IDF/ProjectActivity.php:56 +msgid "date" +msgstr "Date" + +#: IDF/Review/Comment.php:55 IDF/Review/Patch.php:80 +msgid "patch" +msgstr "patch" + +#: IDF/Review/Comment.php:83 +msgid "vote" +msgstr "vote" + +#: IDF/Review/Comment.php:139 IDF/Review/Patch.php:151 +#, php-format +msgid "" +"Review %3$d, %4$s" +msgstr "" +"Revue %3$d, %4$s" + +#: IDF/Review/Comment.php:141 +#, php-format +msgid "Update of review %3$d, by %4$s" +msgstr "" +"Mis à jour de la revue %3$d, par %4$s" + +#: IDF/Review/Comment.php:151 +#, php-format +msgid "%1$s: Updated review %2$d - %3$s" +msgstr "%1$s : Mise à jour de la ressource %2$d - %3$s" + +#: IDF/Review/Comment.php:222 +#, php-format +msgid "Updated Code Review %1$s - %2$s (%3$s)" +msgstr "Mettre à jour la revue de code %1$s - %2$s (%3$s)" + +#: IDF/Review/Patch.php:52 +msgid "review" +msgstr "revue" + +#: IDF/Review/Patch.php:67 +msgid "commit" +msgstr "commit" + +#: IDF/Review/Patch.php:153 +#, php-format +msgid "Creation of review %3$d, by %4$s" +msgstr "" +"Création de la revue %3$d, par %4$s" + +#: IDF/Review/Patch.php:163 +#, php-format +msgid "%1$s: Creation of Review %2$d - %3$s" +msgstr "%1$s: Création de la revue %2$d - %3$s" + +#: IDF/Review/Patch.php:208 +#, php-format +msgid "New Code Review %1$s - %2$s (%3$s)" +msgstr "Nouvelle revue de code %1$s - %2$s (%3$s)" + +#: IDF/Scm/Git.php:309 IDF/Scm/Mercurial.php:199 +#, php-format +msgid "Folder %1$s not found in commit %2$s." +msgstr "Dossier %1$s non trouvé dans le commit %2$s." + +#: IDF/Scm/Git.php:433 IDF/Scm/Mercurial.php:216 +#, php-format +msgid "Not a valid tree: %s." +msgstr "Arbre invalide: %s." + +#: IDF/Scm/Monotone/Stdio.php:81 +msgid "Monotone client key name or hash not in project conf." +msgstr "" +"Le nom ou le hash de la clé cliente monotone ne figure pas dans la " +"configuration du projet." + +#: IDF/Scm/Monotone/Stdio.php:89 +#, php-format +msgid "The key directory %s could not be created." +msgstr "Le dossier des clés %s n'a pu être créé." + +#: IDF/Scm/Monotone/Stdio.php:100 +#, php-format +msgid "Could not write client key \"%s\"" +msgstr "Impossible d'écrire la clé cliente «%s»" + +#: IDF/Search/Occ.php:33 +msgid "occurrence" +msgstr "Occurrence" + +#: IDF/Search/Occ.php:49 +msgid "word" +msgstr "mot" + +#: IDF/Search/Occ.php:75 +msgid "occurrences" +msgstr "Occurrences" + +#: IDF/Search/Occ.php:81 +msgid "ponderated occurrence" +msgstr "Occurrence pondérée" + +#: IDF/Tag.php:59 +msgid "tag class" +msgstr "classe d'étiquette" + +#: IDF/Tag.php:60 +msgid "The class of the tag." +msgstr "La classe de l'étiquette." + +#: IDF/Tag.php:73 +msgid "lcname" +msgstr "lcname" + +#: IDF/Tag.php:74 +msgid "Lower case version of the name for fast searching." +msgstr "Version du nom en minuscules pour recherche rapide." + +#: IDF/Template/Markdown.php:84 +msgid "Create this documentation page" +msgstr "Créer cette page de documentation" + +#: IDF/Template/Markdown.php:97 +msgid "You are not allowed to access the wiki." +msgstr "Vous n'êtes pas autorisé à accéder au wiki." + +#: IDF/Template/Markdown.php:106 +msgid "The wiki resource has not been found." +msgstr "La ressource du wiki n'a pas été trouvé." + +#: IDF/Template/Markdown.php:113 +msgid "The wiki resource has not been found. Create it!" +msgstr "La ressource du wiki n'a pas été trouvé. Créez-la !" + +#: IDF/Template/Markdown.php:146 +msgid "This revision of the resource is no longer available." +msgstr "La version de cette ressource n'est plus disponible." + +#: IDF/Template/ShowUser.php:51 +msgid "Anonymous" +msgstr "Anonyme" + +#: IDF/Template/ShowUser.php:54 +msgid "Me" +msgstr "Moi" + +#: IDF/Timeline/Paginator.php:49 +msgid "Today" +msgstr "Aujourd'hui" + +#: IDF/Upload.php:70 +msgid "file" +msgstr "fichier" + +#: IDF/Upload.php:71 +msgid "The path is relative to the upload path." +msgstr "Le chemin est relatif au dossier de mise en ligne." + +#: IDF/Upload.php:78 IDF/Wiki/ResourceRevision.php:71 +msgid "file size in bytes" +msgstr "taille du fichier en octets" + +#: IDF/Upload.php:84 +msgid "MD5" +msgstr "MD5" + +#: IDF/Upload.php:106 +msgid "number of downloads" +msgstr "nombre de téléchargements" + +#: IDF/Upload.php:201 +#, php-format +msgid "Download %2$d, %3$s" +msgstr "" +"Téléchargement %2$d, " +"%3$s" + +#: IDF/Upload.php:204 +#, php-format +msgid "Addition of download %2$d, by %3$s" +msgstr "Somme des téléchargements %2$d, par %3$s" + +#: IDF/Upload.php:214 +#, php-format +msgid "%1$s: Download %2$d added - %3$s" +msgstr "%1$s: Téléchargement %2$d ajouté - %3$s" + +#: IDF/Upload.php:301 +#, php-format +msgid "New download - %1$s (%2$s)" +msgstr "Nouveau téléchargement - %1$s (%2$s)" + +#: IDF/Upload.php:305 +#, php-format +msgid "Updated download - %1$s (%2$s)" +msgstr "Téléchargement mis à jour - %1$s (%2$s)" + +#: IDF/Views/Admin.php:47 +msgid "The forge configuration has been saved." +msgstr "La configuration de la forge à été sauvegardée." + +#: IDF/Views/Admin.php:80 +msgid "This table shows the projects in the forge." +msgstr "Ce tableau affiche les projets de la forge." + +#: IDF/Views/Admin.php:85 +msgid "Short Name" +msgstr "Nom court" + +#: IDF/Views/Admin.php:87 +msgid "Repository Size" +msgstr "Taille du dépôt" + +#: IDF/Views/Admin.php:93 +msgid "No projects were found." +msgstr "Aucun projet n'a été trouvé." + +#: IDF/Views/Admin.php:116 +msgid "The label configuration has been saved." +msgstr "La configuration des étiquettes à été sauvegardée." + +#: IDF/Views/Admin.php:147 IDF/Views/Admin.php:314 IDF/Views/Wiki.php:484 +#: IDF/Views/Wiki.php:536 +#, php-format +msgid "Update %s" +msgstr "Mettre à jour %s" + +#: IDF/Views/Admin.php:155 IDF/Views/Project.php:304 +msgid "The project has been updated." +msgstr "Le projet a été mis à jour." + +#: IDF/Views/Admin.php:192 +msgid "The project has been created." +msgstr "Le projet a été créé." + +#: IDF/Views/Admin.php:223 +#, php-format +msgid "Delete %s Project" +msgstr "Supprimer le projet %s" + +#: IDF/Views/Admin.php:230 +msgid "The project has been deleted." +msgstr "Le projet a été supprimé." + +#: IDF/Views/Admin.php:260 +msgid "Not Validated User List" +msgstr "Liste des utilisateurs non confirmés" + +#: IDF/Views/Admin.php:268 +msgid "This table shows the users in the forge." +msgstr "Ce tableau affiche les utilisateurs de la forge." + +#: IDF/Views/Admin.php:272 +msgid "login" +msgstr "identifiant" + +#: IDF/Views/Admin.php:275 +msgid "Admin" +msgstr "Admin" + +#: IDF/Views/Admin.php:277 +msgid "Last Login" +msgstr "Dernière connexion" + +#: IDF/Views/Admin.php:284 +msgid "No users were found." +msgstr "Aucun utilisateur trouvé." + +#: IDF/Views/Admin.php:321 +msgid "You do not have the rights to update this user." +msgstr "Vous n'avez pas les droits pour mettre à jour cet utilisateur." + +#: IDF/Views/Admin.php:339 +msgid "The user has been updated." +msgstr "L'utilisateur a été mis à jour." + +#: IDF/Views/Admin.php:372 +#, php-format +msgid "The user %s has been created." +msgstr "L'utilisateur %s a été créé." + +#: IDF/Views/Admin.php:379 +msgid "Add User" +msgstr "Ajouter un utilisateur" + +#: IDF/Views/Admin.php:395 +msgid "Usher management" +msgstr "Administration d'usher" + +#: IDF/Views/Admin.php:432 +msgid "Usher configuration has been reloaded" +msgstr "La configuration d'usher a été rechargée" + +#: IDF/Views/Admin.php:436 +msgid "Usher has been shut down" +msgstr "Usher a été éteint" + +#: IDF/Views/Admin.php:441 +msgid "Usher has been started up" +msgstr "Usher a été démarré" + +#: IDF/Views/Admin.php:479 +#, php-format +msgid "The server \"%s\" has been started" +msgstr "Le serveur «%s» a été démarré" + +#: IDF/Views/Admin.php:483 +#, php-format +msgid "The server \"%s\" has been stopped" +msgstr "Le serveur «%s» a été arrêté" + +#: IDF/Views/Admin.php:488 +#, php-format +msgid "The server \"%s\" has been killed" +msgstr "Le serveur «%s» a été tué" + +#: IDF/Views/Admin.php:508 +#, php-format +msgid "Open connections for \"%s\"" +msgstr "Connexions actives pour «%s»" + +#: IDF/Views/Admin.php:513 +#, php-format +msgid "no connections for server \"%s\"" +msgstr "aucune connexion pour le serveur «%s»" + +#: IDF/Views/Admin.php:534 +msgid "Yes" +msgstr "Oui" + +#: IDF/Views/Admin.php:534 +msgid "No" +msgstr "Non" + +#: IDF/Views/Download.php:45 +#, php-format +msgid "%s Downloads" +msgstr "Téléchargements de %s" + +#: IDF/Views/Download.php:51 +msgid "This table shows the files to download." +msgstr "Ce tableau affiche la liste des fichiers à télécharger." + +#: IDF/Views/Download.php:67 IDF/Views/Download.php:349 +msgid "Uploaded" +msgstr "Mis en ligne" + +#: IDF/Views/Download.php:71 IDF/Views/Download.php:353 +msgid "No downloads were found." +msgstr "Aucun téléchargement n'a été trouvé." + +#: IDF/Views/Download.php:94 +#, php-format +msgid "Download %s" +msgstr "Télécharger %s" + +#: IDF/Views/Download.php:111 +#, php-format +msgid "The file %2$s has been updated." +msgstr "Le fichier %2$s a été mis à jour." + +#: IDF/Views/Download.php:144 +#, php-format +msgid "Delete Download %s" +msgstr "Supprimer le téléchargement %s" + +#: IDF/Views/Download.php:177 +msgid "The file has been deleted." +msgstr "Le fichier a été supprimé." + +#: IDF/Views/Download.php:244 +#, php-format +msgid "The file has been uploaded." +msgstr "Le fichier a été mis en ligne." + +#: IDF/Views/Download.php:271 +msgid "New Downloads from Archive" +msgstr "Nouveau téléchargements depuis l'archive" + +#: IDF/Views/Download.php:278 +msgid "The archive has been uploaded and processed." +msgstr "L'archive à été envoyée et traitée." + +#: IDF/Views/Download.php:331 +#, php-format +msgid "%1$s Downloads with Label %2$s" +msgstr "Téléchargements de %1$s avec l'étiquette %2$s" + +#: IDF/Views/Download.php:341 +#, php-format +msgid "This table shows the downloads with label %s." +msgstr "Ce tableau affiche les téléchargements avec l'étiquette %s." + +#: IDF/Views/Issue.php:41 +#, php-format +msgid "%s Open Issues" +msgstr "Tickets ouverts de %s" + +#: IDF/Views/Issue.php:51 IDF/Views/Issue.php:382 IDF/Views/User.php:75 +msgid "This table shows the open issues." +msgstr "Ce tableau affiche les tickets ouverts." + +#: IDF/Views/Issue.php:61 IDF/Views/Issue.php:220 IDF/Views/Issue.php:301 +#: IDF/Views/Issue.php:390 IDF/Views/Issue.php:542 IDF/Views/Issue.php:765 +#: IDF/Views/Issue.php:824 IDF/Views/Review.php:57 IDF/Views/User.php:81 +msgid "Id" +msgstr "Id" + +#: IDF/Views/Issue.php:64 IDF/Views/Issue.php:223 IDF/Views/Issue.php:305 +#: IDF/Views/Issue.php:393 IDF/Views/Issue.php:545 IDF/Views/Issue.php:768 +#: IDF/Views/Issue.php:827 IDF/Views/Review.php:60 IDF/Views/User.php:85 +msgid "Last Updated" +msgstr "Dernière mise à jour" + +#: IDF/Views/Issue.php:68 IDF/Views/Issue.php:227 IDF/Views/Issue.php:309 +#: IDF/Views/Issue.php:397 IDF/Views/Issue.php:549 IDF/Views/Issue.php:772 +#: IDF/Views/Issue.php:831 +msgid "No issues were found." +msgstr "Aucun ticket n'a été trouvé." + +#: IDF/Views/Issue.php:113 +msgid "Not assigned" +msgstr "Non assigné" + +#: IDF/Views/Issue.php:149 +#, php-format +msgid "Summary of tracked issues in %s." +msgstr "Résumé des tickets du projet %s." + +#: IDF/Views/Issue.php:194 +#, php-format +msgid "Watch List: Closed Issues for %s" +msgstr "Liste de surveillance: tickets fermés pour %s" + +#: IDF/Views/Issue.php:195 +#, php-format +msgid "This table shows the closed issues in your watch list for %s project." +msgstr "" +"Ce tableau affiche les tickets fermés dans votre liste de surveillance pour " +"le projet %s." + +#: IDF/Views/Issue.php:200 +#, php-format +msgid "Watch List: Open Issues for %s" +msgstr "Liste de surveillance: tickets ouverts pour %s" + +#: IDF/Views/Issue.php:201 +#, php-format +msgid "This table shows the open issues in your watch list for %s project." +msgstr "" +"Ce tableau affiche les tickets ouverts dans votre liste de surveillance pour " +"le projet %s." + +#: IDF/Views/Issue.php:277 +msgid "Watch List: Closed Issues" +msgstr "Liste de surveillance: tickets fermés" + +#: IDF/Views/Issue.php:278 +msgid "This table shows the closed issues in your watch list." +msgstr "" +"Ce tableau affiche les tickets fermés dans votre liste de surveillance." + +#: IDF/Views/Issue.php:283 +msgid "Watch List: Open Issues" +msgstr "Liste de surveillance: tickets ouverts" + +#: IDF/Views/Issue.php:284 +msgid "This table shows the open issues in your watch list." +msgstr "" +"Ce tableau affiche les tickets ouverts dans votre liste de surveillance." + +#: IDF/Views/Issue.php:303 IDF/Views/User.php:82 +msgid "Project" +msgstr "Projet" + +#: IDF/Views/Issue.php:344 +#, php-format +msgid "%1$s %2$s Submitted %3$s Issues" +msgstr "Tickets soumis par %1$s %2$s pour %3$s" + +#: IDF/Views/Issue.php:348 +#, php-format +msgid "%1$s %2$s Closed Submitted %3$s Issues" +msgstr "Tickets fermés et soumis par %1$s %2$s pour %3$s" + +#: IDF/Views/Issue.php:352 +#, php-format +msgid "%1$s %2$s Closed Working %3$s Issues" +msgstr "Tickets fermés et assignés à %1$s %2$s pour %3$s" + +#: IDF/Views/Issue.php:356 +#, php-format +msgid "%1$s %2$s Working %3$s Issues" +msgstr "Tickets assignés à %1$s %2$s pour %3$s" + +#: IDF/Views/Issue.php:417 +msgid "Submit a new issue" +msgstr "Soumettre un nouveau ticket" + +#: IDF/Views/Issue.php:433 +#, php-format +msgid "Issue %2$d has been created." +msgstr "Ticket %2$d à été créé." + +#: IDF/Views/Issue.php:490 +#, php-format +msgid "Search issues - %s" +msgstr "Recherche de tickets - %s" + +#: IDF/Views/Issue.php:492 +#, php-format +msgid "Search closed issues - %s" +msgstr "Recherche de tickets fermés - %s" + +#: IDF/Views/Issue.php:539 +msgid "This table shows the found issues." +msgstr "Ce tableau affiche les tickets trouvés." + +#: IDF/Views/Issue.php:604 +#, php-format +msgid "Issue %2$d: %3$s" +msgstr "Ticket %2$d : %3$s" + +#: IDF/Views/Issue.php:628 +#, php-format +msgid "Issue %2$d has been updated." +msgstr "Ticket %2$d à été mis à jour." + +#: IDF/Views/Issue.php:718 +#, php-format +msgid "View %s" +msgstr "Voir %s" + +#: IDF/Views/Issue.php:745 +#, php-format +msgid "%s Closed Issues" +msgstr "Tickets fermés de %s" + +#: IDF/Views/Issue.php:755 +msgid "This table shows the closed issues." +msgstr "Ce tableau affiche les tickets fermés." + +#: IDF/Views/Issue.php:798 +#, php-format +msgid "%1$s Issues with Label %2$s" +msgstr "Tickets de %1$s avec l'étiquette %2$s" + +#: IDF/Views/Issue.php:801 +#, php-format +msgid "%1$s Closed Issues with Label %2$s" +msgstr "Tickets fermés de %1$s avec l'étiquette %2$s" + +#: IDF/Views/Issue.php:814 +#, php-format +msgid "This table shows the issues with label %s." +msgstr "Ce tableau affiche les tickets avec l'étiquette %s." + +#: IDF/Views/Issue.php:937 +msgid "The issue has been removed from your watch list." +msgstr "Le ticket a été supprimé de votre liste de surveillance." + +#: IDF/Views/Issue.php:940 +msgid "The issue has been added to your watch list." +msgstr "Le ticket a été ajouté à votre liste de surveillance." + +#: IDF/Views/Issue.php:1037 +msgid "On your watch list." +msgstr "Dans votre liste de surveillance." + +#: IDF/Views/Project.php:95 +msgid "Issues and Comments" +msgstr "Tickets et commentaires" + +#: IDF/Views/Project.php:99 +msgid "Documents" +msgstr "Documents" + +#: IDF/Views/Project.php:101 +msgid "Reviews and Patches" +msgstr "Revues et patchs" + +#: IDF/Views/Project.php:180 +msgid "This table shows the project updates." +msgstr "Ce tableau affiche les mises à jour du projet." + +#: IDF/Views/Project.php:191 +msgid "Change" +msgstr "Modification" + +#: IDF/Views/Project.php:195 +msgid "No changes were found." +msgstr "Aucune modification n'a été trouvée." + +#: IDF/Views/Project.php:296 +#, php-format +msgid "%s Project Summary" +msgstr "Résumé du projet %s" + +#: IDF/Views/Project.php:335 +#, php-format +msgid "%s Issue Tracking Configuration" +msgstr "Configuration du gestionnaire de tickets de %s" + +#: IDF/Views/Project.php:344 +msgid "The issue tracking configuration has been saved." +msgstr "La configuration du gestionnaire de tickets a été sauvegardée." + +#: IDF/Views/Project.php:381 +#, php-format +msgid "%s Downloads Configuration" +msgstr "Configuration des téléchargements de %s" + +#: IDF/Views/Project.php:393 +msgid "The downloads configuration has been saved." +msgstr "La configuration des téléchargements a été sauvegardée." + +#: IDF/Views/Project.php:428 +#, php-format +msgid "%s Documentation Configuration" +msgstr "Configuration de la documentation de %s" + +#: IDF/Views/Project.php:437 +msgid "The documentation configuration has been saved." +msgstr "La configuration de la documentation a été sauvegardée." + +#: IDF/Views/Project.php:471 +#, php-format +msgid "%s Project Members" +msgstr "Membres du projet %s" + +#: IDF/Views/Project.php:480 +msgid "The project membership has been saved." +msgstr "Les membres du projet ont été sauvegardés." + +#: IDF/Views/Project.php:503 +#, php-format +msgid "%s Tabs Access Rights" +msgstr "Droits d'accès aux onglets de %s" + +#: IDF/Views/Project.php:517 +msgid "" +"The project tabs access rights and notification settings have been saved." +msgstr "" +"Les paramètres de l'onglet de droit d'accès et de notifications on été " +"sauvegardés." + +#: IDF/Views/Project.php:566 +#, php-format +msgid "%s Source" +msgstr "Source de %s" + +#: IDF/Views/Project.php:580 +msgid "The project source configuration has been saved." +msgstr "La configuration de la source du projet a été sauvegardée." + +#: IDF/Views/Review.php:41 +#, php-format +msgid "%s Code Reviews" +msgstr "Revues de code de %s" + +#: IDF/Views/Review.php:48 +msgid "This table shows the latest reviews." +msgstr "Ce tableau affiche les dernières revues." + +#: IDF/Views/Review.php:64 +msgid "No reviews were found." +msgstr "Aucune revue n'a été trouvée." + +#: IDF/Views/Review.php:94 +#, php-format +msgid "The code review %2$d has been created." +msgstr "La revue de code %2$d à été crée." + +#: IDF/Views/Review.php:140 +#, php-format +msgid "Review %2$d: %3$s" +msgstr "Revue %2$d : %3$s" + +#: IDF/Views/Review.php:160 +#, php-format +msgid "Your code review %2$d has been published." +msgstr "Votre revue de code %2$d à été publiée." + +#: IDF/Views/Source.php:40 +#, php-format +msgid "%s Source Help" +msgstr "Aide sur la source de %s" + +#: IDF/Views/Source.php:58 +#, php-format +msgid "%s Invalid Revision" +msgstr "Révision invalide de %s" + +#: IDF/Views/Source.php:82 +#, php-format +msgid "%s Ambiguous Revision" +msgstr "Révision ambiguë de %s" + +#: IDF/Views/Source.php:107 +#, php-format +msgid "%1$s %2$s Change Log" +msgstr "Journal des modifications %2$s de %1$s" + +#: IDF/Views/Source.php:153 IDF/Views/Source.php:234 IDF/Views/Source.php:362 +#, php-format +msgid "%1$s %2$s Source Tree" +msgstr "Arbre des sources %2$s de %1$s" + +#: IDF/Views/Source.php:310 +#, php-format +msgid "%s Commit Details" +msgstr "Détails d'un commit de %s" + +#: IDF/Views/Source.php:311 +#, php-format +msgid "%1$s Commit Details - %2$s" +msgstr "%1$s Détails du commit - %2$s" + +#: IDF/Views/User.php:59 +msgid "Your Dashboard - Working Issues" +msgstr "Votre tableau de bord - Tickets assignés" + +#: IDF/Views/User.php:62 +msgid "Your Dashboard - Submitted Issues" +msgstr "Votre tableau de bord - Tickets soumis" + +#: IDF/Views/User.php:89 +msgid "No issues are assigned to you, yeah!" +msgstr "Aucun ticket ne vous est assigné, youpi!" + +#: IDF/Views/User.php:89 +msgid "All the issues you submitted are fixed, yeah!" +msgstr "Tous les tickets que vous avez soumis ont été résolus, youpi!" + +#: IDF/Views/User.php:121 +msgid "Your personal information has been updated." +msgstr "Vos informations personnelles ont été mises à jour." + +#: IDF/Views/User.php:133 +msgid "Your Account" +msgstr "Votre compte" + +#: IDF/Views/User.php:157 +msgid "The public key has been deleted." +msgstr "La clé publique a été supprimée." + +#: IDF/Views/User.php:177 +msgid "The address has been deleted." +msgstr "L'adresse a été supprimée." + +#: IDF/Views/User.php:200 +msgid "Confirm The Email Change" +msgstr "Confirmez le changement d'email" + +#: IDF/Views/User.php:232 +#, php-format +msgid "Your new email address \"%s\" has been validated. Thank you!" +msgstr "Votre nouvelle adresse email «%s» a été validée. Merci!" + +#: IDF/Views/Wiki.php:41 +#, php-format +msgid "%s Documentation" +msgstr "Documentation de %s" + +#: IDF/Views/Wiki.php:48 +msgid "This table shows the documentation pages." +msgstr "Ce tableau liste les pages de documentation." + +#: IDF/Views/Wiki.php:61 IDF/Views/Wiki.php:144 IDF/Views/Wiki.php:185 +msgid "Page Title" +msgstr "Titre de la page" + +#: IDF/Views/Wiki.php:63 IDF/Views/Wiki.php:103 IDF/Views/Wiki.php:146 +#: IDF/Views/Wiki.php:187 +msgid "Updated" +msgstr "Mise à jour" + +#: IDF/Views/Wiki.php:67 IDF/Views/Wiki.php:191 +msgid "No documentation pages were found." +msgstr "Aucune page de documentation n'a été trouvée." + +#: IDF/Views/Wiki.php:88 +#, php-format +msgid "%s Documentation Resources" +msgstr "%s Documentation de la ressource" + +#: IDF/Views/Wiki.php:94 +msgid "This table shows the resources that can be used on documentation pages." +msgstr "" +"Ce tableau montre quelles ressources peuvent être utilisé dans les pages de " +"documentations." + +#: IDF/Views/Wiki.php:100 +msgid "Resource Title" +msgstr "Titre de la ressource" + +#: IDF/Views/Wiki.php:107 +msgid "No resources were found." +msgstr "Aucune ressource n'a été trouvée." + +#: IDF/Views/Wiki.php:128 +#, php-format +msgid "Documentation Search - %s" +msgstr "Recherche dans la documentation - %s" + +#: IDF/Views/Wiki.php:139 +msgid "This table shows the pages found." +msgstr "Ce tableau liste les pages trouvées." + +#: IDF/Views/Wiki.php:150 +msgid "No pages were found." +msgstr "Aucune page n'a été trouvée." + +#: IDF/Views/Wiki.php:169 +#, php-format +msgid "%1$s Documentation Pages with Label %2$s" +msgstr "Pages de documentation de %1$s avec l'étiquette %2$s" + +#: IDF/Views/Wiki.php:179 +#, php-format +msgid "This table shows the documentation pages with label %s." +msgstr "Ce tableau liste les pages de documentation avec l'étiquette %s." + +#: IDF/Views/Wiki.php:222 +#, php-format +msgid "The page %2$s has been created." +msgstr "La page %2$s à été créée." + +#: IDF/Views/Wiki.php:265 +#, php-format +msgid "The resource %2$s has been created." +msgstr "La ressource %2$s à été créée." + +#: IDF/Views/Wiki.php:409 IDF/Views/Wiki.php:448 +msgid "The old revision has been deleted." +msgstr "L'ancienne révision a été supprimée." + +#: IDF/Views/Wiki.php:415 IDF/Views/Wiki.php:454 +#, php-format +msgid "Delete Old Revision of %s" +msgstr "Supprimer l'ancienne révision de %s" + +#: IDF/Views/Wiki.php:496 +#, php-format +msgid "The page %2$s has been updated." +msgstr "La page %2$s à été mise à jour." + +#: IDF/Views/Wiki.php:548 +#, php-format +msgid "The resource %2$s has been updated." +msgstr "La ressource %2$s à été mise à jour." + +#: IDF/Views/Wiki.php:583 +msgid "The documentation page has been deleted." +msgstr "La page de documentation a été supprimée." + +#: IDF/Views/Wiki.php:591 +#, php-format +msgid "Delete Page %s" +msgstr "Supprimer la page %s" + +#: IDF/Views/Wiki.php:623 +msgid "The documentation resource has been deleted." +msgstr "La documentation de la ressource à été supprimée." + +#: IDF/Views/Wiki.php:631 +#, php-format +msgid "Delete Resource %s" +msgstr "Ressource supprimée %s" + +#: IDF/Views.php:173 IDF/Views.php:199 +msgid "Confirm Your Account Creation" +msgstr "Confirmez la création de votre compte" + +#: IDF/Views.php:219 +msgid "Welcome! You can now participate in the life of your project of choice." +msgstr "" +"Bienvenue! Vous pouvez maintenant prendre part à la vie du projet de votre " +"choix." + +#: IDF/Views.php:245 IDF/Views.php:269 IDF/Views.php:310 +msgid "Password Recovery" +msgstr "Récupération du mot de passe" + +#: IDF/Views.php:289 +msgid "" +"Welcome back! Next time, you can use your broswer options to remember the " +"password." +msgstr "" +"Bienvenue à nouveau! La prochaine fois, vous pouvez utiliser les options de " +"votre navigateur pour qu'il se souvienne de votre mot de passe." + +#: IDF/Views.php:331 +msgid "Here to Help You!" +msgstr "Ici pour vous aider!" + +#: IDF/Views.php:347 +msgid "InDefero Upload Archive Format" +msgstr "Format de l'archive envoyé : InDefero" + +#: IDF/Views.php:363 +msgid "InDefero API (Application Programming Interface)" +msgstr "API d'InDefero (interface de programmation applicative)" + +#: IDF/Wiki/Page.php:62 IDF/Wiki/Resource.php:64 +msgid "title" +msgstr "titre" + +#: IDF/Wiki/Page.php:63 +msgid "" +"The title of the page must only contain letters, digits or the dash " +"character. For example: My-new-Wiki-Page." +msgstr "" +"Le titre de la page ne doit contenir que des lettres, des chiffres ou le " +"tiret (-). Exemple: Ma-nouvelle-page." + +#: IDF/Wiki/Page.php:71 +msgid "A one line description of the page content." +msgstr "Une description d'une ligne du contenu de la page." + +#: IDF/Wiki/Page.php:196 IDF/Wiki/PageRevision.php:196 +#, php-format +msgid "%2$s, %3$s" +msgstr "%2$s, %3$s" + +#: IDF/Wiki/Page.php:198 +#, php-format +msgid "Creation of page %2$s, by %3$s" +msgstr "Création de le page %2$s, par %3$s" + +#: IDF/Wiki/Page.php:208 +#, php-format +msgid "%1$s: Documentation page %2$s added - %3$s" +msgstr "%1$s: Page de documentation %2$s ajouté - %3$s" + +#: IDF/Wiki/PageRevision.php:48 +msgid "page" +msgstr "page" + +#: IDF/Wiki/PageRevision.php:66 IDF/Wiki/ResourceRevision.php:64 +msgid "A one line description of the changes." +msgstr "Une description d'une ligne des modifications effectuées." + +#: IDF/Wiki/PageRevision.php:72 +msgid "content" +msgstr "contenu" + +#: IDF/Wiki/PageRevision.php:218 IDF/Wiki/ResourceRevision.php:311 +#, php-format +msgid "Change of %2$s, by %3$s" +msgstr "Changement de %2$s, par %3$s" + +#: IDF/Wiki/PageRevision.php:231 +#, php-format +msgid "%1$s: Documentation page %2$s updated - %3$s" +msgstr "%1$s: Page de documentation %2$s mise à jjour - %3$s" + +#: IDF/Wiki/PageRevision.php:293 +#, php-format +msgid "New Documentation Page %1$s - %2$s (%3$s)" +msgstr "Nouvelle page de documentation %1$s - %2$s (%3$s)" + +#: IDF/Wiki/PageRevision.php:297 +#, php-format +msgid "Documentation Page Changed %1$s - %2$s (%3$s)" +msgstr "Page de documentation changée %1$s - %2$s (%3$s)" + +#: IDF/Wiki/Resource.php:65 +msgid "" +"The title of the resource must only contain letters, digits, dots or the " +"dash character. For example: my-resource.png." +msgstr "" +"Le titre de la ressource ne peut seulement contenir que des lettres, des " +"chiffres, des points, ou des tirets. Par exemple : my-resource.png." + +#: IDF/Wiki/Resource.php:72 +msgid "MIME media type" +msgstr "Type média MIME" + +#: IDF/Wiki/Resource.php:73 +msgid "The MIME media type of the resource." +msgstr "Le type média MIME de la ressource." + +#: IDF/Wiki/Resource.php:81 +msgid "A one line description of the resource." +msgstr "Une description en une ligne de la ressource." + +#: IDF/Wiki/Resource.php:176 IDF/Wiki/ResourceRevision.php:308 +#, php-format +msgid "%2$s, %3$s" +msgstr "%2$s, %3$s" + +#: IDF/Wiki/Resource.php:178 +#, php-format +msgid "Creation of resource %2$s, by %3$s" +msgstr "Création de la ressource %2$s, par %3$s" + +#: IDF/Wiki/Resource.php:188 +#, php-format +msgid "%1$s: Documentation resource %2$s added - %3$s" +msgstr "%1$s: Documentation de la ressource %2$s ajoutée - %3$s" + +#: IDF/Wiki/ResourceRevision.php:47 +msgid "resource" +msgstr "Ressource" + +#: IDF/Wiki/ResourceRevision.php:78 +msgid "File extension" +msgstr "Extension du fichier" + +#: IDF/Wiki/ResourceRevision.php:79 +msgid "The file extension of the uploaded resource." +msgstr "L'extension du fichier de la ressource envoyée." + +#: IDF/Wiki/ResourceRevision.php:94 +msgid "page usage" +msgstr "Utilisation de la page" + +#: IDF/Wiki/ResourceRevision.php:116 +#, php-format +msgid "id %d: %s" +msgstr "ID %d: %s" + +#: IDF/Wiki/ResourceRevision.php:263 +#, php-format +msgid "Download (%s)" +msgstr "Téléchargements (%s)" + +#: IDF/Wiki/ResourceRevision.php:270 +msgid "View resource details" +msgstr "Voir les détails de la ressource" + +#: IDF/Wiki/ResourceRevision.php:324 +#, php-format +msgid "%1$s: Documentation resource %2$s updated - %3$s" +msgstr "%1$s: Documentation de la ressource %2$s mis à jour - %3$s" diff --git a/indefero/src/IDF/locale/idf.pot b/indefero/src/IDF/locale/idf.pot new file mode 100644 index 0000000..a1ce29b --- /dev/null +++ b/indefero/src/IDF/locale/idf.pot @@ -0,0 +1,5385 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2012-03-22 01:16+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" + +#: IDF/Commit.php:55 IDF/Conf.php:54 IDF/Issue.php:52 +#: IDF/ProjectActivity.php:49 IDF/Review.php:65 IDF/Search/Occ.php:69 +#: IDF/Tag.php:52 IDF/Upload.php:49 IDF/Wiki/Page.php:54 +#: IDF/Wiki/Resource.php:56 +msgid "project" +msgstr "" + +#: IDF/Commit.php:63 IDF/Issue.php:67 IDF/IssueComment.php:65 +#: IDF/IssueFile.php:57 IDF/IssueRelation.php:69 IDF/Review/Comment.php:69 +#: IDF/Review.php:80 IDF/Upload.php:91 IDF/Wiki/Page.php:78 +#: IDF/Wiki/PageRevision.php:79 IDF/Wiki/Resource.php:88 +#: IDF/Wiki/ResourceRevision.php:86 +msgid "submitter" +msgstr "" + +#: IDF/Commit.php:87 IDF/Issue.php:60 IDF/Review/Patch.php:60 +#: IDF/Review.php:73 IDF/Upload.php:57 IDF/Wiki/Page.php:70 +#: IDF/Wiki/PageRevision.php:65 IDF/Wiki/Resource.php:80 +#: IDF/Wiki/ResourceRevision.php:63 +msgid "summary" +msgstr "" + +#: IDF/Commit.php:93 +msgid "changelog" +msgstr "" + +#: IDF/Commit.php:100 IDF/Issue.php:105 IDF/IssueComment.php:79 +#: IDF/IssueFile.php:96 IDF/IssueRelation.php:75 IDF/Review/Comment.php:90 +#: IDF/Review/FileComment.php:75 IDF/Review/Patch.php:87 IDF/Review.php:108 +#: IDF/Upload.php:112 IDF/Wiki/Page.php:100 IDF/Wiki/PageRevision.php:92 +#: IDF/Wiki/Resource.php:95 IDF/Wiki/ResourceRevision.php:101 +msgid "creation date" +msgstr "" + +#: IDF/Commit.php:238 +#, php-format +msgid "Commit %1$s, by %2$s" +msgstr "" + +#: IDF/Commit.php:337 +#, php-format +msgid "New Commit %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Conf.php:61 IDF/Gconf.php:73 +msgid "key" +msgstr "" + +#: IDF/Conf.php:67 IDF/Gconf.php:79 IDF/ProjectActivity.php:62 +msgid "value" +msgstr "" + +#: IDF/Diff.php:460 +msgid "Old" +msgstr "" + +#: IDF/Diff.php:460 +msgid "New" +msgstr "" + +#: IDF/EmailAddress.php:49 IDF/Key.php:49 +msgid "user" +msgstr "" + +#: IDF/EmailAddress.php:55 +msgid "email" +msgstr "" + +#: IDF/Form/Admin/ForgeConf.php:34 +msgid "Custom forge page enabled" +msgstr "" + +#: IDF/Form/Admin/ForgeConf.php:39 IDF/Form/WikiPageCreate.php:80 +#: IDF/Form/WikiPageUpdate.php:72 +msgid "Content" +msgstr "" + +#: IDF/Form/Admin/LabelConf.php:40 +msgid "Predefined project labels" +msgstr "" + +#: IDF/Form/Admin/LabelConf.php:55 +#, php-format +msgid "" +"The label \"%s\" is invalid: A label must only consist of alphanumeric " +"characters and dashes, and can optionally contain a \":\" with a group " +"prefix." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:38 IDF/Views/Project.php:600 +msgid "git" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:39 IDF/Views/Project.php:601 +msgid "Subversion" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:40 IDF/Views/Project.php:602 +msgid "mercurial" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:41 IDF/Views/Project.php:603 +msgid "monotone" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:49 IDF/Form/Admin/ProjectUpdate.php:44 +#: IDF/Form/ProjectConf.php:39 IDF/Views/Admin.php:86 IDF/Views/Admin.php:273 +msgid "Name" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:55 IDF/Form/TabsConf.php:101 +#: IDF/gettexttemplates/idf/base-full.html.php:5 +#: IDF/gettexttemplates/idf/base-full.html~.php:5 +#: IDF/gettexttemplates/idf/base.html.php:5 +#: IDF/gettexttemplates/idf/base.html~.php:5 +#: IDF/gettexttemplates/idf/main-menu.html.php:9 +#: IDF/gettexttemplates/idf/project-list.html.php:5 +#: IDF/gettexttemplates/idf/project-list.html.php:7 +msgid "Private project" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:62 +msgid "Shortname" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:64 +msgid "" +"It must be unique for each project and composed only of letters, digits and " +"dash (-) like \"my-project\"." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:69 IDF/Form/Admin/ProjectUpdate.php:50 +msgid "Short description" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:70 IDF/Form/Admin/ProjectUpdate.php:51 +#: IDF/Project.php:79 +msgid "A one line description of the project." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:77 IDF/Form/Admin/ProjectUpdate.php:58 +#: IDF/Form/ProjectConf.php:56 +msgid "External URL" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:84 +msgid "Repository type" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:92 +msgid "Remote Subversion repository" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:99 IDF/Form/SourceConf.php:40 +msgid "Repository username" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:106 IDF/Form/SourceConf.php:47 +msgid "Repository password" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:113 IDF/Form/Admin/ProjectUpdate.php:66 +msgid "Master branch" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:116 IDF/Form/Admin/ProjectUpdate.php:69 +msgid "" +"This should be a world-wide unique identifier for your project. A reverse " +"DNS notation like \"com.my-domain.my-project\" is a good idea." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:121 IDF/Form/Admin/ProjectUpdate.php:95 +#: IDF/Form/MembersConf.php:46 IDF/Form/TabsConf.php:53 +#: IDF/Form/TabsConf.php:72 +msgid "Project owners" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:130 IDF/Form/Admin/ProjectUpdate.php:103 +#: IDF/Form/MembersConf.php:54 IDF/Form/TabsConf.php:52 +#: IDF/Form/TabsConf.php:78 +msgid "Project members" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:140 IDF/Form/Admin/ProjectUpdate.php:85 +#: IDF/Form/IssueCreate.php:168 IDF/Form/IssueUpdate.php:164 +#: IDF/Form/ProjectConf.php:73 IDF/Form/UpdateUpload.php:71 +#: IDF/Form/Upload.php:70 IDF/Form/WikiPageCreate.php:93 +#: IDF/Form/WikiPageUpdate.php:104 +msgid "Labels" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:155 +msgid "Project template" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:157 +msgid "" +"Use the given project to initialize the new project. Access rights and " +"general configuration will be taken from the template project." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:204 +msgid "" +"Only a remote repository available through HTTP or HTTPS is allowed. For " +"example \"http://somewhere.com/svn/trunk\"." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:220 IDF/Form/Admin/ProjectUpdate.php:117 +msgid "" +"The master branch is empty or contains illegal characters, please use only " +"letters, digits, dashes and dots as separators." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:230 IDF/Form/Admin/ProjectUpdate.php:128 +msgid "This master branch is already used. Please select another one." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:241 +msgid "" +"This shortname contains illegal characters, please use only letters, digits " +"and dash (-)." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:244 +msgid "The shortname cannot start with the dash (-) character." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:247 +msgid "The shortname cannot end with the dash (-) character." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:252 +msgid "This shortname is already used. Please select another one." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:303 IDF/Form/Admin/ProjectDelete.php:78 +#: IDF/Form/Admin/ProjectUpdate.php:153 IDF/Form/Admin/UserCreate.php:106 +#: IDF/Form/Admin/UserUpdate.php:191 IDF/Form/IssueCreate.php:338 +#: IDF/Form/IssueUpdate.php:329 IDF/Form/MembersConf.php:64 +#: IDF/Form/Password.php:76 IDF/Form/Register.php:112 +#: IDF/Form/ReviewCreate.php:187 IDF/Form/ReviewFileComment.php:143 +#: IDF/Form/TabsConf.php:122 IDF/Form/UpdateUpload.php:126 +#: IDF/Form/Upload.php:149 IDF/Form/UploadArchive.php:137 +#: IDF/Form/UserAccount.php:216 IDF/Form/UserChangeEmail.php:80 +#: IDF/Form/WikiPageCreate.php:167 IDF/Form/WikiPageDelete.php:59 +#: IDF/Form/WikiPageUpdate.php:178 IDF/Form/WikiResourceCreate.php:123 +#: IDF/Form/WikiResourceDelete.php:59 IDF/Form/WikiResourceUpdate.php:124 +msgid "Cannot save the model from an invalid form." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:341 +msgid "" +"Click on the Project Management tab to set the description of your project." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:426 +msgid "This project is not available." +msgstr "" + +#: IDF/Form/Admin/ProjectDelete.php:41 +msgid "Confirmation code" +msgstr "" + +#: IDF/Form/Admin/ProjectDelete.php:46 +msgid "I have made a backup of all the important data of this project." +msgstr "" + +#: IDF/Form/Admin/ProjectDelete.php:55 +msgid "" +"The confirmation code does not match. Please provide a valid confirmation " +"code to delete the project." +msgstr "" + +#: IDF/Form/Admin/ProjectDelete.php:63 +msgid "Sorry, you really need to backup your data before deletion." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:37 IDF/Form/Admin/UserUpdate.php:38 +#: IDF/Form/RegisterConfirmation.php:50 IDF/Form/UserAccount.php:40 +msgid "First name" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:46 IDF/Form/Admin/UserUpdate.php:47 +#: IDF/Form/RegisterConfirmation.php:59 IDF/Form/UserAccount.php:49 +msgid "Last name" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:56 +msgid "Login" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:60 +msgid "" +"The login must be between 3 and 15 characters long and contains only letters " +"and digits." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:69 IDF/Form/Admin/UserUpdate.php:57 +msgid "Email" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:71 +msgid "" +"Double check the email address as the password is sent directly to the user." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:76 IDF/Form/Admin/UserUpdate.php:67 +#: IDF/Form/UserAccount.php:66 +msgid "Language" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:87 IDF/Form/UserAccount.php:161 +msgid "Add a public key" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:92 +msgid "" +"Paste a SSH or monotone public key. Be careful to not provide your private " +"key here!" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:157 +msgid "Your details to access your forge." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:189 IDF/Form/UserAccount.php:429 +#: IDF/Form/UserAccount.php:438 +#, php-format +msgid "The email \"%s\" is already used." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:198 IDF/Form/Register.php:72 +#, php-format +msgid "The login \"%s\" can only contain letters and digits." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:203 IDF/Form/Register.php:77 +#, php-format +msgid "The login \"%s\" is already used, please find another one." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:78 +msgid "Password" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:81 +msgid "Leave blank if you do not want to change the password." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:81 +msgid "" +"The password must be hard for other people to guess, but easy for the user " +"to remember." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:89 +msgid "Confirm password" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:100 IDF/Form/IssueCreate.php:66 +#: IDF/Form/ProjectConf.php:48 IDF/Form/ReviewCreate.php:54 +#: IDF/Form/UpdateUpload.php:51 IDF/Form/Upload.php:49 +#: IDF/Form/UserAccount.php:101 IDF/Form/WikiPageCreate.php:70 +#: IDF/Form/WikiPageUpdate.php:60 IDF/Form/WikiResourceCreate.php:54 +#: IDF/Form/WikiResourceUpdate.php:46 IDF/Views/Wiki.php:102 +msgid "Description" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:109 IDF/Form/UserAccount.php:110 +msgid "Twitter username" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:119 IDF/Form/UserAccount.php:120 +msgid "Public email address" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:129 IDF/Form/UserAccount.php:130 +msgid "Website URL" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:139 IDF/Form/UserAccount.php:140 +msgid "Upload custom avatar" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:146 IDF/Form/UserAccount.php:147 +msgid "" +"An image file with a width and height not larger than 60 pixels (bigger " +"images are scaled down)." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:151 IDF/Form/UserAccount.php:152 +msgid "Remove custom avatar" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:155 IDF/Form/UserAccount.php:156 +msgid "Tick this to delete the custom avatar." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:161 IDF/Views/Admin.php:274 +msgid "Staff" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:164 +msgid "If you give staff rights to a user, you really need to trust him." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:172 IDF/Views/Admin.php:276 +msgid "Active" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:176 +msgid "" +"If the user is not getting the confirmation email or is abusing the system, " +"you can directly enable or disable their account here." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:274 +msgid "--- is not a valid first name." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:290 +msgid "" +"A user with this email already exists, please provide another email address." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:301 IDF/Form/UserAccount.php:398 +msgid "For security reason, you cannot upload a file with this extension." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:316 IDF/Form/UserAccount.php:461 +msgid "The passwords do not match. Please give them again." +msgstr "" + +#: IDF/Form/Field/EmailList.php:45 +msgid "Please enter one or more valid email addresses." +msgstr "" + +#: IDF/Form/IssueCreate.php:57 IDF/Form/IssueUpdate.php:46 +#: IDF/Form/ReviewCreate.php:45 IDF/Form/ReviewFileComment.php:73 +#: IDF/Form/UpdateUpload.php:42 IDF/Form/Upload.php:40 +#: IDF/gettexttemplates/idf/issues/base.html.php:3 IDF/Views/Download.php:65 +#: IDF/Views/Download.php:347 IDF/Views/Issue.php:62 IDF/Views/Issue.php:221 +#: IDF/Views/Issue.php:302 IDF/Views/Issue.php:391 IDF/Views/Issue.php:543 +#: IDF/Views/Issue.php:766 IDF/Views/Issue.php:825 IDF/Views/Review.php:58 +#: IDF/Views/User.php:83 IDF/Views/Wiki.php:62 IDF/Views/Wiki.php:145 +#: IDF/Views/Wiki.php:186 +msgid "Summary" +msgstr "" + +#: IDF/Form/IssueCreate.php:76 IDF/Form/IssueUpdate.php:66 +#: IDF/Form/ReviewCreate.php:83 +msgid "The \"upload_issue_path\" configuration variable was not set." +msgstr "" + +#: IDF/Form/IssueCreate.php:86 IDF/Form/IssueUpdate.php:76 +msgid "Attach a file" +msgstr "" + +#: IDF/Form/IssueCreate.php:99 IDF/Form/IssueUpdate.php:89 +#: IDF/Form/ReviewCreate.php:103 IDF/Form/ReviewFileComment.php:83 +#: IDF/Views/Issue.php:63 IDF/Views/Issue.php:222 IDF/Views/Issue.php:304 +#: IDF/Views/Issue.php:392 IDF/Views/Issue.php:544 IDF/Views/Issue.php:767 +#: IDF/Views/Issue.php:826 IDF/Views/Review.php:59 IDF/Views/User.php:84 +msgid "Status" +msgstr "" + +#: IDF/Form/IssueCreate.php:108 IDF/Form/IssueUpdate.php:99 +msgid "Owner" +msgstr "" + +#: IDF/Form/IssueCreate.php:118 IDF/Form/IssueUpdate.php:112 +#: IDF/Form/IssueUpdate.php:129 +msgid "This issue" +msgstr "" + +#: IDF/Form/IssueCreate.php:210 +msgid "You cannot add a label with the \"Status\" prefix to an issue." +msgstr "" + +#: IDF/Form/IssueCreate.php:211 IDF/Form/IssueCreate.php:218 +#: IDF/Form/UpdateUpload.php:110 IDF/Form/Upload.php:121 +#: IDF/Form/WikiPageCreate.php:151 IDF/Form/WikiPageUpdate.php:162 +msgid "You provided an invalid label." +msgstr "" + +#: IDF/Form/IssueCreate.php:217 IDF/Form/UpdateUpload.php:109 +#, php-format +msgid "You cannot provide more than one label from the %s class to an issue." +msgstr "" + +#: IDF/Form/IssueCreate.php:228 IDF/Form/IssueUpdate.php:194 +msgid "You need to provide a description of the issue." +msgstr "" + +#: IDF/Form/IssueCreate.php:251 IDF/Form/ReviewCreate.php:159 +msgid "You provided an invalid status." +msgstr "" + +#: IDF/Form/IssueCreate.php:272 +msgid "You provided an invalid relation type." +msgstr "" + +#: IDF/Form/IssueCreate.php:294 +#, php-format +msgid "The value \"%s\" is not a valid issue id." +msgstr "" + +#: IDF/Form/IssueCreate.php:300 +#, php-format +msgid "The issue \"%s\" does not exist." +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:86 +msgid "is related to" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:87 +msgid "blocks" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:88 +msgid "is blocked by" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:89 +msgid "duplicates" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:90 +msgid "is duplicated by" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:97 +msgid "" +"Define an issue template to hint the reporter to provide certain information" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:106 +msgid "Open issue status values" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:114 +msgid "Closed issue status values" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:123 +msgid "Predefined issue labels" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:125 +msgid "" +"The first \"Type:\" and \"Priority:\" entries found in this list are " +"automatically chosen as defaults for new issues." +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:133 +msgid "Each issue may have at most one label with each of these classes." +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:140 +msgid "Issue relations" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:142 +msgid "" +"You can define bidirectional relations like \"is related to\" or \"blocks, " +"is blocked by\". For standard relations pre-configured translations exist, " +"new relations should however be defined in a language that is understood by " +"all project members." +msgstr "" + +#: IDF/Form/IssueUpdate.php:56 IDF/Form/ReviewFileComment.php:45 +#: IDF/Form/WikiPageUpdate.php:82 IDF/Form/WikiResourceUpdate.php:66 +msgid "Comment" +msgstr "" + +#: IDF/Form/IssueUpdate.php:316 +msgid "No changes were entered." +msgstr "" + +#: IDF/Form/MembersConf.php:104 +#, php-format +msgid "The following login is invalid: %s." +msgid_plural "The following logins are invalid: %s." +msgstr[0] "" +msgstr[1] "" + +#: IDF/Form/Password.php:34 +msgid "Your login or email" +msgstr "" + +#: IDF/Form/Password.php:35 +msgid "Provide either your login or your email to recover your password." +msgstr "" + +#: IDF/Form/Password.php:49 IDF/Form/Password.php:64 +msgid "" +"Sorry, we cannot find a user with this email address or login. Feel free to " +"try again." +msgstr "" + +#: IDF/Form/Password.php:100 +msgid "Password Recovery - InDefero" +msgstr "" + +#: IDF/Form/PasswordInputKey.php:36 IDF/Form/PasswordReset.php:39 +#: IDF/Form/UserChangeEmail.php:36 +msgid "Your verification key" +msgstr "" + +#: IDF/Form/PasswordInputKey.php:50 IDF/Form/PasswordReset.php:89 +msgid "" +"We are sorry but this validation key is not valid. Maybe you should directly " +"copy/paste it from your validation email." +msgstr "" + +#: IDF/Form/PasswordInputKey.php:61 IDF/Form/PasswordReset.php:100 +msgid "" +"Sorry, but this verification key has expired, please restart the password " +"recovery sequence. For security reasons, the verification key is only valid " +"24h." +msgstr "" + +#: IDF/Form/PasswordInputKey.php:76 IDF/Form/PasswordReset.php:108 +#: IDF/Form/RegisterConfirmation.php:137 IDF/Form/RegisterInputKey.php:72 +msgid "Cannot save an invalid form." +msgstr "" + +#: IDF/Form/PasswordReset.php:45 IDF/Form/RegisterConfirmation.php:69 +#: IDF/Form/UserAccount.php:77 +msgid "Your password" +msgstr "" + +#: IDF/Form/PasswordReset.php:48 IDF/Form/UserAccount.php:80 +msgid "" +"Your password must be hard for other people to find it, but easy for you to " +"remember." +msgstr "" + +#: IDF/Form/PasswordReset.php:56 IDF/Form/RegisterConfirmation.php:80 +#: IDF/Form/UserAccount.php:89 +msgid "Confirm your password" +msgstr "" + +#: IDF/Form/PasswordReset.php:74 IDF/Form/RegisterConfirmation.php:122 +msgid "The two passwords must be the same." +msgstr "" + +#: IDF/Form/PasswordReset.php:77 +msgid "" +"This account is not active. Please contact the forge administrator to " +"activate it." +msgstr "" + +#: IDF/Form/ProjectConf.php:43 +msgid "Short Description" +msgstr "" + +#: IDF/Form/ProjectConf.php:85 +msgid "The \"upload_path\" configuration variable was not set." +msgstr "" + +#: IDF/Form/ProjectConf.php:90 +msgid "Update the logo" +msgstr "" + +#: IDF/Form/ProjectConf.php:92 +msgid "The logo must be a picture with a size of 32 by 32." +msgstr "" + +#: IDF/Form/ProjectConf.php:103 +msgid "Remove the current logo" +msgstr "" + +#: IDF/Form/ProjectConf.php:139 +msgid "Could not determine the size of the uploaded picture." +msgstr "" + +#: IDF/Form/ProjectConf.php:143 +msgid "The picture must have a size of 32 by 32." +msgstr "" + +#: IDF/Form/ProjectConf.php:164 +msgid "The entered URL is invalid. Only http and https URLs are allowed." +msgstr "" + +#: IDF/Form/Register.php:41 +msgid "Your login" +msgstr "" + +#: IDF/Form/Register.php:45 +msgid "" +"The login must be between 3 and 15 characters long and contain only letters " +"and digits." +msgstr "" + +#: IDF/Form/Register.php:53 IDF/Form/UserAccount.php:59 +msgid "Your email" +msgstr "" + +#: IDF/Form/Register.php:55 +msgid "We will never send you any unsolicited emails. We hate spam too!" +msgstr "" + +#: IDF/Form/Register.php:60 +msgid "I agree to the terms and conditions." +msgstr "" + +#: IDF/Form/Register.php:88 +msgid "" +"We know, this is boring, but you need to agree with the terms and conditions." +msgstr "" + +#: IDF/Form/Register.php:97 +#, php-format +msgid "" +"The email \"%1$s\" is already used. If you need to, you can recover your password." +msgstr "" + +#: IDF/Form/Register.php:148 +msgid "Confirm the creation of your account." +msgstr "" + +#: IDF/Form/RegisterConfirmation.php:40 IDF/Form/RegisterInputKey.php:36 +msgid "Your confirmation key" +msgstr "" + +#: IDF/Form/RegisterConfirmation.php:72 +msgid "" +"Your password must be hard for other people to guess, but easy for you to " +"remember." +msgstr "" + +#: IDF/Form/RegisterConfirmation.php:99 IDF/Form/RegisterInputKey.php:50 +msgid "" +"We are sorry but this confirmation key is not valid. Maybe you should " +"directly copy/paste it from your confirmation email." +msgstr "" + +#: IDF/Form/RegisterConfirmation.php:110 +#, php-format +msgid "" +"This account has already been confirmed. Maybe should you try to recover your password." +msgstr "" + +#: IDF/Form/ReviewCreate.php:74 +#: IDF/gettexttemplates/idf/source/base.html.php:5 +#: IDF/gettexttemplates/idf/source/changelog.html.php:7 +msgid "Commit" +msgstr "" + +#: IDF/Form/ReviewCreate.php:92 +msgid "Patch" +msgstr "" + +#: IDF/Form/ReviewCreate.php:119 +msgid "We were not able to parse your patch. Please provide a valid patch." +msgstr "" + +#: IDF/Form/ReviewCreate.php:128 +msgid "You provided an invalid commit." +msgstr "" + +#: IDF/Form/ReviewCreate.php:202 +msgid "Initial patch to be reviewed." +msgstr "" + +#: IDF/Form/ReviewFileComment.php:56 +msgid "General comment" +msgstr "" + +#: IDF/Form/ReviewFileComment.php:113 +msgid "" +"You need to provide your general comment about the proposal, or comments on " +"at least one file." +msgstr "" + +#: IDF/Form/ReviewFileComment.php:124 +msgid "The status have been updated." +msgstr "" + +#: IDF/Form/ReviewFileComment.php:130 +msgid "This field is required." +msgstr "" + +#: IDF/Form/SourceConf.php:54 IDF/Form/UploadConf.php:70 +msgid "Webhook URL" +msgstr "" + +#: IDF/Form/TabsConf.php:38 IDF/gettexttemplates/idf/admin/base.html.php:4 +#: IDF/gettexttemplates/idf/base-full.html.php:8 +#: IDF/gettexttemplates/idf/base-full.html~.php:7 +#: IDF/gettexttemplates/idf/base.html.php:8 +#: IDF/gettexttemplates/idf/base.html~.php:7 +#: IDF/gettexttemplates/idf/downloads/base.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:14 +#: IDF/Views/Project.php:97 +msgid "Downloads" +msgstr "" + +#: IDF/Form/TabsConf.php:39 IDF/gettexttemplates/idf/base-full.html.php:12 +#: IDF/gettexttemplates/idf/base-full.html~.php:11 +#: IDF/gettexttemplates/idf/base.html.php:12 +#: IDF/gettexttemplates/idf/base.html~.php:11 +msgid "Code Review" +msgstr "" + +#: IDF/Form/TabsConf.php:40 IDF/gettexttemplates/idf/admin/base.html.php:5 +#: IDF/gettexttemplates/idf/base-full.html.php:9 +#: IDF/gettexttemplates/idf/base-full.html~.php:8 +#: IDF/gettexttemplates/idf/base.html.php:9 +#: IDF/gettexttemplates/idf/base.html~.php:8 +msgid "Documentation" +msgstr "" + +#: IDF/Form/TabsConf.php:41 IDF/gettexttemplates/idf/admin/base.html.php:7 +#: IDF/gettexttemplates/idf/base-full.html.php:11 +#: IDF/gettexttemplates/idf/base-full.html~.php:10 +#: IDF/gettexttemplates/idf/base.html.php:11 +#: IDF/gettexttemplates/idf/base.html~.php:10 +msgid "Source" +msgstr "" + +#: IDF/Form/TabsConf.php:42 IDF/gettexttemplates/idf/base-full.html.php:10 +#: IDF/gettexttemplates/idf/base-full.html~.php:9 +#: IDF/gettexttemplates/idf/base.html.php:10 +#: IDF/gettexttemplates/idf/base.html~.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:17 +msgid "Issues" +msgstr "" + +#: IDF/Form/TabsConf.php:50 +msgid "Open to all" +msgstr "" + +#: IDF/Form/TabsConf.php:51 +msgid "Signed in users" +msgstr "" + +#: IDF/Form/TabsConf.php:54 +msgid "Closed" +msgstr "" + +#: IDF/Form/TabsConf.php:84 +msgid "Others" +msgstr "" + +#: IDF/Form/TabsConf.php:107 +msgid "Extra authorized users" +msgstr "" + +#: IDF/Form/Upload.php:59 IDF/Form/WikiResourceCreate.php:65 +#: IDF/Form/WikiResourceUpdate.php:56 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:7 +#: IDF/Views/Download.php:64 IDF/Views/Download.php:346 +msgid "File" +msgstr "" + +#: IDF/Form/Upload.php:87 IDF/Form/WikiResourceCreate.php:96 +#: IDF/Form/WikiResourceUpdate.php:83 +msgid "For security reasons, you cannot upload a file with this extension." +msgstr "" + +#: IDF/Form/Upload.php:120 +#, php-format +msgid "You cannot provide more than one label from the %s class to a download." +msgstr "" + +#: IDF/Form/UploadArchive.php:41 +msgid "Archive file" +msgstr "" + +#: IDF/Form/UploadArchive.php:67 +#, php-format +msgid "" +"For security reasons, you cannot upload a file (%s) with this extension." +msgstr "" + +#: IDF/Form/UploadArchive.php:98 +#, php-format +msgid "" +"You cannot provide more than label from the %1$s class to a download (%2$s)." +msgstr "" + +#: IDF/Form/UploadArchive.php:109 +#, php-format +msgid "" +"A file with the name \"%s\" has already been uploaded and is not marked to " +"be replaced." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:41 +msgid "The archive does not exist." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:48 +#, php-format +msgid "The archive could not be read (code %d)." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:53 +msgid "The archive does not contain a manifest.xml." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:61 +#, php-format +msgid "The archive's manifest is invalid: %s" +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:77 +#, php-format +msgid "The entry %d in the manifest is missing a file name." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:82 +#, php-format +msgid "The entry %d in the manifest is missing a summary." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:86 +msgid "The manifest must not reference itself." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:91 +#, php-format +msgid "The entry %s in the manifest does not exist in the archive." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:96 +#, php-format +msgid "The entry %s in the manifest is referenced more than once." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:108 +#, php-format +msgid "The entry %s in the manifest has more than the six allowed labels set." +msgstr "" + +#: IDF/Form/UploadConf.php:53 +msgid "Predefined download labels" +msgstr "" + +#: IDF/Form/UploadConf.php:62 +msgid "Each download may have at most one label with each of these classes" +msgstr "" + +#: IDF/Form/UserAccount.php:61 +msgid "" +"If you change your email address, an email will be sent to the new address " +"to confirm it." +msgstr "" + +#: IDF/Form/UserAccount.php:80 +msgid "Leave blank if you do not want to change your password." +msgstr "" + +#: IDF/Form/UserAccount.php:166 +msgid "" +"Paste an SSH or monotone public key. Be careful to not provide your private " +"key here!" +msgstr "" + +#: IDF/Form/UserAccount.php:171 +msgid "Add a secondary email address" +msgstr "" + +#: IDF/Form/UserAccount.php:173 +msgid "You will get an email to confirm that you own the address you specify." +msgstr "" + +#: IDF/Form/UserAccount.php:200 +msgid "Confirm your new email address." +msgstr "" + +#: IDF/Form/UserAccount.php:203 +#, php-format +msgid "" +"A validation email has been sent to \"%s\" to validate the email address " +"change." +msgstr "" + +#: IDF/Form/UserAccount.php:341 +msgid "" +"Please check the key as it does not appear to be a valid SSH public key." +msgstr "" + +#: IDF/Form/UserAccount.php:363 +msgid "" +"Please check the key as it does not appear to be a valid monotone public key." +msgstr "" + +#: IDF/Form/UserAccount.php:371 +msgid "Public key looks like neither an SSH nor monotone public key." +msgstr "" + +#: IDF/Form/UserAccount.php:383 +msgid "You already have uploaded this key." +msgstr "" + +#: IDF/Form/UserChangeEmail.php:63 +msgid "" +"The validation key is not valid. Please copy/paste it from your confirmation " +"email." +msgstr "" + +#: IDF/Form/WikiConf.php:49 +msgid "Predefined documentation page labels" +msgstr "" + +#: IDF/Form/WikiConf.php:58 +msgid "" +"Each documentation page may have at most one label with each of these classes" +msgstr "" + +#: IDF/Form/WikiPageCreate.php:38 +msgid "" +"# Introduction\n" +"\n" +"Add your content here.\n" +"\n" +"\n" +"# Details\n" +"\n" +"Add your content here. Format your content with:\n" +"\n" +"* Text in **bold** or *italic*.\n" +"* Headings, paragraphs, and lists.\n" +"* Links to other [[WikiPage]].\n" +msgstr "" + +#: IDF/Form/WikiPageCreate.php:57 +msgid "PageName" +msgstr "" + +#: IDF/Form/WikiPageCreate.php:60 IDF/Form/WikiPageUpdate.php:50 +msgid "Page title" +msgstr "" + +#: IDF/Form/WikiPageCreate.php:66 IDF/Form/WikiPageUpdate.php:56 +msgid "" +"The page name must contains only letters, digits and the dash (-) character." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:71 IDF/Form/WikiPageUpdate.php:61 +msgid "This one line description is displayed in the list of pages." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:108 IDF/Form/WikiPageUpdate.php:119 +#: IDF/Form/WikiResourceCreate.php:78 +msgid "The title contains invalid characters." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:114 IDF/Form/WikiPageUpdate.php:125 +msgid "A page with this title already exists." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:150 IDF/Form/WikiPageUpdate.php:161 +#, php-format +msgid "You cannot provide more than one label from the %s class to a page." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:200 +msgid "Initial page creation" +msgstr "" + +#: IDF/Form/WikiPageDelete.php:39 +msgid "Yes, I understand that the page and all its revisions will be deleted." +msgstr "" + +#: IDF/Form/WikiPageDelete.php:50 IDF/Form/WikiResourceDelete.php:50 +msgid "You need to confirm the deletion." +msgstr "" + +#: IDF/Form/WikiPageUpdate.php:83 IDF/Form/WikiResourceUpdate.php:67 +msgid "One line to describe the changes you made." +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:40 +msgid "ResourceName" +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:44 +msgid "Resource title" +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:50 +msgid "" +"The resource name must contains only letters, digits and the dash (-) " +"character." +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:55 IDF/Form/WikiResourceUpdate.php:47 +msgid "This one line description is displayed in the list of resources." +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:84 +msgid "A resource with this title already exists." +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:142 +msgid "Initial resource creation" +msgstr "" + +#: IDF/Form/WikiResourceDelete.php:39 +msgid "" +"Yes, I understand that the resource and all its revisions will be deleted." +msgstr "" + +#: IDF/Form/WikiResourceUpdate.php:89 +#, php-format +msgid "" +"The mime type of the uploaded file \"%1$s\" does not match the mime type of " +"this resource \"%2$s\"" +msgstr "" + +#: IDF/Form/WikiResourceUpdate.php:97 +msgid "The current version of the resource and the uploaded file are equal." +msgstr "" + +#: IDF/Gconf.php:60 IDF/Search/Occ.php:56 +msgid "model class" +msgstr "" + +#: IDF/Gconf.php:66 IDF/Search/Occ.php:62 +msgid "model id" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/base.html.php:3 +msgid "Project Summary" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/base.html.php:6 +msgid "Issue Tracking" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/base.html.php:8 +msgid "Project Members" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/base.html.php:9 +msgid "Tabs Access and Notifications" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:3 +#: IDF/gettexttemplates/idf/admin/issue-tracking.html.php:3 +#: IDF/gettexttemplates/idf/admin/wiki.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/labels.html.php:3 +msgid "" +"\n" +"

Instructions:

\n" +"

List one status value per line in desired sort-order.

\n" +"

Optionally, use an equals-sign to document the meaning of each status " +"value.

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:8 +msgid "" +"

The webhook URL setting specifies an URL to which a HTTP PUT\n" +"request is sent after a new download has been added or to which a HTTP " +"POST\n" +"request is sent after an existing download has been updated.\n" +"If this field is empty, notifications are disabled.

\n" +"\n" +"

Only properly-escaped HTTP URLs are supported, for " +"example:

\n" +"\n" +"
    \n" +"
  • http://domain.com/upload
  • \n" +"
  • http://domain.com/upload?my%20param
  • \n" +"
\n" +"\n" +"

In addition, the URL may contain the following \"%\" notation, which\n" +"will be replaced with specific project values for each download:

\n" +"\n" +"
    \n" +"
  • %p - project name
  • \n" +"
  • %d - download id
  • \n" +"
\n" +"\n" +"

For example, updating download 123 of project 'my-project' with\n" +"web hook URL http://mydomain.com/%p/%d would send a POST " +"request to\n" +"http://mydomain.com/my-project/123.

" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:31 +#: IDF/gettexttemplates/idf/admin/source.html.php:30 +msgid "Web-Hook authentication key:" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:32 +#: IDF/gettexttemplates/idf/admin/issue-tracking.html.php:8 +#: IDF/gettexttemplates/idf/admin/members.html.php:13 +#: IDF/gettexttemplates/idf/admin/source.html.php:31 +#: IDF/gettexttemplates/idf/admin/summary.html.php:11 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:12 +#: IDF/gettexttemplates/idf/admin/wiki.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/forge/index.html.php:13 +#: IDF/gettexttemplates/idf/gadmin/projects/labels.html.php:8 +msgid "Save Changes" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/members.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:3 +msgid "" +"\n" +"

Instructions:

\n" +"

Specify each person by its login. Each person must have already " +"registered with the given login.

\n" +"

Separate the logins with commas and/or new lines.

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/members.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:8 +msgid "" +"\n" +"

Notes:

\n" +"

A project owner may make any change to this project, including removing " +"other project owners. You need to be carefull when you give owner rights.\n" +"

A project member will not have access to the administration area but will " +"have more options available in the use of the project.

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:3 +msgid "You can find here the current repository configuration of your project." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:4 +msgid "" +"

The webhook URL setting specifies an URL to which a HTTP \n" +"%%hook_request_method%% request is sent after each " +"repository\n" +"commit. If this field is empty, notifications are disabled.

\n" +"\n" +"

Only properly-escaped HTTP URLs are supported, for " +"example:

\n" +"\n" +"
    \n" +"
  • http://domain.com/commit
  • \n" +"
  • http://domain.com/commit?my%20param
  • \n" +"
\n" +"\n" +"

In addition, the URL may contain the following \"%\" notation, which\n" +"will be replaced with specific project values for each commit:

\n" +"\n" +"
    \n" +"
  • %p - project name
  • \n" +"
  • %r - revision number
  • \n" +"
\n" +"\n" +"

For example, committing revision 123 to project 'my-project' with\n" +"post-commit URL http://mydomain.com/%p/%r would send a request " +"to\n" +"http://mydomain.com/my-project/123.

" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:26 +msgid "" +"The form contains some errors. Please correct them to update the source " +"configuration." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:27 +msgid "Repository type:" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:28 +msgid "Repository access:" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:29 +msgid "Repository size:" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

The description of the project can be improved using the Markdown syntax.

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:7 +msgid "" +"The form contains some errors. Please correct them to update the summary." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:8 +msgid "Current logo" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:9 +#: IDF/gettexttemplates/idf/base-full.html.php:4 +#: IDF/gettexttemplates/idf/base-full.html~.php:4 +#: IDF/gettexttemplates/idf/base.html.php:4 +#: IDF/gettexttemplates/idf/base.html~.php:4 +#: IDF/gettexttemplates/idf/main-menu.html.php:8 +#: IDF/gettexttemplates/idf/project-list.html.php:4 +msgid "Project logo" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:10 +msgid "Your project does not have a logo configured yet." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:3 +msgid "" +"This section allows you to configure project tabs access rights and " +"notifications." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:4 +msgid "" +"Tab access controls whether a single user can navigate into a particular " +"section of your project via the main menu or automatically generated object " +"links." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:5 +msgid "" +"If you mark a project as private, only the project members and " +"administrators, together with the extra authorized users you provide will " +"have access to the project as a whole. You will still be able to define " +"further access rights for the different tabs but the \"Open to all\" and " +"\"Signed in users\" will default to authorized users only." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:6 +msgid "" +"For the extra authorized user list, specify each person by its login. Each " +"person must have already registered with the given login. Separate the " +"logins with commas and/or new lines." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:7 +msgid "" +"Only project members and admins have write access to the source. If you " +"restrict the access to the source, anonymous access is not provided and the " +"users must authenticate themselves with their password or SSH key." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:8 +#, php-format +msgid "" +"Here you can configure who should be notified about changes in a particular " +"section. You can also configure additional addresses, like the one of a " +"mailing list, that should be notified. (Keep in mind that you might have to " +"register the sender address %%from_email%% to let the " +"mailing list actually accept notification emails.) Multiple email addresses " +"must be separated through commas (',')." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:9 +msgid "" +"The form contains some errors. Please correct them to update the access " +"rights." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:10 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:13 +msgid "Access Rights" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:11 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:14 +msgid "Notifications" +msgstr "" + +#: IDF/gettexttemplates/idf/base-full.html.php:3 +#: IDF/gettexttemplates/idf/base-full.html~.php:3 +#: IDF/gettexttemplates/idf/base.html.php:3 +#: IDF/gettexttemplates/idf/base.html~.php:3 +#, php-format +msgid "" +"Sign in or create your account to create issues or " +"add comments" +msgstr "" + +#: IDF/gettexttemplates/idf/base-full.html.php:6 +#: IDF/gettexttemplates/idf/base.html.php:6 +#: IDF/gettexttemplates/idf/project-list.html.php:6 +msgid "External link to project" +msgstr "" + +#: IDF/gettexttemplates/idf/base-full.html.php:7 +#: IDF/gettexttemplates/idf/base-full.html~.php:6 +#: IDF/gettexttemplates/idf/base.html.php:7 +#: IDF/gettexttemplates/idf/base.html~.php:6 +msgid "Project Home" +msgstr "" + +#: IDF/gettexttemplates/idf/base-full.html.php:13 +#: IDF/gettexttemplates/idf/base-full.html~.php:12 +#: IDF/gettexttemplates/idf/base.html.php:13 +#: IDF/gettexttemplates/idf/base.html~.php:12 +msgid "Project Management" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/base.html.php:4 +#: IDF/gettexttemplates/idf/downloads/index.html.php:4 +#: IDF/Views/Download.php:235 +msgid "New Download" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/base.html.php:5 +msgid "Upload Archive" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:3 +msgid "" +"Each file must have a distinct name and file contents\n" +"cannot be changed, so be sure to include release numbers in each file\n" +"name." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:6 +#, php-format +msgid "" +"You can use the Markdown syntax for the description." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:7 +msgid "The form contains some errors. Please correct them to submit the file." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:8 +msgid "Submit File" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:9 +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:8 +#: IDF/gettexttemplates/idf/downloads/delete.html.php:7 +#: IDF/gettexttemplates/idf/downloads/view.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:21 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:14 +#: IDF/gettexttemplates/idf/issues/create.html.php:14 +#: IDF/gettexttemplates/idf/issues/view.html.php:27 +#: IDF/gettexttemplates/idf/register/confirmation.html.php:7 +#: IDF/gettexttemplates/idf/register/index.html.php:8 +#: IDF/gettexttemplates/idf/register/inputkey.html.php:5 +#: IDF/gettexttemplates/idf/review/create.html.php:12 +#: IDF/gettexttemplates/idf/review/view.html.php:41 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:5 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:13 +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:7 +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:9 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:5 +msgid "Cancel" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:10 +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:9 +#: IDF/gettexttemplates/idf/register/inputkey.html.php:6 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:6 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:6 +msgid "Instructions" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:3 +msgid "" +"The archive must include a manifest.xml file with meta " +"information about the\n" +"files to process inside the archive. All processed files must be unique or " +"replace existing files explicitely." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:5 +#, php-format +msgid "" +"You can learn more about the archive format here." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:6 +msgid "" +"The form contains some errors. Please correct them to submit the archive." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:7 +msgid "Submit Archive" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:3 +msgid "" +"Attention! If you want to delete a specific version of your " +"software, maybe, someone is depending on this specific version to run his " +"systems. Are you sure, you will not affect anybody when removing this file?" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:4 +#, php-format +msgid "" +"Instead of deleting the file, you could mark it as " +"deprecated." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:5 +#: IDF/gettexttemplates/idf/downloads/view.html.php:4 +#: IDF/gettexttemplates/idf/issues/attachment.html.php:4 +#: IDF/gettexttemplates/idf/issues/view.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:5 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:7 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:7 +#, php-format +msgid "by %%submitter%%" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:6 +msgid "Delete File" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:8 +#: IDF/gettexttemplates/idf/downloads/view.html.php:14 +msgid "Uploaded:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:9 +#: IDF/gettexttemplates/idf/downloads/view.html.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:29 +#: IDF/gettexttemplates/idf/review/view.html.php:27 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:12 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:14 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:14 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:15 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:17 +msgid "Updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:10 +#: IDF/gettexttemplates/idf/downloads/view.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:6 +#: IDF/gettexttemplates/idf/listProjects.html.php:17 +msgid "Downloads:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:11 +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:7 +#: IDF/gettexttemplates/idf/downloads/view.html.php:17 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:6 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:6 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:11 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:16 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:10 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:21 +#: IDF/gettexttemplates/idf/issues/view.html.php:33 +#: IDF/gettexttemplates/idf/project-list.html.php:8 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:6 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:13 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:16 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:12 +#: IDF/IssueComment.php:157 IDF/Wiki/PageRevision.php:204 +msgid "Labels:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:3 +msgid "A new file is available for download:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:4 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:6 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:5 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:8 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:4 +msgid "Hello," +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:6 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:5 +msgid "Project:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:6 +msgid "Submitted by:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:8 +msgid "Download:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/view.html.php:31 +#: IDF/gettexttemplates/idf/user/public.html.php:4 +msgid "Description:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:3 +msgid "A file download was updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/feedfragment.xml.php:3 +msgid "Details" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/index.html.php:3 +#, php-format +msgid "See the deprecated files." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/index.html.php:5 +msgid "Number of files:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:3 +msgid "" +"Attention! This file is marked as deprecated, download it " +"only if you are sure you need this specific version." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:5 +msgid "md5:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:6 +msgid "Changes" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:7 +msgid "The form contains some errors. Please correct them to update the file." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:8 +msgid "Update File" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:10 +#: IDF/gettexttemplates/idf/downloads/view.html.php:12 +msgid "Remove this file" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:11 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:18 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:7 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:12 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:12 +msgid "Trash" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:13 +msgid "Delete this file" +msgstr "" + +#: IDF/gettexttemplates/idf/faq-api.html.php:3 +#: IDF/gettexttemplates/idf/faq-archive-format.html.php:3 +#: IDF/gettexttemplates/idf/faq.html.php:65 +msgid "Here we are, just to help you." +msgstr "" + +#: IDF/gettexttemplates/idf/faq-api.html.php:4 +#: IDF/gettexttemplates/idf/faq-archive-format.html.php:4 +#: IDF/gettexttemplates/idf/faq.html.php:66 +#: IDF/gettexttemplates/idf/gadmin/base.html.php:4 +#: IDF/gettexttemplates/idf/index.html.php:4 IDF/Views/Admin.php:77 +#: IDF/Views.php:91 +msgid "Projects" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:3 +msgid "" +"

This is simple:

\n" +"
    \n" +"
  1. Write in the comments \"This is a duplicate of issue 123\" or - if you " +"are a member of the crew -\n" +"directly add the \"duplicates\" relation with the value \"123\" below the " +"comment field. Change \"123\"\n" +"with the corresponding issue number.
  2. \n" +"
  3. Change the status of the current issue to Duplicate.
  4. \n" +"
  5. Submit the changes.
  6. \n" +"
" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:11 +msgid "" +"You need to create an account on Gravatar, this takes about 5 minutes and is free." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:12 +msgid "" +"\n" +"

To embed any previously uploaded resource into your wiki page, you can " +"use the [[!ResourceName]] syntax.

\n" +"\n" +"

The rendering of the resource can then be further fine-tuned:\n" +"

    \n" +"
  • [[!ImageResource, align=right, width=200]] renders " +"\"ImageResource\" right-aligned and scale its width to 200
  • \n" +"
  • [[!TextResource, align=center, width=300, height=300]] " +"renders \"TextResource\" in a centered, 300 by 300 px iframe
  • \n" +"
  • [[!AnyResource, preview=no]] does not render a preview of " +"the resource, but only provides a download link (default for binary " +"resources)
  • \n" +"
  • [[!BinaryResource, title=Download]] renders the download " +"link of \"BinaryResource\" with an alternative title
  • \n" +"
\n" +"

\n" +"\n" +"Resources are versioned, just like wiki pages. If you update a resource, old " +"wiki pages still show the state of the resource\n" +"at the time when the wiki page was edited. If you specifically want to " +"update a resource on a page, you therefor need to update\n" +"the resource at first and then also the page where it is referenced, " +"otherwise the change won't be visible until the next regular edit. \n" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:28 +msgid "" +"

If you have to publish many files at once for a new release, it is a very " +"tedious task\n" +"to upload them one after another and enter meta information like a summary, " +"a description or additional\n" +"labels for each of them.

\n" +"

InDefero therefore supports a special archive format that is basically a " +"standard zip file which comes with\n" +"some meta information. These meta information are kept in a special manifest " +"file, which is distinctly kept from\n" +"the rest of the files in the archive that should be published.

\n" +"

Once this archive has been uploaded, InDefero reads in the meta " +"information, unpacks the other files from\n" +"the archive and creates new individual downloads for each of them.

" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:36 +#, php-format +msgid "Learn more about the archive format." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:37 +msgid "" +"The API (Application Programming Interface) is used to interact with " +"InDefero with another program. For example, this can be used to create a " +"desktop program to submit new tickets easily." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:38 +#, php-format +msgid "Learn more about the API." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:39 +#: IDF/gettexttemplates/idf/faq.html.php:45 +msgid "What are the keyboard shortcuts?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:40 +#: IDF/gettexttemplates/idf/faq.html.php:60 +msgid "How to mark an issue as duplicate?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:41 +#: IDF/gettexttemplates/idf/faq.html.php:61 +msgid "How can I display my head next to my comments?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:42 +#: IDF/gettexttemplates/idf/faq.html.php:62 +msgid "How can I embed images and other resources in my documentation pages?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:43 +#: IDF/gettexttemplates/idf/faq.html.php:63 +msgid "What is this \"Upload Archive\" functionality about?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:44 +#: IDF/gettexttemplates/idf/faq.html.php:64 +msgid "What is the API and how is it used?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:46 +msgid "Shift+h: This help page." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:47 +msgid "If you are in a project, you have the following shortcuts:" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:48 +msgid "Shift+u: Project updates." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:49 +msgid "Shift+d: Downloads." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:50 +msgid "Shift+o: Documentation." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:51 +msgid "Shift+a: Create a new issue." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:52 +msgid "Shift+i: List of open issues." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:53 +msgid "Shift+m: The issues you submitted." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:54 +msgid "Shift+w: The issues assigned to you." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:55 +msgid "Shift+s: Source." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:56 +msgid "You also have the standard access keys:" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:57 +msgid "Alt+1: Home." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:58 +msgid "Alt+2: Skip the menus." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:59 +msgid "Alt+4: Search (when available)." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:3 +msgid "Forge" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:5 +msgid "People" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:6 +msgid "Usher" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/forge/base.html.php:3 +msgid "Frontpage" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/forge/index.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

You can set up a custom forge page that is used as entry page for the " +"forge instead of the plain project listing. This page is then also " +"accessible via the 'Home' link in main menu bar.

\n" +"

The content of the page can use the Markdown syntax with the Extra extension.

\n" +"

Additionally, the following macros are available:
\n" +"

    \n" +"
  • {projectlist, label=..., order=(name|activity), limit=...} - Renders a project list that can optionally be filtered by label, " +"ordered by 'name' or 'activity' and / or limited to a specific number of " +"projects.
  • \n" +"
\n" +"

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:3 +#: IDF/gettexttemplates/idf/main-menu.html.php:7 +msgid "Project List" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:4 +#: IDF/Views/Admin.php:110 +msgid "Project Labels" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:16 +#: IDF/gettexttemplates/idf/listProjects.html.php:6 IDF/Views/Admin.php:186 +msgid "Create Project" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:6 +msgid "Change Project Details" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:3 +msgid "" +"You can select the type of repository you want. In the case of subversion, " +"you can use optionally a remote repository instead of the local one." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:4 +msgid "" +"Once you have defined the repository type, you cannot change it." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:5 +msgid "" +"\n" +"

Specify each person by its login. Each person must have already " +"registered with the given login.

\n" +"

Separate the logins with commas and/or new lines.

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:14 +msgid "" +"The form contains some errors. Please correct them to create the project." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:15 +msgid "Provide at least one owner for the project or use a template." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:15 +msgid "Instructions:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:3 +#, php-format +msgid "" +"Confirmation code to confirm the deletion of the project: \n" +"%%code%%." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:5 +msgid "" +"\n" +"Attention! Deleting a project is a one second operation\n" +"with the consequences that all the data related to the \n" +"project will be deleted.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:10 +msgid "" +"The form contains some errors. Please correct them to delete the project." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:11 +msgid "Project Statistics" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:12 +msgid "Tab" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:13 +msgid "Number" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:15 +msgid "Code reviews" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:16 +#: IDF/Views/Project.php:93 +msgid "Commits" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:18 +msgid "Documentation pages" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:19 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:20 +msgid "Delete Project" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:22 +msgid "" +"For large projects, the suppression can take a while, please be patient." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:3 +msgid "Space Usage Statistics" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:4 +msgid "Repositories:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:5 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:11 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:18 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:16 +msgid "Attachments:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:7 +msgid "Database:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:8 +msgid "Total Forge:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:13 +msgid "" +"The form contains some errors. Please correct them to update the project." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:14 +msgid "Provide at least one owner for the project." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:15 +msgid "Update Project" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:19 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:20 +msgid "Delete this project" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:21 +msgid "You will be asked to confirm." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:3 +#: IDF/Views/Admin.php:264 +msgid "User List" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:13 +msgid "Update User" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:4 +msgid "Create User" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:3 +msgid "The form contains some errors. Please correct them to create the user." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:6 +msgid "The user password will be sent by email to the user." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/createuser-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"An account on the forge has been created for you by\n" +"the administrator %%admin%%.\n" +"\n" +"Please find here your details to access the forge:\n" +"\n" +" Address: %%url%%\n" +" Login: %%user.login%%\n" +" Password: %%password%%\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:3 +#, php-format +msgid "See not validated users." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:4 +msgid "

You have here an overview of the users registered in the forge.

" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:5 +msgid "Number of users:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:3 +msgid "" +"If you are changing the email address of the user, you\n" +"need to ensure that you are providing a valid email\n" +"address" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:6 +msgid "" +"If you give the user staff rights, the user will be\n" +"able to create new projects and update other non staff users.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:9 +msgid "The form contains some errors. Please correct them to update the user." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:10 +#: IDF/gettexttemplates/idf/register/confirmation.html.php:4 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:4 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:4 +msgid "Login:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:11 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:5 +msgid "Public Profile" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:12 +msgid "Administrative" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/base.html.php:3 +msgid "Configured servers" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/base.html.php:4 +#: IDF/Views/Admin.php:421 +msgid "Usher control" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html~.php:3 +msgid "address" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html~.php:4 +msgid "port" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:5 +msgid "No connections found." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:3 +msgid "current server status:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:4 +msgid "startup" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:5 +msgid "shutdown" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:6 +msgid "reload server configuration:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:7 +msgid "reload" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:11 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:11 +msgid "Status explanation" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:9 +msgid "active with n total open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:10 +msgid "waiting for new connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:11 +msgid "usher is being shut down, not accepting connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:12 +msgid "" +"usher is shut down, all local servers are stopped and not accepting " +"connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:3 +msgid "server name" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:4 IDF/Issue.php:99 +#: IDF/Review.php:102 +msgid "status" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:5 +msgid "action" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:6 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:6 +msgid "No monotone servers configured." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:7 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:7 +msgid "stop" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:8 +msgid "start" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:9 +msgid "kill" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:10 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:10 +msgid "active connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:12 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:12 +msgid "remote server without open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:13 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:13 +msgid "server with n open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:14 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:14 +msgid "local server running, without open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:15 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:15 +msgid "local server not running, waiting for connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:16 +msgid "local server is about to stop, n connections still open" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:17 +msgid "local server not running, not accepting connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:18 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:18 +msgid "usher is shut down, not running and not accepting connections" +msgstr "" + +#: IDF/gettexttemplates/idf/index.atom.php:3 +#, php-format +msgid "Personal project feed for %%user%%." +msgstr "" + +#: IDF/gettexttemplates/idf/index.html.php:3 +#: IDF/gettexttemplates/idf/main-menu.html.php:6 +msgid "Home" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:3 +#, php-format +msgid "Attachment to issue %%issue.id%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:5 +#: IDF/gettexttemplates/idf/review/view.html.php:35 +#: IDF/gettexttemplates/idf/source/commit.html.php:23 +#: IDF/gettexttemplates/idf/source/commit.html~.php:22 +#: IDF/gettexttemplates/idf/source/git/file.html.php:6 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:7 +msgid "Archive" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:6 +#: IDF/gettexttemplates/idf/source/git/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:12 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:12 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:10 +msgid "Download this file" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:7 +#: IDF/gettexttemplates/idf/issues/view.html.php:28 +#: IDF/gettexttemplates/idf/review/view.html.php:26 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:13 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:14 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:16 +msgid "Created:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/base.html.php:4 +msgid "All Issues" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/base.html.php:5 +msgid "My Issues" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/base.html.php:6 +msgid "My watch list" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/base.html.php:7 +#: IDF/gettexttemplates/idf/issues/by-label.html.php:6 +#: IDF/gettexttemplates/idf/issues/index.html.php:5 +#: IDF/gettexttemplates/idf/issues/project-watchlist.html.php:5 +#: IDF/gettexttemplates/idf/issues/search.html.php:8 +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:5 +msgid "New Issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/base.html.php:8 +#: IDF/gettexttemplates/idf/wiki/base.html.php:9 +msgid "Search" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/base.html.php:9 +msgid "Back to the issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:3 +#, php-format +msgid "" +"

Open issues: %%open%%

\n" +"

Closed issues: %%closed%%

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:7 +msgid "Label:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:8 +msgid "Completion:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/create.html.php:3 +msgid "" +"

When you submit the issue do not forget to provide the following " +"information:

\n" +"
    \n" +"
  • The steps to reproduce the problem.
  • \n" +"
  • The version of the software and your operating system.
  • \n" +"
  • Any information that can help the developers to solve the issue.
  • \n" +"
  • Do not provide any password or confidential information!
  • \n" +"
" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/create.html.php:10 +msgid "The form contains some errors. Please correct them to submit the issue." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/create.html.php:11 +#: IDF/gettexttemplates/idf/issues/create.html.php:13 +#: IDF/gettexttemplates/idf/issues/view.html.php:24 +#: IDF/gettexttemplates/idf/issues/view.html.php:26 +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:5 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:5 +msgid "Preview" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/create.html.php:12 +msgid "Submit Issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/create.html.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:34 +msgid "Attach file" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/create.html.php:16 +#: IDF/gettexttemplates/idf/issues/create.html.php:17 +#: IDF/gettexttemplates/idf/issues/view.html.php:35 +#: IDF/gettexttemplates/idf/issues/view.html.php:36 +msgid "Attach another file" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:3 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:3 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:13 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:12 +#: IDF/gettexttemplates/idf/issues/view.html.php:18 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:3 +#: IDF/gettexttemplates/idf/review/view.html.php:38 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:11 +#: IDF/IssueComment.php:151 +msgid "Summary:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:4 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:4 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:8 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:14 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:13 +#: IDF/gettexttemplates/idf/issues/view.html.php:19 +#: IDF/gettexttemplates/idf/issues/view.html.php:30 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:4 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/view.html.php:39 IDF/IssueComment.php:153 +msgid "Status:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:5 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:15 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:14 +#: IDF/gettexttemplates/idf/issues/view.html.php:20 +#: IDF/gettexttemplates/idf/issues/view.html.php:31 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:5 +#: IDF/IssueComment.php:155 +msgid "Owner:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:17 +#: IDF/gettexttemplates/idf/issues/view.html.php:22 IDF/IssueComment.php:159 +msgid "Relations:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/forge-watchlist.html.php:3 +#: IDF/gettexttemplates/idf/issues/index.html.php:3 +#: IDF/gettexttemplates/idf/issues/project-watchlist.html.php:3 +#, php-format +msgid "" +"

Open issues: %%open%%

\n" +"

Closed issues: %%closed%%

" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:3 +msgid "A new issue has been created and assigned to you:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:4 +msgid "A new issue has been created:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:8 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:11 +msgid "Reported by:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:12 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:19 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:17 +msgid "Issue:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:3 +msgid "The following issue you are owning has been updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:4 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:3 +msgid "The following issue has been updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:4 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:4 +#, php-format +msgid "By %%who%%, %%c.creation_dtime%%:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:10 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:9 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:12 +msgid "URL:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:12 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:11 +msgid "Comments (last first):" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/search.html.php:3 +#, php-format +msgid "" +"\n" +"

Found open issues: %%open%%

\n" +"

Found closed issues: %%closed" +"%%

" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/search.html.php:6 +#, php-format +msgid "" +"

Label:\n" +"%%tag.class%%:" +"%%tag.name%%

" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:3 +msgid "View all open issues." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:4 +msgid "Create an issue." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:5 +#, php-format +msgid "" +"The issue tracker is empty.
Create your " +"first issue." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:6 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:4 +#, php-format +msgid "Unresolved: By %%key%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:7 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:5 +msgid "Status Summary" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:8 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:6 +msgid "Unresolved: By Assignee" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html~.php:3 +#, php-format +msgid "" +"The issue tracker is empty.
You can create your first issue here." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:3 +#, php-format +msgid "" +"See the %%nb_submit_closed%% closed." +msgid_plural "" +"See the %%nb_submit_closed%% closed." +msgstr[0] "" +msgstr[1] "" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:4 +#, php-format +msgid "" +"See the %%nb_owner_closed%% closed." +msgid_plural "" +"See the %%nb_owner_closed%% closed." +msgstr[0] "" +msgstr[1] "" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:6 +#: IDF/gettexttemplates/idf/user/dashboard.html.php:7 +msgid "Submitted issues:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:7 +#: IDF/gettexttemplates/idf/user/dashboard.html.php:6 +msgid "Working issues:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:3 +#, php-format +msgid "Reported by %%submitter%%, %%c.creation_dtime%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:4 +#: IDF/gettexttemplates/idf/review/view.html.php:22 +#, php-format +msgid "" +"Comment %%i%% by %%submitter%%, %%c.creation_dtime%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:5 +#, php-format +msgid "Sign in to reply to this comment." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:6 +msgid "" +"This issue is marked as closed, add a comment only if you think this issue " +"is still valid and more work is needed to fully fix it." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:8 +#, php-format +msgid "%%interested%% person" +msgid_plural "%%interested%% persons" +msgstr[0] "" +msgstr[1] "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:9 +#, php-format +msgid "This issue %%verb%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:10 +msgid "Remove this issue from your watch list" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:11 +msgid "Add this issue to your watch list" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:12 +msgid "View the previous closed issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:13 +msgid "View the previous open issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:14 +msgid "View the next closed issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:15 +msgid "View the next open issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:16 +msgid "download" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:17 +msgid "view" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:23 +msgid "The form contains some errors. Please correct them to change the issue." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:25 +msgid "Submit Changes" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:32 +msgid "Followed by:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:3 +#, php-format +msgid "1 project" +msgid_plural "%%label.project_count%% projects" +msgstr[0] "" +msgstr[1] "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:4 +#, php-format +msgid "Remove filter for %%tag%%" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:5 +msgid "No projects managed with InDefero were found." +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:7 +msgid "Filter projects by label" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:8 +msgid "No projects with labels found." +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:9 +msgid "Order" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:10 +msgid "By name" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:11 +msgid "By activity" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:12 +msgid "Filtered project stats" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:13 +msgid "Members:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:14 +msgid "Issues:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:15 +msgid "Commits:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:16 +msgid "Documentations:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:18 +msgid "Code reviews:" +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:3 +#, php-format +msgid "" +"You can create an account if you don't have one yet." +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:4 +msgid "What is your account information?" +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:5 +msgid "My login is" +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:6 +msgid "My password is" +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:7 +msgid "Sign in" +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:8 +msgid "I lost my password!" +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:9 +msgid "Welcome." +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:10 +msgid "It takes less than a minute to create your account." +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:3 +#, php-format +msgid "" +"Welcome, %%user%%." +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:4 +msgid "Sign Out" +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:5 +msgid "Sign in or create your account" +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:10 IDF/Views/Admin.php:40 +msgid "Forge Management" +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:11 +msgid "Help and accessibility features" +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:12 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:14 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:14 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:15 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:13 +msgid "Help" +msgstr "" + +#: IDF/gettexttemplates/idf/project/home.html.php:3 +#: IDF/gettexttemplates/idf/project/timeline.html.php:4 IDF/Views.php:46 +msgid "Welcome" +msgstr "" + +#: IDF/gettexttemplates/idf/project/home.html.php:4 +#: IDF/gettexttemplates/idf/project/timeline.html.php:5 +msgid "Latest Updates" +msgstr "" + +#: IDF/gettexttemplates/idf/project/home.html.php:5 +msgid "Featured Downloads" +msgstr "" + +#: IDF/gettexttemplates/idf/project/home.html.php:6 +msgid "Show more featured downloads" +msgstr "" + +#: IDF/gettexttemplates/idf/project/home.html.php:7 +#: IDF/gettexttemplates/idf/project/home.html.php:10 +msgid "show more..." +msgstr "" + +#: IDF/gettexttemplates/idf/project/home.html.php:8 +msgid "Featured Documentation" +msgstr "" + +#: IDF/gettexttemplates/idf/project/home.html.php:9 +msgid "Show more featured documentation" +msgstr "" + +#: IDF/gettexttemplates/idf/project/home.html.php:11 +msgid "Development Team" +msgstr "" + +#: IDF/gettexttemplates/idf/project/home.html.php:12 +msgid "Admins" +msgstr "" + +#: IDF/gettexttemplates/idf/project/home.html.php:13 +msgid "Happy Crew" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:3 +msgid "Latest updates" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:6 +#: IDF/Views/Project.php:90 +msgid "All Updates" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:7 +msgid "Filter by type" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:8 +msgid "Subscribe to this timeline" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:9 +msgid "RSS" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:10 +msgid "Atom feed" +msgstr "" + +#: IDF/gettexttemplates/idf/project-list.html.php:3 +msgid "Project activity: %%activity%%%" +msgstr "" + +#: IDF/gettexttemplates/idf/project-list.html.php:9 +msgid "n/a" +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation-email.txt.php:3 +#, php-format +msgid "" +"Hello,\n" +"\n" +"You have requested the creation of an account to\n" +"participate in the life of a software project.\n" +"\n" +"To confirm the account please follow this link:\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following confirmation key:\n" +"\n" +"%%key%%\n" +"\n" +"If you are not interested any longer in taking\n" +"part in the life of the software project or if\n" +"you can't remember having requested the creation\n" +"of an account, please excuse us and simply ignore\n" +"this email. \n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:3 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:3 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:3 +msgid "Oops, please check the form for errors." +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:5 +msgid "Email:" +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:6 +msgid "Enable Your Account" +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:8 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:8 +msgid "" +"This is the last step, but just be sure to have the cookies enabled to log in afterwards." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:3 +msgid "" +"Read the terms and conditions – " +"basically \"Please be nice, we respect you\"." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:4 +#, php-format +msgid "" +"If you have just forgotten your login information, then there is no need to " +"create a new account. You can just recover your login " +"name and password." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:5 +#, php-format +msgid "" +"With your account, you will able to participate in the life of all the " +"projects hosted here. Participating in a software project must be fun, so if " +"you have troubles, you can let us know about your issues " +"at anytime!" +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:6 +msgid "Oops, please check the provided login and email address to register." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:7 IDF/Views.php:137 +msgid "Create Your Account" +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:9 +msgid "" +"Be sure to provide a valid email address, as we are sending a validation " +"link by email." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:10 +msgid "Did you know?" +msgstr "" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:3 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:3 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:3 +msgid "Oops, we found an error in the form." +msgstr "" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:4 +msgid "Confirm Your Account" +msgstr "" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:7 +msgid "" +"Use your email software to read your emails and open your confirmation " +"email. Either click directly on the confirmation link or copy/paste the " +"confirmation key in the box and submit the form." +msgstr "" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:8 +msgid "" +"Just after providing the confirmation key, you will be able to set your " +"password and start using this website fully." +msgstr "" + +#: IDF/gettexttemplates/idf/review/base-full.html.php:3 +#: IDF/gettexttemplates/idf/review/base.html.php:3 +msgid "Open Reviews" +msgstr "" + +#: IDF/gettexttemplates/idf/review/base.html.php:4 +#: IDF/gettexttemplates/idf/review/create.html.php:11 +#: IDF/gettexttemplates/idf/review/index.html.php:3 IDF/Views/Review.php:83 +msgid "Start Code Review" +msgstr "" + +#: IDF/gettexttemplates/idf/review/create.html.php:3 +msgid "" +"

To start a code review, you need to provide:

\n" +"
    \n" +"
  • A commit or revision of the current code in the repository from which " +"you started your work.
  • \n" +"
  • A patch describing your changes with respect to the reference commit.\n" +"
  • Check your patch does not provide any password or confidential " +"information!
  • \n" +"
" +msgstr "" + +#: IDF/gettexttemplates/idf/review/create.html.php:9 +msgid "" +"The form contains some errors. Please correct them to submit the code review." +msgstr "" + +#: IDF/gettexttemplates/idf/review/create.html.php:10 +msgid "" +"Select the commit against which you created your patch to be sure it applies " +"correctly." +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:3 +msgid "The following review has been created:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:16 +msgid "Review:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:3 +msgid "The following review has been updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:5 +#, php-format +msgid "" +"By %%who%%, %%c.creation_dtime%%, on file:\n" +"%%c.cfile%%\n" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:14 +msgid "General comments (last first):" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:15 +msgid "Detailed file comments (last first):" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:3 +msgid "" +"Code review is a process in which\n" +"after or before changes are commited into the code repository,\n" +"different people discuss the code changes. The goal is\n" +"to improve the quality of the code and the\n" +"contributions, as such, you must be pragmatic when writing\n" +"your review. Correctly mention the line numbers (in the old or in the\n" +"new file) and try to keep a good balance between seriousness and fun.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:11 +msgid "" +"\n" +"Proposing code for review is intimidating, you know\n" +"you will receive critics, so please, as a reviewer, keep this\n" +"process fun, use it to help your contributor learn your\n" +"coding standards and the structure of the code and make them want\n" +"to propose more contributions.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:18 +#: IDF/gettexttemplates/idf/source/commit.html.php:3 +#: IDF/gettexttemplates/idf/source/commit.html~.php:3 +#, php-format +msgid "%%ndiff%% diff" +msgid_plural "%%ndiff%% diffs" +msgstr[0] "" +msgstr[1] "" + +#: IDF/gettexttemplates/idf/review/view.html.php:19 +#, php-format +msgid "%%nc%% comment" +msgid_plural "%%nc%% comments" +msgstr[0] "" +msgstr[1] "" + +#: IDF/gettexttemplates/idf/review/view.html.php:20 +#, php-format +msgid "" +"Comment %%i%% by %%who%%, " +"%%c.creation_dtime%%" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:21 +#, php-format +msgid "Your comments on the changes in file %%file%%:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:23 +#, php-format +msgid "Sign in to participate in the review." +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:24 +msgid "" +"The form contains some errors. Please correct them to submit your review." +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:25 +msgid "How to Participate in a Code Review" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:28 +#: IDF/gettexttemplates/idf/source/commit.html.php:5 +#: IDF/gettexttemplates/idf/source/commit.html~.php:5 +msgid "Author:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:29 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/source/commit.html.php:7 +#: IDF/gettexttemplates/idf/source/commit.html~.php:7 +msgid "Commit:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:30 +#: IDF/gettexttemplates/idf/source/commit.html.php:8 +#: IDF/gettexttemplates/idf/source/commit.html~.php:8 +msgid "View corresponding source tree" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:32 +msgid "Reviewers:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:33 +msgid "No reviewers at the moment." +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:34 +msgid "Files:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:36 +#: IDF/gettexttemplates/idf/source/commit.html.php:24 +#: IDF/gettexttemplates/idf/source/commit.html~.php:23 +msgid "Download the corresponding diff file" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:37 +msgid "General Comments" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:40 +msgid "Submit Code Review" +msgstr "" + +#: IDF/gettexttemplates/idf/source/base.html.php:3 +msgid "Source Tree" +msgstr "" + +#: IDF/gettexttemplates/idf/source/base.html.php:4 +msgid "Change Log" +msgstr "" + +#: IDF/gettexttemplates/idf/source/base.html.php:6 +msgid "How To Get The Code" +msgstr "" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:3 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:8 +#: IDF/Views/Project.php:190 +msgid "Age" +msgstr "" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:4 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:10 +msgid "Message" +msgstr "" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:5 +msgid "Parent:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:6 +#: IDF/gettexttemplates/idf/source/commit.html.php:10 +#: IDF/gettexttemplates/idf/source/commit.html~.php:10 +msgid "View corresponding commit" +msgstr "" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:8 +msgid "by" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:3 +msgid "A new commit has been created:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:8 +msgid "Created by:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:8 +msgid "Created at:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:8 +msgid "Content:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:10 +msgid "Commit details:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:4 +#: IDF/gettexttemplates/idf/source/commit.html~.php:4 +msgid "Date:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:6 +#: IDF/gettexttemplates/idf/source/commit.html~.php:6 +msgid "Branch:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:9 +#: IDF/gettexttemplates/idf/source/commit.html~.php:9 +msgid "Parents:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:11 +#: IDF/gettexttemplates/idf/source/commit.html~.php:11 +msgid "Message:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:12 +#: IDF/gettexttemplates/idf/source/commit.html~.php:12 +#: IDF/gettexttemplates/idf/wiki/feedfragment-page.xml.php:3 +#: IDF/gettexttemplates/idf/wiki/feedfragment-resource.xml.php:3 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:10 +msgid "Changes:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:13 +#: IDF/gettexttemplates/idf/source/commit.html~.php:13 +msgid "deleted" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:14 +#: IDF/gettexttemplates/idf/source/commit.html.php:18 +#: IDF/gettexttemplates/idf/source/commit.html~.php:14 +#: IDF/gettexttemplates/idf/source/commit.html~.php:17 +msgid "full" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:15 +#: IDF/gettexttemplates/idf/source/commit.html~.php:15 +msgid "renamed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:16 +msgid "copied" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:17 +#: IDF/gettexttemplates/idf/source/commit.html~.php:16 +msgid "added" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:19 +#: IDF/gettexttemplates/idf/source/commit.html~.php:18 +msgid "modified" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:20 +msgid "properties changed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:21 +#: IDF/gettexttemplates/idf/source/commit.html~.php:20 +msgid "removed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:22 +#: IDF/gettexttemplates/idf/source/commit.html~.php:21 +msgid "File differences" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html~.php:19 +msgid "properies changed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:3 +#, php-format +msgid "" +"The revision identifier %%commit%% is ambiguous and can be\n" +"expanded to multiple valid revisions - please choose one:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:5 +msgid "Title" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:6 +msgid "Author" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:7 +msgid "Date" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:8 +msgid "Branch" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:9 +msgid "Revision" +msgstr "" + +#: IDF/gettexttemplates/idf/source/feedfragment.xml.php:3 +#, php-format +msgid "%%cproject.name%%: Commit %%c.scm_id%%" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:3 +msgid "Branches" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:4 +msgid "filter branches" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:5 +msgid "Tags" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:6 +msgid "filter tags" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/file.html.php:3 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:4 +#, php-format +msgid "" +"Source at commit %%commit%% created " +"%%cobject.date%%." +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/file.html.php:4 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:5 +#, php-format +msgid "By %%cobject.author%%, %%cobject.title%%" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/file.html.php:5 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:6 +msgid "Root" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the git software to manage the source\n" +"code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:6 +#, php-format +msgid "" +"You may need to provide your SSH key. The " +"synchronization of your SSH key can take a couple of minutes. You can learn " +"more about SSH key authentication." +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:6 +msgid "To make a first commit in the repository, perform the following steps:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:8 +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:7 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:7 +#, php-format +msgid "Find here more details on how to access %%project%% source code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:9 +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:8 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:8 +msgid "Command-Line Access" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:10 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:9 +msgid "First Commit" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:11 +#: IDF/Views/Download.php:66 IDF/Views/Download.php:348 +msgid "Size" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:12 +msgid ":" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:13 +msgid "Download this version" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:13 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:13 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:14 +msgid "or" +msgstr "" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:3 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:3 +#, php-format +msgid "" +"The branch or revision %%commit%% is not valid or does not exist\n" +"in this repository." +msgstr "" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:5 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:5 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:5 +msgid "The following list shows all available branches:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:6 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:6 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:6 +#, php-format +msgid "" +"If this is a new repository, the reason for this error\n" +"could be that you have not committed and / or pushed any change so far.\n" +"In this case please take a look at the Help page\n" +"how to access your repository." +msgstr "" + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the Mercurial software to manage the source\n" +"code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:6 +#, php-format +msgid "" +"To get write access to the repository, you need to use your username and " +"your extra password." +msgstr "" + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:9 +msgid "Write Access Authentication" +msgstr "" + +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:3 +#, php-format +msgid "Property %%prop%% set to %%val%%" +msgstr "" + +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the monotone software to manage the source\n" +"code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/changelog.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/commit.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/commit.html~.php:3 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:14 +msgid "Revision:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/changelog.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/commit.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/commit.html~.php:4 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:10 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:15 +msgid "Switch" +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the subversion software to manage the source\n" +"code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:3 +#, php-format +msgid "" +"The revision %%commit%% is not valid or does not exist\n" +"in this repository." +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:9 +msgid "Rev" +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:16 +msgid "Branches:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:17 +msgid "Tags:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/changeemail-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"To confirm that you want %%email%%\n" +"to be your new email address, just follow this link:\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following verification key:\n" +"\n" +"%%key%%\n" +"\n" +"If you do not want to change your email address, \n" +"just ignore this message.\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/user/changeemail.html.php:4 +msgid "Confirm Your New Email Address" +msgstr "" + +#: IDF/gettexttemplates/idf/user/changeemail.html.php:7 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:7 +msgid "" +"Use your email software to read your emails and open your verification " +"email. Either click directly on the verification link or copy/paste the " +"verification key in the box and submit the form." +msgstr "" + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:3 +#, php-format +msgid "Update your account." +msgstr "" + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:4 +#, php-format +msgid "See your public profile." +msgstr "" + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:5 +#, php-format +msgid "See your forge issue watch list." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:6 +msgid "Key Management" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:7 +msgid "Secondary Emails" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:8 +msgid "Extra password" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:9 +msgid "" +"This password is used to access some of the external systems managed by our " +"infrastructure. It will be regenerated if you change your password." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:10 +msgid "API key" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:11 +msgid "" +"Your API key will be regenerated automatically if you change your password." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:12 +msgid "Update Your Account" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:14 +msgid "Your Current Public Keys" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:15 +msgid "Delete this key" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:16 +msgid "Your additional email addresses" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:17 +msgid "Delete this address" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:18 +msgid "" +"If possible, use your real name. By using your real name, people will have " +"more trust in your comments and remarks." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:19 +msgid "" +"The extra password is used to access some of the external systems and the " +"API key is used to interact with this website using a program." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:20 +msgid "Show API key and extra password" +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:3 +msgid "" +"Oops, please check the provided login or email address to recover your " +"password." +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:4 +msgid "Recover My Password" +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:6 +msgid "" +"Provide either your login or email address, if a corresponding user is found " +"in the database, we will send you an email with the details on how to reset " +"your password." +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"You lost your password and wanted to recover it.\n" +"To provide a new password for your account, you\n" +"just have to follow the provided link. You will\n" +"get a simple form to provide a new password.\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following verification key:\n" +"\n" +"%%key%%\n" +"\n" +"If you are not the one who requested to reset\n" +"your password, simply ignore this email, your\n" +"password will not be changed.\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:4 +msgid "Recover Your Password" +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:8 +msgid "" +"Just after providing the confirmation key, you will be able to reset your " +"password and use this website fully." +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:6 +msgid "Reset Your Password" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:3 +#, php-format +msgid "You are looking at the public profile of %%member%%." +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:5 +msgid "Twitter:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:6 +msgid "Public Email:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:7 +msgid "Website:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:8 +msgid "Last time seen:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:9 +msgid "Member since:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:3 +msgid "List Pages" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:4 +msgid "List Resources" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:5 +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:4 +#: IDF/gettexttemplates/idf/wiki/search.html.php:3 IDF/Views/Wiki.php:211 +msgid "New Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:6 +#: IDF/gettexttemplates/idf/wiki/listResources.html.php:3 +#: IDF/Views/Wiki.php:256 +msgid "New Resource" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:7 +msgid "Update This Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:8 +msgid "Update This Resource" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:3 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:3 +msgid "Preview of the Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:7 +msgid "The form contains some errors. Please correct them to create the page." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:6 +msgid "Create Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:3 +msgid "" +"\n" +"Wiki resources are later addressed in wiki pages by their title, so ensure " +"that you\n" +"give your resource a unique and an easy to remember name.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:8 +msgid "Create Resource" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:3 +msgid "" +"If you delete this documentation page, it will be removed from the database " +"with all the associated revisions and you will not be able to " +"recover it." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:6 +msgid "Delete Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:14 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:15 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:15 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:17 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:18 +msgid "Old Revisions" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:3 +#, php-format +msgid "" +"You are looking at an old revision (%%oldrev.summary%%) of the " +"page \n" +"%%page.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:5 +msgid "" +"If you delete this old revision, it will be removed from the database and " +"you will not be able to recover it." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:8 +msgid "Delete Revision" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:3 +msgid "" +"If you delete this documentation resource, it will be removed from the " +"database with all the associated revisions \n" +"and you will not be able to recover it. Any documentation " +"pages that reference this resource,\n" +"will no longer be able to render it, but won't be deleted." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:8 +msgid "Delete Resource" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:10 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:8 +msgid "File size" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:9 +#: IDF/Views/Wiki.php:101 +msgid "MIME type" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:3 +#, php-format +msgid "" +"You are looking at an old revision (%%oldrev.summary%%) of the " +"resource \n" +"%%resource.title%%. This revision was created by " +"%%submitter%%." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/edit-info.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

The content of the page can use the Markdown syntax with the Extra extension.

\n" +"

Website addresses are automatically linked and you can link to another " +"page in the documentation using double square brackets like that " +"[[AnotherPage]].

\n" +"

If you want to embed uploaded resources, use the [[!ResourceName]] syntax for that. This is described more in detail in the FAQ.

\n" +"

To directly include a file content from the repository, embrace its path " +"with triple square brackets: [[[my/file.txt]]].

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/feedfragment-resource.xml.php:4 +msgid "Initial creation" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:3 +#, php-format +msgid "See the deprecated pages." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:5 +msgid "Number of pages:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/listResources.html.php:4 +msgid "Number of resources:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/search.html.php:4 +msgid "Pages found:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:3 +msgid "The form contains some errors. Please correct them to update the page." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:6 +msgid "Update Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:10 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:11 +msgid "Delete this page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:4 +msgid "Update Resource" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:8 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:9 +msgid "Delete this resource" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:3 +msgid "" +"Attention! This page is marked as deprecated, \n" +"use it as reference only if you are sure you need these specific information." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:5 +#, php-format +msgid "" +"You are looking at an old revision of the page \n" +"%%page.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:10 +msgid "Table of Content" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:13 +msgid "Delete this revision" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:3 +#, php-format +msgid "" +"You are looking at an old revision of the resource \n" +"%%resource.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:14 +msgid "Page Usage" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:15 +msgid "This resource is not used on any pages yet." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:3 +msgid "A new documentation page has been created:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:14 +msgid "Documentation page:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:3 +msgid "The following documentation page has been updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:7 +msgid "Updated by:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:13 +msgid "New content:" +msgstr "" + +#: IDF/Issue.php:76 +msgid "owner" +msgstr "" + +#: IDF/Issue.php:84 IDF/Wiki/Page.php:86 +msgid "interested users" +msgstr "" + +#: IDF/Issue.php:85 +msgid "" +"Interested users will get an email notification when the issue is changed." +msgstr "" + +#: IDF/Issue.php:92 IDF/Project.php:94 IDF/Review.php:95 IDF/Upload.php:99 +#: IDF/Wiki/Page.php:94 +msgid "labels" +msgstr "" + +#: IDF/Issue.php:111 IDF/IssueFile.php:102 IDF/Review.php:114 +#: IDF/Upload.php:118 IDF/Wiki/Page.php:106 IDF/Wiki/Resource.php:101 +msgid "modification date" +msgstr "" + +#: IDF/Issue.php:212 IDF/IssueComment.php:143 +#, php-format +msgid "" +"Issue %3$d, %4$s" +msgstr "" + +#: IDF/Issue.php:214 +#, php-format +msgid "Creation of issue %3$d, by %4$s" +msgstr "" + +#: IDF/Issue.php:224 +#, php-format +msgid "%1$s: Issue %2$d created - %3$s" +msgstr "" + +#: IDF/Issue.php:307 +#, php-format +msgid "Issue %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Issue.php:311 +#, php-format +msgid "Updated Issue %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/IssueComment.php:51 IDF/IssueRelation.php:47 +msgid "issue" +msgstr "" + +#: IDF/IssueComment.php:58 IDF/IssueFile.php:49 IDF/Review/Comment.php:62 +#: IDF/Review/FileComment.php:49 IDF/Review/FileComment.php:69 +msgid "comment" +msgstr "" + +#: IDF/IssueComment.php:72 IDF/Review/Comment.php:75 IDF/Upload.php:63 +#: IDF/Wiki/PageRevision.php:85 +msgid "changes" +msgstr "" + +#: IDF/IssueComment.php:73 +msgid "Serialized array of the changes in the issue." +msgstr "" + +#: IDF/IssueComment.php:180 +#, php-format +msgid "Comment on issue %3$d, by %4$s" +msgstr "" + +#: IDF/IssueComment.php:191 +#, php-format +msgid "%1$s: Comment on issue %2$d - %3$s" +msgstr "" + +#: IDF/IssueFile.php:64 +msgid "file name" +msgstr "" + +#: IDF/IssueFile.php:70 +msgid "the file" +msgstr "" + +#: IDF/IssueFile.php:76 +msgid "file size" +msgstr "" + +#: IDF/IssueFile.php:84 +msgid "type" +msgstr "" + +#: IDF/IssueFile.php:86 +msgid "Image" +msgstr "" + +#: IDF/IssueFile.php:87 +msgid "Other" +msgstr "" + +#: IDF/IssueRelation.php:54 +msgid "verb" +msgstr "" + +#: IDF/IssueRelation.php:61 +msgid "other issue" +msgstr "" + +#: IDF/Key.php:55 +msgid "public key" +msgstr "" + +#: IDF/Key.php:90 +msgid "Invalid or unknown key data detected." +msgstr "" + +#: IDF/Plugin/SyncMercurial.php:78 IDF/Plugin/SyncSvn.php:81 +#, php-format +msgid "The repository %s already exists." +msgstr "" + +#: IDF/Plugin/SyncMercurial.php:142 +#, php-format +msgid "%s does not exist or is not writable." +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:107 IDF/Plugin/SyncMonotone.php:492 +msgid "\"mtn_repositories\" must be defined in your configuration file" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:114 IDF/Plugin/SyncMonotone.php:482 +msgid "\"mtn_usher_conf\" does not exist or is not writable" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:121 +#, php-format +msgid "Could not find mtn-post-push script \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:155 +#, php-format +msgid "The configuration file \"%s\" is missing" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:164 +#, php-format +msgid "The project path \"%s\" already exists" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:170 +#, php-format +msgid "The project path \"%s\" could not be created" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:208 +#, php-format +msgid "The key directory \"%s\" could not be created" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:227 +#, php-format +msgid "Could not parse key information: %s" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:265 +#, php-format +msgid "Could not create configuration directory \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:275 +#, php-format +msgid "Could not create symlink for configuration file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:293 +#, php-format +msgid "Could not write configuration file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:309 IDF/Plugin/SyncMonotone.php:525 +#, php-format +msgid "Could not parse usher configuration in \"%1$s\": %2$s" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:320 +#, php-format +msgid "usher configuration already contains a server entry named \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:345 IDF/Plugin/SyncMonotone.php:546 +#, php-format +msgid "Could not write usher configuration file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:395 +#, php-format +msgid "Could not write write-permissions file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:420 +#, php-format +msgid "Could not write read-permissions file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:438 +#, php-format +msgid "Could not remove symlink \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:446 +#, php-format +msgid "Could not create symlink \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:500 +#, php-format +msgid "One or more paths underneath %s could not be deleted" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:512 +#, php-format +msgid "Could not delete client private key \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:599 IDF/Plugin/SyncMonotone.php:718 +#, php-format +msgid "Could not parse read-permissions for project \"%1$s\": %2$s" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:643 IDF/Plugin/SyncMonotone.php:741 +#, php-format +msgid "Could not write read-permissions for project \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:657 IDF/Plugin/SyncMonotone.php:760 +#, php-format +msgid "Could not write write-permissions file for project \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:813 +msgid "\"mtn_repositories\" must be defined in your configuration file." +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:820 +#, php-format +msgid "The project path %s does not exists." +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:838 +#, php-format +msgid "The command \"%s\" could not be executed." +msgstr "" + +#: IDF/Project.php:62 IDF/Tag.php:66 +msgid "name" +msgstr "" + +#: IDF/Project.php:69 +msgid "short name" +msgstr "" + +#: IDF/Project.php:70 +msgid "" +"Used in the URL to access the project, must be short with only letters and " +"numbers." +msgstr "" + +#: IDF/Project.php:78 +msgid "short description" +msgstr "" + +#: IDF/Project.php:86 IDF/Review/Patch.php:74 +msgid "description" +msgstr "" + +#: IDF/Project.php:87 +msgid "The description can be extended using the Markdown syntax." +msgstr "" + +#: IDF/Project.php:100 +msgid "private" +msgstr "" + +#: IDF/Project.php:108 +msgid "current project activity" +msgstr "" + +#: IDF/Project.php:159 +#, php-format +msgid "Project \"%s\" not found." +msgstr "" + +#: IDF/ProjectActivity.php:56 +msgid "date" +msgstr "" + +#: IDF/Review/Comment.php:55 IDF/Review/Patch.php:80 +msgid "patch" +msgstr "" + +#: IDF/Review/Comment.php:83 +msgid "vote" +msgstr "" + +#: IDF/Review/Comment.php:139 IDF/Review/Patch.php:151 +#, php-format +msgid "" +"Review %3$d, %4$s" +msgstr "" + +#: IDF/Review/Comment.php:141 +#, php-format +msgid "Update of review %3$d, by %4$s" +msgstr "" + +#: IDF/Review/Comment.php:151 +#, php-format +msgid "%1$s: Updated review %2$d - %3$s" +msgstr "" + +#: IDF/Review/Comment.php:222 +#, php-format +msgid "Updated Code Review %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Review/Patch.php:52 +msgid "review" +msgstr "" + +#: IDF/Review/Patch.php:67 +msgid "commit" +msgstr "" + +#: IDF/Review/Patch.php:153 +#, php-format +msgid "Creation of review %3$d, by %4$s" +msgstr "" + +#: IDF/Review/Patch.php:163 +#, php-format +msgid "%1$s: Creation of Review %2$d - %3$s" +msgstr "" + +#: IDF/Review/Patch.php:208 +#, php-format +msgid "New Code Review %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Scm/Git.php:309 IDF/Scm/Mercurial.php:199 +#, php-format +msgid "Folder %1$s not found in commit %2$s." +msgstr "" + +#: IDF/Scm/Git.php:433 IDF/Scm/Mercurial.php:216 +#, php-format +msgid "Not a valid tree: %s." +msgstr "" + +#: IDF/Scm/Monotone/Stdio.php:81 +msgid "Monotone client key name or hash not in project conf." +msgstr "" + +#: IDF/Scm/Monotone/Stdio.php:89 +#, php-format +msgid "The key directory %s could not be created." +msgstr "" + +#: IDF/Scm/Monotone/Stdio.php:100 +#, php-format +msgid "Could not write client key \"%s\"" +msgstr "" + +#: IDF/Search/Occ.php:33 +msgid "occurrence" +msgstr "" + +#: IDF/Search/Occ.php:49 +msgid "word" +msgstr "" + +#: IDF/Search/Occ.php:75 +msgid "occurrences" +msgstr "" + +#: IDF/Search/Occ.php:81 +msgid "ponderated occurrence" +msgstr "" + +#: IDF/Tag.php:59 +msgid "tag class" +msgstr "" + +#: IDF/Tag.php:60 +msgid "The class of the tag." +msgstr "" + +#: IDF/Tag.php:73 +msgid "lcname" +msgstr "" + +#: IDF/Tag.php:74 +msgid "Lower case version of the name for fast searching." +msgstr "" + +#: IDF/Template/Markdown.php:84 +msgid "Create this documentation page" +msgstr "" + +#: IDF/Template/Markdown.php:97 +msgid "You are not allowed to access the wiki." +msgstr "" + +#: IDF/Template/Markdown.php:106 +msgid "The wiki resource has not been found." +msgstr "" + +#: IDF/Template/Markdown.php:113 +msgid "The wiki resource has not been found. Create it!" +msgstr "" + +#: IDF/Template/Markdown.php:146 +msgid "This revision of the resource is no longer available." +msgstr "" + +#: IDF/Template/ShowUser.php:51 +msgid "Anonymous" +msgstr "" + +#: IDF/Template/ShowUser.php:54 +msgid "Me" +msgstr "" + +#: IDF/Timeline/Paginator.php:49 +msgid "Today" +msgstr "" + +#: IDF/Upload.php:70 +msgid "file" +msgstr "" + +#: IDF/Upload.php:71 +msgid "The path is relative to the upload path." +msgstr "" + +#: IDF/Upload.php:78 IDF/Wiki/ResourceRevision.php:71 +msgid "file size in bytes" +msgstr "" + +#: IDF/Upload.php:84 +msgid "MD5" +msgstr "" + +#: IDF/Upload.php:106 +msgid "number of downloads" +msgstr "" + +#: IDF/Upload.php:201 +#, php-format +msgid "Download %2$d, %3$s" +msgstr "" + +#: IDF/Upload.php:204 +#, php-format +msgid "Addition of download %2$d, by %3$s" +msgstr "" + +#: IDF/Upload.php:214 +#, php-format +msgid "%1$s: Download %2$d added - %3$s" +msgstr "" + +#: IDF/Upload.php:301 +#, php-format +msgid "New download - %1$s (%2$s)" +msgstr "" + +#: IDF/Upload.php:305 +#, php-format +msgid "Updated download - %1$s (%2$s)" +msgstr "" + +#: IDF/Views/Admin.php:47 +msgid "The forge configuration has been saved." +msgstr "" + +#: IDF/Views/Admin.php:80 +msgid "This table shows the projects in the forge." +msgstr "" + +#: IDF/Views/Admin.php:85 +msgid "Short Name" +msgstr "" + +#: IDF/Views/Admin.php:87 +msgid "Repository Size" +msgstr "" + +#: IDF/Views/Admin.php:93 +msgid "No projects were found." +msgstr "" + +#: IDF/Views/Admin.php:116 +msgid "The label configuration has been saved." +msgstr "" + +#: IDF/Views/Admin.php:147 IDF/Views/Admin.php:314 IDF/Views/Wiki.php:484 +#: IDF/Views/Wiki.php:536 +#, php-format +msgid "Update %s" +msgstr "" + +#: IDF/Views/Admin.php:155 IDF/Views/Project.php:304 +msgid "The project has been updated." +msgstr "" + +#: IDF/Views/Admin.php:192 +msgid "The project has been created." +msgstr "" + +#: IDF/Views/Admin.php:223 +#, php-format +msgid "Delete %s Project" +msgstr "" + +#: IDF/Views/Admin.php:230 +msgid "The project has been deleted." +msgstr "" + +#: IDF/Views/Admin.php:260 +msgid "Not Validated User List" +msgstr "" + +#: IDF/Views/Admin.php:268 +msgid "This table shows the users in the forge." +msgstr "" + +#: IDF/Views/Admin.php:272 +msgid "login" +msgstr "" + +#: IDF/Views/Admin.php:275 +msgid "Admin" +msgstr "" + +#: IDF/Views/Admin.php:277 +msgid "Last Login" +msgstr "" + +#: IDF/Views/Admin.php:284 +msgid "No users were found." +msgstr "" + +#: IDF/Views/Admin.php:321 +msgid "You do not have the rights to update this user." +msgstr "" + +#: IDF/Views/Admin.php:339 +msgid "The user has been updated." +msgstr "" + +#: IDF/Views/Admin.php:372 +#, php-format +msgid "The user %s has been created." +msgstr "" + +#: IDF/Views/Admin.php:379 +msgid "Add User" +msgstr "" + +#: IDF/Views/Admin.php:395 +msgid "Usher management" +msgstr "" + +#: IDF/Views/Admin.php:432 +msgid "Usher configuration has been reloaded" +msgstr "" + +#: IDF/Views/Admin.php:436 +msgid "Usher has been shut down" +msgstr "" + +#: IDF/Views/Admin.php:441 +msgid "Usher has been started up" +msgstr "" + +#: IDF/Views/Admin.php:479 +#, php-format +msgid "The server \"%s\" has been started" +msgstr "" + +#: IDF/Views/Admin.php:483 +#, php-format +msgid "The server \"%s\" has been stopped" +msgstr "" + +#: IDF/Views/Admin.php:488 +#, php-format +msgid "The server \"%s\" has been killed" +msgstr "" + +#: IDF/Views/Admin.php:508 +#, php-format +msgid "Open connections for \"%s\"" +msgstr "" + +#: IDF/Views/Admin.php:513 +#, php-format +msgid "no connections for server \"%s\"" +msgstr "" + +#: IDF/Views/Admin.php:534 +msgid "Yes" +msgstr "" + +#: IDF/Views/Admin.php:534 +msgid "No" +msgstr "" + +#: IDF/Views/Download.php:45 +#, php-format +msgid "%s Downloads" +msgstr "" + +#: IDF/Views/Download.php:51 +msgid "This table shows the files to download." +msgstr "" + +#: IDF/Views/Download.php:67 IDF/Views/Download.php:349 +msgid "Uploaded" +msgstr "" + +#: IDF/Views/Download.php:71 IDF/Views/Download.php:353 +msgid "No downloads were found." +msgstr "" + +#: IDF/Views/Download.php:94 +#, php-format +msgid "Download %s" +msgstr "" + +#: IDF/Views/Download.php:111 +#, php-format +msgid "The file %2$s has been updated." +msgstr "" + +#: IDF/Views/Download.php:144 +#, php-format +msgid "Delete Download %s" +msgstr "" + +#: IDF/Views/Download.php:177 +msgid "The file has been deleted." +msgstr "" + +#: IDF/Views/Download.php:244 +#, php-format +msgid "The file has been uploaded." +msgstr "" + +#: IDF/Views/Download.php:271 +msgid "New Downloads from Archive" +msgstr "" + +#: IDF/Views/Download.php:278 +msgid "The archive has been uploaded and processed." +msgstr "" + +#: IDF/Views/Download.php:331 +#, php-format +msgid "%1$s Downloads with Label %2$s" +msgstr "" + +#: IDF/Views/Download.php:341 +#, php-format +msgid "This table shows the downloads with label %s." +msgstr "" + +#: IDF/Views/Issue.php:41 +#, php-format +msgid "%s Open Issues" +msgstr "" + +#: IDF/Views/Issue.php:51 IDF/Views/Issue.php:382 IDF/Views/User.php:75 +msgid "This table shows the open issues." +msgstr "" + +#: IDF/Views/Issue.php:61 IDF/Views/Issue.php:220 IDF/Views/Issue.php:301 +#: IDF/Views/Issue.php:390 IDF/Views/Issue.php:542 IDF/Views/Issue.php:765 +#: IDF/Views/Issue.php:824 IDF/Views/Review.php:57 IDF/Views/User.php:81 +msgid "Id" +msgstr "" + +#: IDF/Views/Issue.php:64 IDF/Views/Issue.php:223 IDF/Views/Issue.php:305 +#: IDF/Views/Issue.php:393 IDF/Views/Issue.php:545 IDF/Views/Issue.php:768 +#: IDF/Views/Issue.php:827 IDF/Views/Review.php:60 IDF/Views/User.php:85 +msgid "Last Updated" +msgstr "" + +#: IDF/Views/Issue.php:68 IDF/Views/Issue.php:227 IDF/Views/Issue.php:309 +#: IDF/Views/Issue.php:397 IDF/Views/Issue.php:549 IDF/Views/Issue.php:772 +#: IDF/Views/Issue.php:831 +msgid "No issues were found." +msgstr "" + +#: IDF/Views/Issue.php:113 +msgid "Not assigned" +msgstr "" + +#: IDF/Views/Issue.php:149 +#, php-format +msgid "Summary of tracked issues in %s." +msgstr "" + +#: IDF/Views/Issue.php:194 +#, php-format +msgid "Watch List: Closed Issues for %s" +msgstr "" + +#: IDF/Views/Issue.php:195 +#, php-format +msgid "This table shows the closed issues in your watch list for %s project." +msgstr "" + +#: IDF/Views/Issue.php:200 +#, php-format +msgid "Watch List: Open Issues for %s" +msgstr "" + +#: IDF/Views/Issue.php:201 +#, php-format +msgid "This table shows the open issues in your watch list for %s project." +msgstr "" + +#: IDF/Views/Issue.php:277 +msgid "Watch List: Closed Issues" +msgstr "" + +#: IDF/Views/Issue.php:278 +msgid "This table shows the closed issues in your watch list." +msgstr "" + +#: IDF/Views/Issue.php:283 +msgid "Watch List: Open Issues" +msgstr "" + +#: IDF/Views/Issue.php:284 +msgid "This table shows the open issues in your watch list." +msgstr "" + +#: IDF/Views/Issue.php:303 IDF/Views/User.php:82 +msgid "Project" +msgstr "" + +#: IDF/Views/Issue.php:344 +#, php-format +msgid "%1$s %2$s Submitted %3$s Issues" +msgstr "" + +#: IDF/Views/Issue.php:348 +#, php-format +msgid "%1$s %2$s Closed Submitted %3$s Issues" +msgstr "" + +#: IDF/Views/Issue.php:352 +#, php-format +msgid "%1$s %2$s Closed Working %3$s Issues" +msgstr "" + +#: IDF/Views/Issue.php:356 +#, php-format +msgid "%1$s %2$s Working %3$s Issues" +msgstr "" + +#: IDF/Views/Issue.php:417 +msgid "Submit a new issue" +msgstr "" + +#: IDF/Views/Issue.php:433 +#, php-format +msgid "Issue %2$d has been created." +msgstr "" + +#: IDF/Views/Issue.php:490 +#, php-format +msgid "Search issues - %s" +msgstr "" + +#: IDF/Views/Issue.php:492 +#, php-format +msgid "Search closed issues - %s" +msgstr "" + +#: IDF/Views/Issue.php:539 +msgid "This table shows the found issues." +msgstr "" + +#: IDF/Views/Issue.php:604 +#, php-format +msgid "Issue %2$d: %3$s" +msgstr "" + +#: IDF/Views/Issue.php:628 +#, php-format +msgid "Issue %2$d has been updated." +msgstr "" + +#: IDF/Views/Issue.php:718 +#, php-format +msgid "View %s" +msgstr "" + +#: IDF/Views/Issue.php:745 +#, php-format +msgid "%s Closed Issues" +msgstr "" + +#: IDF/Views/Issue.php:755 +msgid "This table shows the closed issues." +msgstr "" + +#: IDF/Views/Issue.php:798 +#, php-format +msgid "%1$s Issues with Label %2$s" +msgstr "" + +#: IDF/Views/Issue.php:801 +#, php-format +msgid "%1$s Closed Issues with Label %2$s" +msgstr "" + +#: IDF/Views/Issue.php:814 +#, php-format +msgid "This table shows the issues with label %s." +msgstr "" + +#: IDF/Views/Issue.php:937 +msgid "The issue has been removed from your watch list." +msgstr "" + +#: IDF/Views/Issue.php:940 +msgid "The issue has been added to your watch list." +msgstr "" + +#: IDF/Views/Issue.php:1037 +msgid "On your watch list." +msgstr "" + +#: IDF/Views/Project.php:95 +msgid "Issues and Comments" +msgstr "" + +#: IDF/Views/Project.php:99 +msgid "Documents" +msgstr "" + +#: IDF/Views/Project.php:101 +msgid "Reviews and Patches" +msgstr "" + +#: IDF/Views/Project.php:180 +msgid "This table shows the project updates." +msgstr "" + +#: IDF/Views/Project.php:191 +msgid "Change" +msgstr "" + +#: IDF/Views/Project.php:195 +msgid "No changes were found." +msgstr "" + +#: IDF/Views/Project.php:296 +#, php-format +msgid "%s Project Summary" +msgstr "" + +#: IDF/Views/Project.php:335 +#, php-format +msgid "%s Issue Tracking Configuration" +msgstr "" + +#: IDF/Views/Project.php:344 +msgid "The issue tracking configuration has been saved." +msgstr "" + +#: IDF/Views/Project.php:381 +#, php-format +msgid "%s Downloads Configuration" +msgstr "" + +#: IDF/Views/Project.php:393 +msgid "The downloads configuration has been saved." +msgstr "" + +#: IDF/Views/Project.php:428 +#, php-format +msgid "%s Documentation Configuration" +msgstr "" + +#: IDF/Views/Project.php:437 +msgid "The documentation configuration has been saved." +msgstr "" + +#: IDF/Views/Project.php:471 +#, php-format +msgid "%s Project Members" +msgstr "" + +#: IDF/Views/Project.php:480 +msgid "The project membership has been saved." +msgstr "" + +#: IDF/Views/Project.php:503 +#, php-format +msgid "%s Tabs Access Rights" +msgstr "" + +#: IDF/Views/Project.php:517 +msgid "" +"The project tabs access rights and notification settings have been saved." +msgstr "" + +#: IDF/Views/Project.php:566 +#, php-format +msgid "%s Source" +msgstr "" + +#: IDF/Views/Project.php:580 +msgid "The project source configuration has been saved." +msgstr "" + +#: IDF/Views/Review.php:41 +#, php-format +msgid "%s Code Reviews" +msgstr "" + +#: IDF/Views/Review.php:48 +msgid "This table shows the latest reviews." +msgstr "" + +#: IDF/Views/Review.php:64 +msgid "No reviews were found." +msgstr "" + +#: IDF/Views/Review.php:94 +#, php-format +msgid "The code review %2$d has been created." +msgstr "" + +#: IDF/Views/Review.php:140 +#, php-format +msgid "Review %2$d: %3$s" +msgstr "" + +#: IDF/Views/Review.php:160 +#, php-format +msgid "Your code review %2$d has been published." +msgstr "" + +#: IDF/Views/Source.php:40 +#, php-format +msgid "%s Source Help" +msgstr "" + +#: IDF/Views/Source.php:58 +#, php-format +msgid "%s Invalid Revision" +msgstr "" + +#: IDF/Views/Source.php:82 +#, php-format +msgid "%s Ambiguous Revision" +msgstr "" + +#: IDF/Views/Source.php:107 +#, php-format +msgid "%1$s %2$s Change Log" +msgstr "" + +#: IDF/Views/Source.php:153 IDF/Views/Source.php:234 IDF/Views/Source.php:362 +#, php-format +msgid "%1$s %2$s Source Tree" +msgstr "" + +#: IDF/Views/Source.php:310 +#, php-format +msgid "%s Commit Details" +msgstr "" + +#: IDF/Views/Source.php:311 +#, php-format +msgid "%1$s Commit Details - %2$s" +msgstr "" + +#: IDF/Views/User.php:59 +msgid "Your Dashboard - Working Issues" +msgstr "" + +#: IDF/Views/User.php:62 +msgid "Your Dashboard - Submitted Issues" +msgstr "" + +#: IDF/Views/User.php:89 +msgid "No issues are assigned to you, yeah!" +msgstr "" + +#: IDF/Views/User.php:89 +msgid "All the issues you submitted are fixed, yeah!" +msgstr "" + +#: IDF/Views/User.php:121 +msgid "Your personal information has been updated." +msgstr "" + +#: IDF/Views/User.php:133 +msgid "Your Account" +msgstr "" + +#: IDF/Views/User.php:157 +msgid "The public key has been deleted." +msgstr "" + +#: IDF/Views/User.php:177 +msgid "The address has been deleted." +msgstr "" + +#: IDF/Views/User.php:200 +msgid "Confirm The Email Change" +msgstr "" + +#: IDF/Views/User.php:232 +#, php-format +msgid "Your new email address \"%s\" has been validated. Thank you!" +msgstr "" + +#: IDF/Views/Wiki.php:41 +#, php-format +msgid "%s Documentation" +msgstr "" + +#: IDF/Views/Wiki.php:48 +msgid "This table shows the documentation pages." +msgstr "" + +#: IDF/Views/Wiki.php:61 IDF/Views/Wiki.php:144 IDF/Views/Wiki.php:185 +msgid "Page Title" +msgstr "" + +#: IDF/Views/Wiki.php:63 IDF/Views/Wiki.php:103 IDF/Views/Wiki.php:146 +#: IDF/Views/Wiki.php:187 +msgid "Updated" +msgstr "" + +#: IDF/Views/Wiki.php:67 IDF/Views/Wiki.php:191 +msgid "No documentation pages were found." +msgstr "" + +#: IDF/Views/Wiki.php:88 +#, php-format +msgid "%s Documentation Resources" +msgstr "" + +#: IDF/Views/Wiki.php:94 +msgid "This table shows the resources that can be used on documentation pages." +msgstr "" + +#: IDF/Views/Wiki.php:100 +msgid "Resource Title" +msgstr "" + +#: IDF/Views/Wiki.php:107 +msgid "No resources were found." +msgstr "" + +#: IDF/Views/Wiki.php:128 +#, php-format +msgid "Documentation Search - %s" +msgstr "" + +#: IDF/Views/Wiki.php:139 +msgid "This table shows the pages found." +msgstr "" + +#: IDF/Views/Wiki.php:150 +msgid "No pages were found." +msgstr "" + +#: IDF/Views/Wiki.php:169 +#, php-format +msgid "%1$s Documentation Pages with Label %2$s" +msgstr "" + +#: IDF/Views/Wiki.php:179 +#, php-format +msgid "This table shows the documentation pages with label %s." +msgstr "" + +#: IDF/Views/Wiki.php:222 +#, php-format +msgid "The page %2$s has been created." +msgstr "" + +#: IDF/Views/Wiki.php:265 +#, php-format +msgid "The resource %2$s has been created." +msgstr "" + +#: IDF/Views/Wiki.php:409 IDF/Views/Wiki.php:448 +msgid "The old revision has been deleted." +msgstr "" + +#: IDF/Views/Wiki.php:415 IDF/Views/Wiki.php:454 +#, php-format +msgid "Delete Old Revision of %s" +msgstr "" + +#: IDF/Views/Wiki.php:496 +#, php-format +msgid "The page %2$s has been updated." +msgstr "" + +#: IDF/Views/Wiki.php:548 +#, php-format +msgid "The resource %2$s has been updated." +msgstr "" + +#: IDF/Views/Wiki.php:583 +msgid "The documentation page has been deleted." +msgstr "" + +#: IDF/Views/Wiki.php:591 +#, php-format +msgid "Delete Page %s" +msgstr "" + +#: IDF/Views/Wiki.php:623 +msgid "The documentation resource has been deleted." +msgstr "" + +#: IDF/Views/Wiki.php:631 +#, php-format +msgid "Delete Resource %s" +msgstr "" + +#: IDF/Views.php:173 IDF/Views.php:199 +msgid "Confirm Your Account Creation" +msgstr "" + +#: IDF/Views.php:219 +msgid "Welcome! You can now participate in the life of your project of choice." +msgstr "" + +#: IDF/Views.php:245 IDF/Views.php:269 IDF/Views.php:310 +msgid "Password Recovery" +msgstr "" + +#: IDF/Views.php:289 +msgid "" +"Welcome back! Next time, you can use your broswer options to remember the " +"password." +msgstr "" + +#: IDF/Views.php:331 +msgid "Here to Help You!" +msgstr "" + +#: IDF/Views.php:347 +msgid "InDefero Upload Archive Format" +msgstr "" + +#: IDF/Views.php:363 +msgid "InDefero API (Application Programming Interface)" +msgstr "" + +#: IDF/Wiki/Page.php:62 IDF/Wiki/Resource.php:64 +msgid "title" +msgstr "" + +#: IDF/Wiki/Page.php:63 +msgid "" +"The title of the page must only contain letters, digits or the dash " +"character. For example: My-new-Wiki-Page." +msgstr "" + +#: IDF/Wiki/Page.php:71 +msgid "A one line description of the page content." +msgstr "" + +#: IDF/Wiki/Page.php:196 IDF/Wiki/PageRevision.php:196 +#, php-format +msgid "%2$s, %3$s" +msgstr "" + +#: IDF/Wiki/Page.php:198 +#, php-format +msgid "Creation of page %2$s, by %3$s" +msgstr "" + +#: IDF/Wiki/Page.php:208 +#, php-format +msgid "%1$s: Documentation page %2$s added - %3$s" +msgstr "" + +#: IDF/Wiki/PageRevision.php:48 +msgid "page" +msgstr "" + +#: IDF/Wiki/PageRevision.php:66 IDF/Wiki/ResourceRevision.php:64 +msgid "A one line description of the changes." +msgstr "" + +#: IDF/Wiki/PageRevision.php:72 +msgid "content" +msgstr "" + +#: IDF/Wiki/PageRevision.php:218 IDF/Wiki/ResourceRevision.php:311 +#, php-format +msgid "Change of %2$s, by %3$s" +msgstr "" + +#: IDF/Wiki/PageRevision.php:231 +#, php-format +msgid "%1$s: Documentation page %2$s updated - %3$s" +msgstr "" + +#: IDF/Wiki/PageRevision.php:293 +#, php-format +msgid "New Documentation Page %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Wiki/PageRevision.php:297 +#, php-format +msgid "Documentation Page Changed %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Wiki/Resource.php:65 +msgid "" +"The title of the resource must only contain letters, digits, dots or the " +"dash character. For example: my-resource.png." +msgstr "" + +#: IDF/Wiki/Resource.php:72 +msgid "MIME media type" +msgstr "" + +#: IDF/Wiki/Resource.php:73 +msgid "The MIME media type of the resource." +msgstr "" + +#: IDF/Wiki/Resource.php:81 +msgid "A one line description of the resource." +msgstr "" + +#: IDF/Wiki/Resource.php:176 IDF/Wiki/ResourceRevision.php:308 +#, php-format +msgid "%2$s, %3$s" +msgstr "" + +#: IDF/Wiki/Resource.php:178 +#, php-format +msgid "Creation of resource %2$s, by %3$s" +msgstr "" + +#: IDF/Wiki/Resource.php:188 +#, php-format +msgid "%1$s: Documentation resource %2$s added - %3$s" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:47 +msgid "resource" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:78 +msgid "File extension" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:79 +msgid "The file extension of the uploaded resource." +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:94 +msgid "page usage" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:116 +#, php-format +msgid "id %d: %s" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:263 +#, php-format +msgid "Download (%s)" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:270 +msgid "View resource details" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:324 +#, php-format +msgid "%1$s: Documentation resource %2$s updated - %3$s" +msgstr "" diff --git a/indefero/src/IDF/locale/pt_BR/idf.po b/indefero/src/IDF/locale/pt_BR/idf.po new file mode 100644 index 0000000..5af095c --- /dev/null +++ b/indefero/src/IDF/locale/pt_BR/idf.po @@ -0,0 +1,5398 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# pkiefer , 2011. +msgid "" +msgstr "" +"Project-Id-Version: Indefero\n" +"Report-Msgid-Bugs-To: http://projects.ceondo.com/p/indefero/issues/\n" +"POT-Creation-Date: 2012-03-22 01:16+0100\n" +"PO-Revision-Date: 2011-10-31 00:19+0000\n" +"Last-Translator: tommyd \n" +"Language-Team: LANGUAGE \n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1)\n" + +#: IDF/Commit.php:55 IDF/Conf.php:54 IDF/Issue.php:52 +#: IDF/ProjectActivity.php:49 IDF/Review.php:65 IDF/Search/Occ.php:69 +#: IDF/Tag.php:52 IDF/Upload.php:49 IDF/Wiki/Page.php:54 +#: IDF/Wiki/Resource.php:56 +msgid "project" +msgstr "projeto" + +#: IDF/Commit.php:63 IDF/Issue.php:67 IDF/IssueComment.php:65 +#: IDF/IssueFile.php:57 IDF/IssueRelation.php:69 IDF/Review/Comment.php:69 +#: IDF/Review.php:80 IDF/Upload.php:91 IDF/Wiki/Page.php:78 +#: IDF/Wiki/PageRevision.php:79 IDF/Wiki/Resource.php:88 +#: IDF/Wiki/ResourceRevision.php:86 +msgid "submitter" +msgstr "" + +#: IDF/Commit.php:87 IDF/Issue.php:60 IDF/Review/Patch.php:60 +#: IDF/Review.php:73 IDF/Upload.php:57 IDF/Wiki/Page.php:70 +#: IDF/Wiki/PageRevision.php:65 IDF/Wiki/Resource.php:80 +#: IDF/Wiki/ResourceRevision.php:63 +msgid "summary" +msgstr "sumário" + +#: IDF/Commit.php:93 +msgid "changelog" +msgstr "" + +#: IDF/Commit.php:100 IDF/Issue.php:105 IDF/IssueComment.php:79 +#: IDF/IssueFile.php:96 IDF/IssueRelation.php:75 IDF/Review/Comment.php:90 +#: IDF/Review/FileComment.php:75 IDF/Review/Patch.php:87 IDF/Review.php:108 +#: IDF/Upload.php:112 IDF/Wiki/Page.php:100 IDF/Wiki/PageRevision.php:92 +#: IDF/Wiki/Resource.php:95 IDF/Wiki/ResourceRevision.php:101 +msgid "creation date" +msgstr "data de criação" + +#: IDF/Commit.php:238 +#, php-format +msgid "Commit %1$s, by %2$s" +msgstr "" + +#: IDF/Commit.php:337 +#, php-format +msgid "New Commit %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Conf.php:61 IDF/Gconf.php:73 +msgid "key" +msgstr "chave" + +#: IDF/Conf.php:67 IDF/Gconf.php:79 IDF/ProjectActivity.php:62 +msgid "value" +msgstr "valor" + +#: IDF/Diff.php:460 +msgid "Old" +msgstr "" + +#: IDF/Diff.php:460 +msgid "New" +msgstr "" + +#: IDF/EmailAddress.php:49 IDF/Key.php:49 +msgid "user" +msgstr "usuário" + +#: IDF/EmailAddress.php:55 +msgid "email" +msgstr "" + +#: IDF/Form/Admin/ForgeConf.php:34 +msgid "Custom forge page enabled" +msgstr "" + +#: IDF/Form/Admin/ForgeConf.php:39 IDF/Form/WikiPageCreate.php:80 +#: IDF/Form/WikiPageUpdate.php:72 +msgid "Content" +msgstr "" + +#: IDF/Form/Admin/LabelConf.php:40 +msgid "Predefined project labels" +msgstr "" + +#: IDF/Form/Admin/LabelConf.php:55 +#, php-format +msgid "" +"The label \"%s\" is invalid: A label must only consist of alphanumeric " +"characters and dashes, and can optionally contain a \":\" with a group " +"prefix." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:38 IDF/Views/Project.php:600 +msgid "git" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:39 IDF/Views/Project.php:601 +msgid "Subversion" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:40 IDF/Views/Project.php:602 +msgid "mercurial" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:41 IDF/Views/Project.php:603 +msgid "monotone" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:49 IDF/Form/Admin/ProjectUpdate.php:44 +#: IDF/Form/ProjectConf.php:39 IDF/Views/Admin.php:86 IDF/Views/Admin.php:273 +msgid "Name" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:55 IDF/Form/TabsConf.php:101 +#: IDF/gettexttemplates/idf/base-full.html.php:5 +#: IDF/gettexttemplates/idf/base-full.html~.php:5 +#: IDF/gettexttemplates/idf/base.html.php:5 +#: IDF/gettexttemplates/idf/base.html~.php:5 +#: IDF/gettexttemplates/idf/main-menu.html.php:9 +#: IDF/gettexttemplates/idf/project-list.html.php:5 +#: IDF/gettexttemplates/idf/project-list.html.php:7 +msgid "Private project" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:62 +msgid "Shortname" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:64 +msgid "" +"It must be unique for each project and composed only of letters, digits and " +"dash (-) like \"my-project\"." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:69 IDF/Form/Admin/ProjectUpdate.php:50 +msgid "Short description" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:70 IDF/Form/Admin/ProjectUpdate.php:51 +#: IDF/Project.php:79 +msgid "A one line description of the project." +msgstr "Descrição do projeto em uma linha." + +#: IDF/Form/Admin/ProjectCreate.php:77 IDF/Form/Admin/ProjectUpdate.php:58 +#: IDF/Form/ProjectConf.php:56 +msgid "External URL" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:84 +msgid "Repository type" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:92 +msgid "Remote Subversion repository" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:99 IDF/Form/SourceConf.php:40 +msgid "Repository username" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:106 IDF/Form/SourceConf.php:47 +msgid "Repository password" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:113 IDF/Form/Admin/ProjectUpdate.php:66 +msgid "Master branch" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:116 IDF/Form/Admin/ProjectUpdate.php:69 +msgid "" +"This should be a world-wide unique identifier for your project. A reverse " +"DNS notation like \"com.my-domain.my-project\" is a good idea." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:121 IDF/Form/Admin/ProjectUpdate.php:95 +#: IDF/Form/MembersConf.php:46 IDF/Form/TabsConf.php:53 +#: IDF/Form/TabsConf.php:72 +msgid "Project owners" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:130 IDF/Form/Admin/ProjectUpdate.php:103 +#: IDF/Form/MembersConf.php:54 IDF/Form/TabsConf.php:52 +#: IDF/Form/TabsConf.php:78 +msgid "Project members" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:140 IDF/Form/Admin/ProjectUpdate.php:85 +#: IDF/Form/IssueCreate.php:168 IDF/Form/IssueUpdate.php:164 +#: IDF/Form/ProjectConf.php:73 IDF/Form/UpdateUpload.php:71 +#: IDF/Form/Upload.php:70 IDF/Form/WikiPageCreate.php:93 +#: IDF/Form/WikiPageUpdate.php:104 +msgid "Labels" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:155 +msgid "Project template" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:157 +msgid "" +"Use the given project to initialize the new project. Access rights and " +"general configuration will be taken from the template project." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:204 +msgid "" +"Only a remote repository available through HTTP or HTTPS is allowed. For " +"example \"http://somewhere.com/svn/trunk\"." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:220 IDF/Form/Admin/ProjectUpdate.php:117 +msgid "" +"The master branch is empty or contains illegal characters, please use only " +"letters, digits, dashes and dots as separators." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:230 IDF/Form/Admin/ProjectUpdate.php:128 +msgid "This master branch is already used. Please select another one." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:241 +msgid "" +"This shortname contains illegal characters, please use only letters, digits " +"and dash (-)." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:244 +msgid "The shortname cannot start with the dash (-) character." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:247 +msgid "The shortname cannot end with the dash (-) character." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:252 +msgid "This shortname is already used. Please select another one." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:303 IDF/Form/Admin/ProjectDelete.php:78 +#: IDF/Form/Admin/ProjectUpdate.php:153 IDF/Form/Admin/UserCreate.php:106 +#: IDF/Form/Admin/UserUpdate.php:191 IDF/Form/IssueCreate.php:338 +#: IDF/Form/IssueUpdate.php:329 IDF/Form/MembersConf.php:64 +#: IDF/Form/Password.php:76 IDF/Form/Register.php:112 +#: IDF/Form/ReviewCreate.php:187 IDF/Form/ReviewFileComment.php:143 +#: IDF/Form/TabsConf.php:122 IDF/Form/UpdateUpload.php:126 +#: IDF/Form/Upload.php:149 IDF/Form/UploadArchive.php:137 +#: IDF/Form/UserAccount.php:216 IDF/Form/UserChangeEmail.php:80 +#: IDF/Form/WikiPageCreate.php:167 IDF/Form/WikiPageDelete.php:59 +#: IDF/Form/WikiPageUpdate.php:178 IDF/Form/WikiResourceCreate.php:123 +#: IDF/Form/WikiResourceDelete.php:59 IDF/Form/WikiResourceUpdate.php:124 +msgid "Cannot save the model from an invalid form." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:341 +msgid "" +"Click on the Project Management tab to set the description of your project." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:426 +msgid "This project is not available." +msgstr "" + +#: IDF/Form/Admin/ProjectDelete.php:41 +msgid "Confirmation code" +msgstr "" + +#: IDF/Form/Admin/ProjectDelete.php:46 +msgid "I have made a backup of all the important data of this project." +msgstr "" + +#: IDF/Form/Admin/ProjectDelete.php:55 +msgid "" +"The confirmation code does not match. Please provide a valid confirmation " +"code to delete the project." +msgstr "" + +#: IDF/Form/Admin/ProjectDelete.php:63 +msgid "Sorry, you really need to backup your data before deletion." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:37 IDF/Form/Admin/UserUpdate.php:38 +#: IDF/Form/RegisterConfirmation.php:50 IDF/Form/UserAccount.php:40 +msgid "First name" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:46 IDF/Form/Admin/UserUpdate.php:47 +#: IDF/Form/RegisterConfirmation.php:59 IDF/Form/UserAccount.php:49 +msgid "Last name" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:56 +msgid "Login" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:60 +msgid "" +"The login must be between 3 and 15 characters long and contains only letters " +"and digits." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:69 IDF/Form/Admin/UserUpdate.php:57 +msgid "Email" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:71 +msgid "" +"Double check the email address as the password is sent directly to the user." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:76 IDF/Form/Admin/UserUpdate.php:67 +#: IDF/Form/UserAccount.php:66 +msgid "Language" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:87 IDF/Form/UserAccount.php:161 +msgid "Add a public key" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:92 +msgid "" +"Paste a SSH or monotone public key. Be careful to not provide your private " +"key here!" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:157 +msgid "Your details to access your forge." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:189 IDF/Form/UserAccount.php:429 +#: IDF/Form/UserAccount.php:438 +#, php-format +msgid "The email \"%s\" is already used." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:198 IDF/Form/Register.php:72 +#, php-format +msgid "The login \"%s\" can only contain letters and digits." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:203 IDF/Form/Register.php:77 +#, php-format +msgid "The login \"%s\" is already used, please find another one." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:78 +msgid "Password" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:81 +msgid "Leave blank if you do not want to change the password." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:81 +msgid "" +"The password must be hard for other people to guess, but easy for the user " +"to remember." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:89 +msgid "Confirm password" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:100 IDF/Form/IssueCreate.php:66 +#: IDF/Form/ProjectConf.php:48 IDF/Form/ReviewCreate.php:54 +#: IDF/Form/UpdateUpload.php:51 IDF/Form/Upload.php:49 +#: IDF/Form/UserAccount.php:101 IDF/Form/WikiPageCreate.php:70 +#: IDF/Form/WikiPageUpdate.php:60 IDF/Form/WikiResourceCreate.php:54 +#: IDF/Form/WikiResourceUpdate.php:46 IDF/Views/Wiki.php:102 +msgid "Description" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:109 IDF/Form/UserAccount.php:110 +msgid "Twitter username" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:119 IDF/Form/UserAccount.php:120 +msgid "Public email address" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:129 IDF/Form/UserAccount.php:130 +msgid "Website URL" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:139 IDF/Form/UserAccount.php:140 +msgid "Upload custom avatar" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:146 IDF/Form/UserAccount.php:147 +msgid "" +"An image file with a width and height not larger than 60 pixels (bigger " +"images are scaled down)." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:151 IDF/Form/UserAccount.php:152 +msgid "Remove custom avatar" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:155 IDF/Form/UserAccount.php:156 +msgid "Tick this to delete the custom avatar." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:161 IDF/Views/Admin.php:274 +msgid "Staff" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:164 +msgid "If you give staff rights to a user, you really need to trust him." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:172 IDF/Views/Admin.php:276 +msgid "Active" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:176 +msgid "" +"If the user is not getting the confirmation email or is abusing the system, " +"you can directly enable or disable their account here." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:274 +msgid "--- is not a valid first name." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:290 +msgid "" +"A user with this email already exists, please provide another email address." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:301 IDF/Form/UserAccount.php:398 +msgid "For security reason, you cannot upload a file with this extension." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:316 IDF/Form/UserAccount.php:461 +msgid "The passwords do not match. Please give them again." +msgstr "" + +#: IDF/Form/Field/EmailList.php:45 +msgid "Please enter one or more valid email addresses." +msgstr "" + +#: IDF/Form/IssueCreate.php:57 IDF/Form/IssueUpdate.php:46 +#: IDF/Form/ReviewCreate.php:45 IDF/Form/ReviewFileComment.php:73 +#: IDF/Form/UpdateUpload.php:42 IDF/Form/Upload.php:40 +#: IDF/gettexttemplates/idf/issues/base.html.php:3 IDF/Views/Download.php:65 +#: IDF/Views/Download.php:347 IDF/Views/Issue.php:62 IDF/Views/Issue.php:221 +#: IDF/Views/Issue.php:302 IDF/Views/Issue.php:391 IDF/Views/Issue.php:543 +#: IDF/Views/Issue.php:766 IDF/Views/Issue.php:825 IDF/Views/Review.php:58 +#: IDF/Views/User.php:83 IDF/Views/Wiki.php:62 IDF/Views/Wiki.php:145 +#: IDF/Views/Wiki.php:186 +msgid "Summary" +msgstr "" + +#: IDF/Form/IssueCreate.php:76 IDF/Form/IssueUpdate.php:66 +#: IDF/Form/ReviewCreate.php:83 +msgid "The \"upload_issue_path\" configuration variable was not set." +msgstr "" + +#: IDF/Form/IssueCreate.php:86 IDF/Form/IssueUpdate.php:76 +msgid "Attach a file" +msgstr "" + +#: IDF/Form/IssueCreate.php:99 IDF/Form/IssueUpdate.php:89 +#: IDF/Form/ReviewCreate.php:103 IDF/Form/ReviewFileComment.php:83 +#: IDF/Views/Issue.php:63 IDF/Views/Issue.php:222 IDF/Views/Issue.php:304 +#: IDF/Views/Issue.php:392 IDF/Views/Issue.php:544 IDF/Views/Issue.php:767 +#: IDF/Views/Issue.php:826 IDF/Views/Review.php:59 IDF/Views/User.php:84 +msgid "Status" +msgstr "" + +#: IDF/Form/IssueCreate.php:108 IDF/Form/IssueUpdate.php:99 +msgid "Owner" +msgstr "" + +#: IDF/Form/IssueCreate.php:118 IDF/Form/IssueUpdate.php:112 +#: IDF/Form/IssueUpdate.php:129 +msgid "This issue" +msgstr "" + +#: IDF/Form/IssueCreate.php:210 +msgid "You cannot add a label with the \"Status\" prefix to an issue." +msgstr "" + +#: IDF/Form/IssueCreate.php:211 IDF/Form/IssueCreate.php:218 +#: IDF/Form/UpdateUpload.php:110 IDF/Form/Upload.php:121 +#: IDF/Form/WikiPageCreate.php:151 IDF/Form/WikiPageUpdate.php:162 +msgid "You provided an invalid label." +msgstr "" + +#: IDF/Form/IssueCreate.php:217 IDF/Form/UpdateUpload.php:109 +#, php-format +msgid "You cannot provide more than one label from the %s class to an issue." +msgstr "" + +#: IDF/Form/IssueCreate.php:228 IDF/Form/IssueUpdate.php:194 +msgid "You need to provide a description of the issue." +msgstr "" + +#: IDF/Form/IssueCreate.php:251 IDF/Form/ReviewCreate.php:159 +msgid "You provided an invalid status." +msgstr "" + +#: IDF/Form/IssueCreate.php:272 +msgid "You provided an invalid relation type." +msgstr "" + +#: IDF/Form/IssueCreate.php:294 +#, php-format +msgid "The value \"%s\" is not a valid issue id." +msgstr "" + +#: IDF/Form/IssueCreate.php:300 +#, php-format +msgid "The issue \"%s\" does not exist." +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:86 +msgid "is related to" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:87 +msgid "blocks" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:88 +msgid "is blocked by" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:89 +msgid "duplicates" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:90 +msgid "is duplicated by" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:97 +msgid "" +"Define an issue template to hint the reporter to provide certain information" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:106 +msgid "Open issue status values" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:114 +msgid "Closed issue status values" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:123 +msgid "Predefined issue labels" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:125 +msgid "" +"The first \"Type:\" and \"Priority:\" entries found in this list are " +"automatically chosen as defaults for new issues." +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:133 +msgid "Each issue may have at most one label with each of these classes." +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:140 +msgid "Issue relations" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:142 +msgid "" +"You can define bidirectional relations like \"is related to\" or \"blocks, " +"is blocked by\". For standard relations pre-configured translations exist, " +"new relations should however be defined in a language that is understood by " +"all project members." +msgstr "" + +#: IDF/Form/IssueUpdate.php:56 IDF/Form/ReviewFileComment.php:45 +#: IDF/Form/WikiPageUpdate.php:82 IDF/Form/WikiResourceUpdate.php:66 +msgid "Comment" +msgstr "" + +#: IDF/Form/IssueUpdate.php:316 +msgid "No changes were entered." +msgstr "" + +#: IDF/Form/MembersConf.php:104 +#, php-format +msgid "The following login is invalid: %s." +msgid_plural "The following logins are invalid: %s." +msgstr[0] "" +msgstr[1] "" + +#: IDF/Form/Password.php:34 +msgid "Your login or email" +msgstr "" + +#: IDF/Form/Password.php:35 +msgid "Provide either your login or your email to recover your password." +msgstr "" + +#: IDF/Form/Password.php:49 IDF/Form/Password.php:64 +msgid "" +"Sorry, we cannot find a user with this email address or login. Feel free to " +"try again." +msgstr "" + +#: IDF/Form/Password.php:100 +msgid "Password Recovery - InDefero" +msgstr "" + +#: IDF/Form/PasswordInputKey.php:36 IDF/Form/PasswordReset.php:39 +#: IDF/Form/UserChangeEmail.php:36 +msgid "Your verification key" +msgstr "" + +#: IDF/Form/PasswordInputKey.php:50 IDF/Form/PasswordReset.php:89 +msgid "" +"We are sorry but this validation key is not valid. Maybe you should directly " +"copy/paste it from your validation email." +msgstr "" + +#: IDF/Form/PasswordInputKey.php:61 IDF/Form/PasswordReset.php:100 +msgid "" +"Sorry, but this verification key has expired, please restart the password " +"recovery sequence. For security reasons, the verification key is only valid " +"24h." +msgstr "" + +#: IDF/Form/PasswordInputKey.php:76 IDF/Form/PasswordReset.php:108 +#: IDF/Form/RegisterConfirmation.php:137 IDF/Form/RegisterInputKey.php:72 +msgid "Cannot save an invalid form." +msgstr "" + +#: IDF/Form/PasswordReset.php:45 IDF/Form/RegisterConfirmation.php:69 +#: IDF/Form/UserAccount.php:77 +msgid "Your password" +msgstr "" + +#: IDF/Form/PasswordReset.php:48 IDF/Form/UserAccount.php:80 +msgid "" +"Your password must be hard for other people to find it, but easy for you to " +"remember." +msgstr "" + +#: IDF/Form/PasswordReset.php:56 IDF/Form/RegisterConfirmation.php:80 +#: IDF/Form/UserAccount.php:89 +msgid "Confirm your password" +msgstr "" + +#: IDF/Form/PasswordReset.php:74 IDF/Form/RegisterConfirmation.php:122 +msgid "The two passwords must be the same." +msgstr "" + +#: IDF/Form/PasswordReset.php:77 +msgid "" +"This account is not active. Please contact the forge administrator to " +"activate it." +msgstr "" + +#: IDF/Form/ProjectConf.php:43 +msgid "Short Description" +msgstr "" + +#: IDF/Form/ProjectConf.php:85 +msgid "The \"upload_path\" configuration variable was not set." +msgstr "" + +#: IDF/Form/ProjectConf.php:90 +msgid "Update the logo" +msgstr "" + +#: IDF/Form/ProjectConf.php:92 +msgid "The logo must be a picture with a size of 32 by 32." +msgstr "" + +#: IDF/Form/ProjectConf.php:103 +msgid "Remove the current logo" +msgstr "" + +#: IDF/Form/ProjectConf.php:139 +msgid "Could not determine the size of the uploaded picture." +msgstr "" + +#: IDF/Form/ProjectConf.php:143 +msgid "The picture must have a size of 32 by 32." +msgstr "" + +#: IDF/Form/ProjectConf.php:164 +msgid "The entered URL is invalid. Only http and https URLs are allowed." +msgstr "" + +#: IDF/Form/Register.php:41 +msgid "Your login" +msgstr "" + +#: IDF/Form/Register.php:45 +msgid "" +"The login must be between 3 and 15 characters long and contain only letters " +"and digits." +msgstr "" + +#: IDF/Form/Register.php:53 IDF/Form/UserAccount.php:59 +msgid "Your email" +msgstr "" + +#: IDF/Form/Register.php:55 +msgid "We will never send you any unsolicited emails. We hate spam too!" +msgstr "" + +#: IDF/Form/Register.php:60 +msgid "I agree to the terms and conditions." +msgstr "" + +#: IDF/Form/Register.php:88 +msgid "" +"We know, this is boring, but you need to agree with the terms and conditions." +msgstr "" + +#: IDF/Form/Register.php:97 +#, php-format +msgid "" +"The email \"%1$s\" is already used. If you need to, you can recover your password." +msgstr "" + +#: IDF/Form/Register.php:148 +msgid "Confirm the creation of your account." +msgstr "" + +#: IDF/Form/RegisterConfirmation.php:40 IDF/Form/RegisterInputKey.php:36 +msgid "Your confirmation key" +msgstr "" + +#: IDF/Form/RegisterConfirmation.php:72 +msgid "" +"Your password must be hard for other people to guess, but easy for you to " +"remember." +msgstr "" + +#: IDF/Form/RegisterConfirmation.php:99 IDF/Form/RegisterInputKey.php:50 +msgid "" +"We are sorry but this confirmation key is not valid. Maybe you should " +"directly copy/paste it from your confirmation email." +msgstr "" + +#: IDF/Form/RegisterConfirmation.php:110 +#, php-format +msgid "" +"This account has already been confirmed. Maybe should you try to recover your password." +msgstr "" + +#: IDF/Form/ReviewCreate.php:74 +#: IDF/gettexttemplates/idf/source/base.html.php:5 +#: IDF/gettexttemplates/idf/source/changelog.html.php:7 +msgid "Commit" +msgstr "" + +#: IDF/Form/ReviewCreate.php:92 +msgid "Patch" +msgstr "" + +#: IDF/Form/ReviewCreate.php:119 +msgid "We were not able to parse your patch. Please provide a valid patch." +msgstr "" + +#: IDF/Form/ReviewCreate.php:128 +msgid "You provided an invalid commit." +msgstr "" + +#: IDF/Form/ReviewCreate.php:202 +msgid "Initial patch to be reviewed." +msgstr "" + +#: IDF/Form/ReviewFileComment.php:56 +msgid "General comment" +msgstr "" + +#: IDF/Form/ReviewFileComment.php:113 +msgid "" +"You need to provide your general comment about the proposal, or comments on " +"at least one file." +msgstr "" + +#: IDF/Form/ReviewFileComment.php:124 +msgid "The status have been updated." +msgstr "" + +#: IDF/Form/ReviewFileComment.php:130 +msgid "This field is required." +msgstr "" + +#: IDF/Form/SourceConf.php:54 IDF/Form/UploadConf.php:70 +msgid "Webhook URL" +msgstr "" + +#: IDF/Form/TabsConf.php:38 IDF/gettexttemplates/idf/admin/base.html.php:4 +#: IDF/gettexttemplates/idf/base-full.html.php:8 +#: IDF/gettexttemplates/idf/base-full.html~.php:7 +#: IDF/gettexttemplates/idf/base.html.php:8 +#: IDF/gettexttemplates/idf/base.html~.php:7 +#: IDF/gettexttemplates/idf/downloads/base.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:14 +#: IDF/Views/Project.php:97 +msgid "Downloads" +msgstr "" + +#: IDF/Form/TabsConf.php:39 IDF/gettexttemplates/idf/base-full.html.php:12 +#: IDF/gettexttemplates/idf/base-full.html~.php:11 +#: IDF/gettexttemplates/idf/base.html.php:12 +#: IDF/gettexttemplates/idf/base.html~.php:11 +msgid "Code Review" +msgstr "Revisão de Código" + +#: IDF/Form/TabsConf.php:40 IDF/gettexttemplates/idf/admin/base.html.php:5 +#: IDF/gettexttemplates/idf/base-full.html.php:9 +#: IDF/gettexttemplates/idf/base-full.html~.php:8 +#: IDF/gettexttemplates/idf/base.html.php:9 +#: IDF/gettexttemplates/idf/base.html~.php:8 +msgid "Documentation" +msgstr "Documentação" + +#: IDF/Form/TabsConf.php:41 IDF/gettexttemplates/idf/admin/base.html.php:7 +#: IDF/gettexttemplates/idf/base-full.html.php:11 +#: IDF/gettexttemplates/idf/base-full.html~.php:10 +#: IDF/gettexttemplates/idf/base.html.php:11 +#: IDF/gettexttemplates/idf/base.html~.php:10 +msgid "Source" +msgstr "Código Fonte" + +#: IDF/Form/TabsConf.php:42 IDF/gettexttemplates/idf/base-full.html.php:10 +#: IDF/gettexttemplates/idf/base-full.html~.php:9 +#: IDF/gettexttemplates/idf/base.html.php:10 +#: IDF/gettexttemplates/idf/base.html~.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:17 +msgid "Issues" +msgstr "" + +#: IDF/Form/TabsConf.php:50 +msgid "Open to all" +msgstr "" + +#: IDF/Form/TabsConf.php:51 +msgid "Signed in users" +msgstr "" + +#: IDF/Form/TabsConf.php:54 +msgid "Closed" +msgstr "" + +#: IDF/Form/TabsConf.php:84 +#, fuzzy +msgid "Others" +msgstr "Outro" + +#: IDF/Form/TabsConf.php:107 +msgid "Extra authorized users" +msgstr "" + +#: IDF/Form/Upload.php:59 IDF/Form/WikiResourceCreate.php:65 +#: IDF/Form/WikiResourceUpdate.php:56 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:7 +#: IDF/Views/Download.php:64 IDF/Views/Download.php:346 +msgid "File" +msgstr "" + +#: IDF/Form/Upload.php:87 IDF/Form/WikiResourceCreate.php:96 +#: IDF/Form/WikiResourceUpdate.php:83 +msgid "For security reasons, you cannot upload a file with this extension." +msgstr "" + +#: IDF/Form/Upload.php:120 +#, php-format +msgid "You cannot provide more than one label from the %s class to a download." +msgstr "" + +#: IDF/Form/UploadArchive.php:41 +#, fuzzy +msgid "Archive file" +msgstr "o arquivo" + +#: IDF/Form/UploadArchive.php:67 +#, php-format +msgid "" +"For security reasons, you cannot upload a file (%s) with this extension." +msgstr "" + +#: IDF/Form/UploadArchive.php:98 +#, php-format +msgid "" +"You cannot provide more than label from the %1$s class to a download (%2$s)." +msgstr "" + +#: IDF/Form/UploadArchive.php:109 +#, php-format +msgid "" +"A file with the name \"%s\" has already been uploaded and is not marked to " +"be replaced." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:41 +msgid "The archive does not exist." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:48 +#, php-format +msgid "The archive could not be read (code %d)." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:53 +msgid "The archive does not contain a manifest.xml." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:61 +#, php-format +msgid "The archive's manifest is invalid: %s" +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:77 +#, php-format +msgid "The entry %d in the manifest is missing a file name." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:82 +#, php-format +msgid "The entry %d in the manifest is missing a summary." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:86 +msgid "The manifest must not reference itself." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:91 +#, php-format +msgid "The entry %s in the manifest does not exist in the archive." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:96 +#, php-format +msgid "The entry %s in the manifest is referenced more than once." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:108 +#, php-format +msgid "The entry %s in the manifest has more than the six allowed labels set." +msgstr "" + +#: IDF/Form/UploadConf.php:53 +msgid "Predefined download labels" +msgstr "" + +#: IDF/Form/UploadConf.php:62 +msgid "Each download may have at most one label with each of these classes" +msgstr "" + +#: IDF/Form/UserAccount.php:61 +msgid "" +"If you change your email address, an email will be sent to the new address " +"to confirm it." +msgstr "" + +#: IDF/Form/UserAccount.php:80 +msgid "Leave blank if you do not want to change your password." +msgstr "" + +#: IDF/Form/UserAccount.php:166 +msgid "" +"Paste an SSH or monotone public key. Be careful to not provide your private " +"key here!" +msgstr "" + +#: IDF/Form/UserAccount.php:171 +msgid "Add a secondary email address" +msgstr "" + +#: IDF/Form/UserAccount.php:173 +msgid "You will get an email to confirm that you own the address you specify." +msgstr "" + +#: IDF/Form/UserAccount.php:200 +msgid "Confirm your new email address." +msgstr "" + +#: IDF/Form/UserAccount.php:203 +#, php-format +msgid "" +"A validation email has been sent to \"%s\" to validate the email address " +"change." +msgstr "" + +#: IDF/Form/UserAccount.php:341 +msgid "" +"Please check the key as it does not appear to be a valid SSH public key." +msgstr "" + +#: IDF/Form/UserAccount.php:363 +msgid "" +"Please check the key as it does not appear to be a valid monotone public key." +msgstr "" + +#: IDF/Form/UserAccount.php:371 +msgid "Public key looks like neither an SSH nor monotone public key." +msgstr "" + +#: IDF/Form/UserAccount.php:383 +msgid "You already have uploaded this key." +msgstr "" + +#: IDF/Form/UserChangeEmail.php:63 +msgid "" +"The validation key is not valid. Please copy/paste it from your confirmation " +"email." +msgstr "" + +#: IDF/Form/WikiConf.php:49 +msgid "Predefined documentation page labels" +msgstr "" + +#: IDF/Form/WikiConf.php:58 +msgid "" +"Each documentation page may have at most one label with each of these classes" +msgstr "" + +#: IDF/Form/WikiPageCreate.php:38 +msgid "" +"# Introduction\n" +"\n" +"Add your content here.\n" +"\n" +"\n" +"# Details\n" +"\n" +"Add your content here. Format your content with:\n" +"\n" +"* Text in **bold** or *italic*.\n" +"* Headings, paragraphs, and lists.\n" +"* Links to other [[WikiPage]].\n" +msgstr "" + +#: IDF/Form/WikiPageCreate.php:57 +msgid "PageName" +msgstr "" + +#: IDF/Form/WikiPageCreate.php:60 IDF/Form/WikiPageUpdate.php:50 +msgid "Page title" +msgstr "" + +#: IDF/Form/WikiPageCreate.php:66 IDF/Form/WikiPageUpdate.php:56 +msgid "" +"The page name must contains only letters, digits and the dash (-) character." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:71 IDF/Form/WikiPageUpdate.php:61 +msgid "This one line description is displayed in the list of pages." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:108 IDF/Form/WikiPageUpdate.php:119 +#: IDF/Form/WikiResourceCreate.php:78 +msgid "The title contains invalid characters." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:114 IDF/Form/WikiPageUpdate.php:125 +msgid "A page with this title already exists." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:150 IDF/Form/WikiPageUpdate.php:161 +#, php-format +msgid "You cannot provide more than one label from the %s class to a page." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:200 +msgid "Initial page creation" +msgstr "" + +#: IDF/Form/WikiPageDelete.php:39 +msgid "Yes, I understand that the page and all its revisions will be deleted." +msgstr "" + +#: IDF/Form/WikiPageDelete.php:50 IDF/Form/WikiResourceDelete.php:50 +msgid "You need to confirm the deletion." +msgstr "" + +#: IDF/Form/WikiPageUpdate.php:83 IDF/Form/WikiResourceUpdate.php:67 +msgid "One line to describe the changes you made." +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:40 +msgid "ResourceName" +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:44 +msgid "Resource title" +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:50 +msgid "" +"The resource name must contains only letters, digits and the dash (-) " +"character." +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:55 IDF/Form/WikiResourceUpdate.php:47 +#, fuzzy +msgid "This one line description is displayed in the list of resources." +msgstr "Descrição do projeto em uma linha." + +#: IDF/Form/WikiResourceCreate.php:84 +msgid "A resource with this title already exists." +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:142 +msgid "Initial resource creation" +msgstr "" + +#: IDF/Form/WikiResourceDelete.php:39 +msgid "" +"Yes, I understand that the resource and all its revisions will be deleted." +msgstr "" + +#: IDF/Form/WikiResourceUpdate.php:89 +#, php-format +msgid "" +"The mime type of the uploaded file \"%1$s\" does not match the mime type of " +"this resource \"%2$s\"" +msgstr "" + +#: IDF/Form/WikiResourceUpdate.php:97 +msgid "The current version of the resource and the uploaded file are equal." +msgstr "" + +#: IDF/Gconf.php:60 IDF/Search/Occ.php:56 +msgid "model class" +msgstr "" + +#: IDF/Gconf.php:66 IDF/Search/Occ.php:62 +msgid "model id" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/base.html.php:3 +msgid "Project Summary" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/base.html.php:6 +msgid "Issue Tracking" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/base.html.php:8 +msgid "Project Members" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/base.html.php:9 +msgid "Tabs Access and Notifications" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:3 +#: IDF/gettexttemplates/idf/admin/issue-tracking.html.php:3 +#: IDF/gettexttemplates/idf/admin/wiki.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/labels.html.php:3 +msgid "" +"\n" +"

Instructions:

\n" +"

List one status value per line in desired sort-order.

\n" +"

Optionally, use an equals-sign to document the meaning of each status " +"value.

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:8 +msgid "" +"

The webhook URL setting specifies an URL to which a HTTP PUT\n" +"request is sent after a new download has been added or to which a HTTP " +"POST\n" +"request is sent after an existing download has been updated.\n" +"If this field is empty, notifications are disabled.

\n" +"\n" +"

Only properly-escaped HTTP URLs are supported, for " +"example:

\n" +"\n" +"
    \n" +"
  • http://domain.com/upload
  • \n" +"
  • http://domain.com/upload?my%20param
  • \n" +"
\n" +"\n" +"

In addition, the URL may contain the following \"%\" notation, which\n" +"will be replaced with specific project values for each download:

\n" +"\n" +"
    \n" +"
  • %p - project name
  • \n" +"
  • %d - download id
  • \n" +"
\n" +"\n" +"

For example, updating download 123 of project 'my-project' with\n" +"web hook URL http://mydomain.com/%p/%d would send a POST " +"request to\n" +"http://mydomain.com/my-project/123.

" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:31 +#: IDF/gettexttemplates/idf/admin/source.html.php:30 +msgid "Web-Hook authentication key:" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:32 +#: IDF/gettexttemplates/idf/admin/issue-tracking.html.php:8 +#: IDF/gettexttemplates/idf/admin/members.html.php:13 +#: IDF/gettexttemplates/idf/admin/source.html.php:31 +#: IDF/gettexttemplates/idf/admin/summary.html.php:11 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:12 +#: IDF/gettexttemplates/idf/admin/wiki.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/forge/index.html.php:13 +#: IDF/gettexttemplates/idf/gadmin/projects/labels.html.php:8 +msgid "Save Changes" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/members.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:3 +msgid "" +"\n" +"

Instructions:

\n" +"

Specify each person by its login. Each person must have already " +"registered with the given login.

\n" +"

Separate the logins with commas and/or new lines.

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/members.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:8 +msgid "" +"\n" +"

Notes:

\n" +"

A project owner may make any change to this project, including removing " +"other project owners. You need to be carefull when you give owner rights.\n" +"

A project member will not have access to the administration area but will " +"have more options available in the use of the project.

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:3 +msgid "You can find here the current repository configuration of your project." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:4 +msgid "" +"

The webhook URL setting specifies an URL to which a HTTP \n" +"%%hook_request_method%% request is sent after each " +"repository\n" +"commit. If this field is empty, notifications are disabled.

\n" +"\n" +"

Only properly-escaped HTTP URLs are supported, for " +"example:

\n" +"\n" +"
    \n" +"
  • http://domain.com/commit
  • \n" +"
  • http://domain.com/commit?my%20param
  • \n" +"
\n" +"\n" +"

In addition, the URL may contain the following \"%\" notation, which\n" +"will be replaced with specific project values for each commit:

\n" +"\n" +"
    \n" +"
  • %p - project name
  • \n" +"
  • %r - revision number
  • \n" +"
\n" +"\n" +"

For example, committing revision 123 to project 'my-project' with\n" +"post-commit URL http://mydomain.com/%p/%r would send a request " +"to\n" +"http://mydomain.com/my-project/123.

" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:26 +msgid "" +"The form contains some errors. Please correct them to update the source " +"configuration." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:27 +msgid "Repository type:" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:28 +msgid "Repository access:" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:29 +msgid "Repository size:" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

The description of the project can be improved using the Markdown syntax.

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:7 +msgid "" +"The form contains some errors. Please correct them to update the summary." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:8 +msgid "Current logo" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:9 +#: IDF/gettexttemplates/idf/base-full.html.php:4 +#: IDF/gettexttemplates/idf/base-full.html~.php:4 +#: IDF/gettexttemplates/idf/base.html.php:4 +#: IDF/gettexttemplates/idf/base.html~.php:4 +#: IDF/gettexttemplates/idf/main-menu.html.php:8 +#: IDF/gettexttemplates/idf/project-list.html.php:4 +msgid "Project logo" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:10 +msgid "Your project does not have a logo configured yet." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:3 +msgid "" +"This section allows you to configure project tabs access rights and " +"notifications." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:4 +msgid "" +"Tab access controls whether a single user can navigate into a particular " +"section of your project via the main menu or automatically generated object " +"links." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:5 +msgid "" +"If you mark a project as private, only the project members and " +"administrators, together with the extra authorized users you provide will " +"have access to the project as a whole. You will still be able to define " +"further access rights for the different tabs but the \"Open to all\" and " +"\"Signed in users\" will default to authorized users only." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:6 +msgid "" +"For the extra authorized user list, specify each person by its login. Each " +"person must have already registered with the given login. Separate the " +"logins with commas and/or new lines." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:7 +msgid "" +"Only project members and admins have write access to the source. If you " +"restrict the access to the source, anonymous access is not provided and the " +"users must authenticate themselves with their password or SSH key." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:8 +#, php-format +msgid "" +"Here you can configure who should be notified about changes in a particular " +"section. You can also configure additional addresses, like the one of a " +"mailing list, that should be notified. (Keep in mind that you might have to " +"register the sender address %%from_email%% to let the " +"mailing list actually accept notification emails.) Multiple email addresses " +"must be separated through commas (',')." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:9 +msgid "" +"The form contains some errors. Please correct them to update the access " +"rights." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:10 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:13 +msgid "Access Rights" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:11 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:14 +#, fuzzy +msgid "Notifications" +msgstr "data de modificação" + +#: IDF/gettexttemplates/idf/base-full.html.php:3 +#: IDF/gettexttemplates/idf/base-full.html~.php:3 +#: IDF/gettexttemplates/idf/base.html.php:3 +#: IDF/gettexttemplates/idf/base.html~.php:3 +#, php-format +msgid "" +"Sign in or create your account to create issues or " +"add comments" +msgstr "" + +#: IDF/gettexttemplates/idf/base-full.html.php:6 +#: IDF/gettexttemplates/idf/base.html.php:6 +#: IDF/gettexttemplates/idf/project-list.html.php:6 +msgid "External link to project" +msgstr "" + +#: IDF/gettexttemplates/idf/base-full.html.php:7 +#: IDF/gettexttemplates/idf/base-full.html~.php:6 +#: IDF/gettexttemplates/idf/base.html.php:7 +#: IDF/gettexttemplates/idf/base.html~.php:6 +msgid "Project Home" +msgstr "" + +#: IDF/gettexttemplates/idf/base-full.html.php:13 +#: IDF/gettexttemplates/idf/base-full.html~.php:12 +#: IDF/gettexttemplates/idf/base.html.php:13 +#: IDF/gettexttemplates/idf/base.html~.php:12 +msgid "Project Management" +msgstr "Gerência de Projeto" + +#: IDF/gettexttemplates/idf/downloads/base.html.php:4 +#: IDF/gettexttemplates/idf/downloads/index.html.php:4 +#: IDF/Views/Download.php:235 +msgid "New Download" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/base.html.php:5 +msgid "Upload Archive" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:3 +msgid "" +"Each file must have a distinct name and file contents\n" +"cannot be changed, so be sure to include release numbers in each file\n" +"name." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:6 +#, php-format +msgid "" +"You can use the Markdown syntax for the description." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:7 +msgid "The form contains some errors. Please correct them to submit the file." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:8 +msgid "Submit File" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:9 +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:8 +#: IDF/gettexttemplates/idf/downloads/delete.html.php:7 +#: IDF/gettexttemplates/idf/downloads/view.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:21 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:14 +#: IDF/gettexttemplates/idf/issues/create.html.php:14 +#: IDF/gettexttemplates/idf/issues/view.html.php:27 +#: IDF/gettexttemplates/idf/register/confirmation.html.php:7 +#: IDF/gettexttemplates/idf/register/index.html.php:8 +#: IDF/gettexttemplates/idf/register/inputkey.html.php:5 +#: IDF/gettexttemplates/idf/review/create.html.php:12 +#: IDF/gettexttemplates/idf/review/view.html.php:41 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:5 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:13 +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:7 +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:9 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:5 +msgid "Cancel" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:10 +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:9 +#: IDF/gettexttemplates/idf/register/inputkey.html.php:6 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:6 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:6 +msgid "Instructions" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:3 +msgid "" +"The archive must include a manifest.xml file with meta " +"information about the\n" +"files to process inside the archive. All processed files must be unique or " +"replace existing files explicitely." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:5 +#, php-format +msgid "" +"You can learn more about the archive format here." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:6 +msgid "" +"The form contains some errors. Please correct them to submit the archive." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:7 +msgid "Submit Archive" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:3 +msgid "" +"Attention! If you want to delete a specific version of your " +"software, maybe, someone is depending on this specific version to run his " +"systems. Are you sure, you will not affect anybody when removing this file?" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:4 +#, php-format +msgid "" +"Instead of deleting the file, you could mark it as " +"deprecated." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:5 +#: IDF/gettexttemplates/idf/downloads/view.html.php:4 +#: IDF/gettexttemplates/idf/issues/attachment.html.php:4 +#: IDF/gettexttemplates/idf/issues/view.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:5 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:7 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:7 +#, php-format +msgid "by %%submitter%%" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:6 +msgid "Delete File" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:8 +#: IDF/gettexttemplates/idf/downloads/view.html.php:14 +msgid "Uploaded:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:9 +#: IDF/gettexttemplates/idf/downloads/view.html.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:29 +#: IDF/gettexttemplates/idf/review/view.html.php:27 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:12 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:14 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:14 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:15 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:17 +msgid "Updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:10 +#: IDF/gettexttemplates/idf/downloads/view.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:6 +#: IDF/gettexttemplates/idf/listProjects.html.php:17 +msgid "Downloads:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:11 +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:7 +#: IDF/gettexttemplates/idf/downloads/view.html.php:17 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:6 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:6 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:11 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:16 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:10 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:21 +#: IDF/gettexttemplates/idf/issues/view.html.php:33 +#: IDF/gettexttemplates/idf/project-list.html.php:8 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:6 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:13 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:16 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:12 +#: IDF/IssueComment.php:157 IDF/Wiki/PageRevision.php:204 +msgid "Labels:" +msgstr "Marcadores:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:3 +msgid "A new file is available for download:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:4 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:6 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:5 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:8 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:4 +msgid "Hello," +msgstr "Olá," + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:6 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:5 +msgid "Project:" +msgstr "Projeto:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:6 +msgid "Submitted by:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:8 +msgid "Download:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/view.html.php:31 +#: IDF/gettexttemplates/idf/user/public.html.php:4 +msgid "Description:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:3 +msgid "A file download was updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/feedfragment.xml.php:3 +msgid "Details" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/index.html.php:3 +#, php-format +msgid "See the deprecated files." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/index.html.php:5 +msgid "Number of files:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:3 +msgid "" +"Attention! This file is marked as deprecated, download it " +"only if you are sure you need this specific version." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:5 +msgid "md5:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:6 +msgid "Changes" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:7 +msgid "The form contains some errors. Please correct them to update the file." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:8 +msgid "Update File" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:10 +#: IDF/gettexttemplates/idf/downloads/view.html.php:12 +msgid "Remove this file" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:11 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:18 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:7 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:12 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:12 +msgid "Trash" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:13 +msgid "Delete this file" +msgstr "" + +#: IDF/gettexttemplates/idf/faq-api.html.php:3 +#: IDF/gettexttemplates/idf/faq-archive-format.html.php:3 +#: IDF/gettexttemplates/idf/faq.html.php:65 +msgid "Here we are, just to help you." +msgstr "" + +#: IDF/gettexttemplates/idf/faq-api.html.php:4 +#: IDF/gettexttemplates/idf/faq-archive-format.html.php:4 +#: IDF/gettexttemplates/idf/faq.html.php:66 +#: IDF/gettexttemplates/idf/gadmin/base.html.php:4 +#: IDF/gettexttemplates/idf/index.html.php:4 IDF/Views/Admin.php:77 +#: IDF/Views.php:91 +msgid "Projects" +msgstr "Projetos" + +#: IDF/gettexttemplates/idf/faq.html.php:3 +msgid "" +"

This is simple:

\n" +"
    \n" +"
  1. Write in the comments \"This is a duplicate of issue 123\" or - if you " +"are a member of the crew -\n" +"directly add the \"duplicates\" relation with the value \"123\" below the " +"comment field. Change \"123\"\n" +"with the corresponding issue number.
  2. \n" +"
  3. Change the status of the current issue to Duplicate.
  4. \n" +"
  5. Submit the changes.
  6. \n" +"
" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:11 +msgid "" +"You need to create an account on Gravatar, this takes about 5 minutes and is free." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:12 +msgid "" +"\n" +"

To embed any previously uploaded resource into your wiki page, you can " +"use the [[!ResourceName]] syntax.

\n" +"\n" +"

The rendering of the resource can then be further fine-tuned:\n" +"

    \n" +"
  • [[!ImageResource, align=right, width=200]] renders " +"\"ImageResource\" right-aligned and scale its width to 200
  • \n" +"
  • [[!TextResource, align=center, width=300, height=300]] " +"renders \"TextResource\" in a centered, 300 by 300 px iframe
  • \n" +"
  • [[!AnyResource, preview=no]] does not render a preview of " +"the resource, but only provides a download link (default for binary " +"resources)
  • \n" +"
  • [[!BinaryResource, title=Download]] renders the download " +"link of \"BinaryResource\" with an alternative title
  • \n" +"
\n" +"

\n" +"\n" +"Resources are versioned, just like wiki pages. If you update a resource, old " +"wiki pages still show the state of the resource\n" +"at the time when the wiki page was edited. If you specifically want to " +"update a resource on a page, you therefor need to update\n" +"the resource at first and then also the page where it is referenced, " +"otherwise the change won't be visible until the next regular edit. \n" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:28 +msgid "" +"

If you have to publish many files at once for a new release, it is a very " +"tedious task\n" +"to upload them one after another and enter meta information like a summary, " +"a description or additional\n" +"labels for each of them.

\n" +"

InDefero therefore supports a special archive format that is basically a " +"standard zip file which comes with\n" +"some meta information. These meta information are kept in a special manifest " +"file, which is distinctly kept from\n" +"the rest of the files in the archive that should be published.

\n" +"

Once this archive has been uploaded, InDefero reads in the meta " +"information, unpacks the other files from\n" +"the archive and creates new individual downloads for each of them.

" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:36 +#, php-format +msgid "Learn more about the archive format." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:37 +msgid "" +"The API (Application Programming Interface) is used to interact with " +"InDefero with another program. For example, this can be used to create a " +"desktop program to submit new tickets easily." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:38 +#, php-format +msgid "Learn more about the API." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:39 +#: IDF/gettexttemplates/idf/faq.html.php:45 +msgid "What are the keyboard shortcuts?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:40 +#: IDF/gettexttemplates/idf/faq.html.php:60 +msgid "How to mark an issue as duplicate?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:41 +#: IDF/gettexttemplates/idf/faq.html.php:61 +msgid "How can I display my head next to my comments?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:42 +#: IDF/gettexttemplates/idf/faq.html.php:62 +msgid "How can I embed images and other resources in my documentation pages?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:43 +#: IDF/gettexttemplates/idf/faq.html.php:63 +msgid "What is this \"Upload Archive\" functionality about?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:44 +#: IDF/gettexttemplates/idf/faq.html.php:64 +msgid "What is the API and how is it used?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:46 +msgid "Shift+h: This help page." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:47 +msgid "If you are in a project, you have the following shortcuts:" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:48 +msgid "Shift+u: Project updates." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:49 +msgid "Shift+d: Downloads." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:50 +msgid "Shift+o: Documentation." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:51 +msgid "Shift+a: Create a new issue." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:52 +msgid "Shift+i: List of open issues." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:53 +msgid "Shift+m: The issues you submitted." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:54 +msgid "Shift+w: The issues assigned to you." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:55 +msgid "Shift+s: Source." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:56 +msgid "You also have the standard access keys:" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:57 +msgid "Alt+1: Home." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:58 +msgid "Alt+2: Skip the menus." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:59 +msgid "Alt+4: Search (when available)." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:3 +msgid "Forge" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:5 +msgid "People" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:6 +msgid "Usher" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/forge/base.html.php:3 +#, fuzzy +msgid "Frontpage" +msgstr "página" + +#: IDF/gettexttemplates/idf/gadmin/forge/index.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

You can set up a custom forge page that is used as entry page for the " +"forge instead of the plain project listing. This page is then also " +"accessible via the 'Home' link in main menu bar.

\n" +"

The content of the page can use the Markdown syntax with the Extra extension.

\n" +"

Additionally, the following macros are available:
\n" +"

    \n" +"
  • {projectlist, label=..., order=(name|activity), limit=...} - Renders a project list that can optionally be filtered by label, " +"ordered by 'name' or 'activity' and / or limited to a specific number of " +"projects.
  • \n" +"
\n" +"

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:3 +#: IDF/gettexttemplates/idf/main-menu.html.php:7 +msgid "Project List" +msgstr "Lista de Projetos" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:4 +#: IDF/Views/Admin.php:110 +#, fuzzy +msgid "Project Labels" +msgstr "Lista de Projetos" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:16 +#: IDF/gettexttemplates/idf/listProjects.html.php:6 IDF/Views/Admin.php:186 +msgid "Create Project" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:6 +msgid "Change Project Details" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:3 +msgid "" +"You can select the type of repository you want. In the case of subversion, " +"you can use optionally a remote repository instead of the local one." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:4 +msgid "" +"Once you have defined the repository type, you cannot change it." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:5 +msgid "" +"\n" +"

Specify each person by its login. Each person must have already " +"registered with the given login.

\n" +"

Separate the logins with commas and/or new lines.

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:14 +msgid "" +"The form contains some errors. Please correct them to create the project." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:15 +msgid "Provide at least one owner for the project or use a template." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:15 +msgid "Instructions:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:3 +#, php-format +msgid "" +"Confirmation code to confirm the deletion of the project: \n" +"%%code%%." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:5 +msgid "" +"\n" +"Attention! Deleting a project is a one second operation\n" +"with the consequences that all the data related to the \n" +"project will be deleted.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:10 +msgid "" +"The form contains some errors. Please correct them to delete the project." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:11 +msgid "Project Statistics" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:12 +msgid "Tab" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:13 +msgid "Number" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:15 +msgid "Code reviews" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:16 +#: IDF/Views/Project.php:93 +msgid "Commits" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:18 +msgid "Documentation pages" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:19 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:20 +msgid "Delete Project" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:22 +msgid "" +"For large projects, the suppression can take a while, please be patient." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:3 +msgid "Space Usage Statistics" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:4 +msgid "Repositories:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:5 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:11 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:18 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:16 +msgid "Attachments:" +msgstr "Anexos:" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:7 +msgid "Database:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:8 +msgid "Total Forge:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:13 +msgid "" +"The form contains some errors. Please correct them to update the project." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:14 +msgid "Provide at least one owner for the project." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:15 +msgid "Update Project" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:19 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:20 +msgid "Delete this project" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:21 +msgid "You will be asked to confirm." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:3 +#: IDF/Views/Admin.php:264 +msgid "User List" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:13 +msgid "Update User" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:4 +msgid "Create User" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:3 +msgid "The form contains some errors. Please correct them to create the user." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:6 +msgid "The user password will be sent by email to the user." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/createuser-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"An account on the forge has been created for you by\n" +"the administrator %%admin%%.\n" +"\n" +"Please find here your details to access the forge:\n" +"\n" +" Address: %%url%%\n" +" Login: %%user.login%%\n" +" Password: %%password%%\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:3 +#, php-format +msgid "See not validated users." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:4 +msgid "

You have here an overview of the users registered in the forge.

" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:5 +msgid "Number of users:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:3 +msgid "" +"If you are changing the email address of the user, you\n" +"need to ensure that you are providing a valid email\n" +"address" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:6 +msgid "" +"If you give the user staff rights, the user will be\n" +"able to create new projects and update other non staff users.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:9 +msgid "The form contains some errors. Please correct them to update the user." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:10 +#: IDF/gettexttemplates/idf/register/confirmation.html.php:4 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:4 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:4 +msgid "Login:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:11 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:5 +msgid "Public Profile" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:12 +msgid "Administrative" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/base.html.php:3 +msgid "Configured servers" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/base.html.php:4 +#: IDF/Views/Admin.php:421 +msgid "Usher control" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html~.php:3 +msgid "address" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html~.php:4 +msgid "port" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:5 +msgid "No connections found." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:3 +msgid "current server status:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:4 +msgid "startup" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:5 +msgid "shutdown" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:6 +msgid "reload server configuration:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:7 +msgid "reload" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:11 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:11 +msgid "Status explanation" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:9 +msgid "active with n total open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:10 +msgid "waiting for new connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:11 +msgid "usher is being shut down, not accepting connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:12 +msgid "" +"usher is shut down, all local servers are stopped and not accepting " +"connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:3 +msgid "server name" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:4 IDF/Issue.php:99 +#: IDF/Review.php:102 +msgid "status" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:5 +msgid "action" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:6 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:6 +msgid "No monotone servers configured." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:7 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:7 +msgid "stop" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:8 +msgid "start" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:9 +msgid "kill" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:10 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:10 +msgid "active connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:12 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:12 +msgid "remote server without open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:13 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:13 +msgid "server with n open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:14 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:14 +msgid "local server running, without open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:15 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:15 +msgid "local server not running, waiting for connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:16 +msgid "local server is about to stop, n connections still open" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:17 +msgid "local server not running, not accepting connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:18 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:18 +msgid "usher is shut down, not running and not accepting connections" +msgstr "" + +#: IDF/gettexttemplates/idf/index.atom.php:3 +#, php-format +msgid "Personal project feed for %%user%%." +msgstr "" + +#: IDF/gettexttemplates/idf/index.html.php:3 +#: IDF/gettexttemplates/idf/main-menu.html.php:6 +msgid "Home" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:3 +#, php-format +msgid "Attachment to issue %%issue.id%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:5 +#: IDF/gettexttemplates/idf/review/view.html.php:35 +#: IDF/gettexttemplates/idf/source/commit.html.php:23 +#: IDF/gettexttemplates/idf/source/commit.html~.php:22 +#: IDF/gettexttemplates/idf/source/git/file.html.php:6 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:7 +msgid "Archive" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:6 +#: IDF/gettexttemplates/idf/source/git/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:12 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:12 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:10 +msgid "Download this file" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:7 +#: IDF/gettexttemplates/idf/issues/view.html.php:28 +#: IDF/gettexttemplates/idf/review/view.html.php:26 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:13 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:14 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:16 +msgid "Created:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/base.html.php:4 +msgid "All Issues" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/base.html.php:5 +msgid "My Issues" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/base.html.php:6 +msgid "My watch list" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/base.html.php:7 +#: IDF/gettexttemplates/idf/issues/by-label.html.php:6 +#: IDF/gettexttemplates/idf/issues/index.html.php:5 +#: IDF/gettexttemplates/idf/issues/project-watchlist.html.php:5 +#: IDF/gettexttemplates/idf/issues/search.html.php:8 +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:5 +msgid "New Issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/base.html.php:8 +#: IDF/gettexttemplates/idf/wiki/base.html.php:9 +msgid "Search" +msgstr "Pesquisar" + +#: IDF/gettexttemplates/idf/issues/base.html.php:9 +msgid "Back to the issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:3 +#, php-format +msgid "" +"

Open issues: %%open%%

\n" +"

Closed issues: %%closed%%

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:7 +msgid "Label:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:8 +msgid "Completion:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/create.html.php:3 +msgid "" +"

When you submit the issue do not forget to provide the following " +"information:

\n" +"
    \n" +"
  • The steps to reproduce the problem.
  • \n" +"
  • The version of the software and your operating system.
  • \n" +"
  • Any information that can help the developers to solve the issue.
  • \n" +"
  • Do not provide any password or confidential information!
  • \n" +"
" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/create.html.php:10 +msgid "The form contains some errors. Please correct them to submit the issue." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/create.html.php:11 +#: IDF/gettexttemplates/idf/issues/create.html.php:13 +#: IDF/gettexttemplates/idf/issues/view.html.php:24 +#: IDF/gettexttemplates/idf/issues/view.html.php:26 +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:5 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:5 +msgid "Preview" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/create.html.php:12 +msgid "Submit Issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/create.html.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:34 +msgid "Attach file" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/create.html.php:16 +#: IDF/gettexttemplates/idf/issues/create.html.php:17 +#: IDF/gettexttemplates/idf/issues/view.html.php:35 +#: IDF/gettexttemplates/idf/issues/view.html.php:36 +msgid "Attach another file" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:3 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:3 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:13 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:12 +#: IDF/gettexttemplates/idf/issues/view.html.php:18 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:3 +#: IDF/gettexttemplates/idf/review/view.html.php:38 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:11 +#: IDF/IssueComment.php:151 +msgid "Summary:" +msgstr "Sumário:" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:4 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:4 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:8 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:14 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:13 +#: IDF/gettexttemplates/idf/issues/view.html.php:19 +#: IDF/gettexttemplates/idf/issues/view.html.php:30 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:4 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/view.html.php:39 IDF/IssueComment.php:153 +msgid "Status:" +msgstr "Estado:" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:5 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:15 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:14 +#: IDF/gettexttemplates/idf/issues/view.html.php:20 +#: IDF/gettexttemplates/idf/issues/view.html.php:31 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:5 +#: IDF/IssueComment.php:155 +msgid "Owner:" +msgstr "Proprietário:" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:17 +#: IDF/gettexttemplates/idf/issues/view.html.php:22 IDF/IssueComment.php:159 +msgid "Relations:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/forge-watchlist.html.php:3 +#: IDF/gettexttemplates/idf/issues/index.html.php:3 +#: IDF/gettexttemplates/idf/issues/project-watchlist.html.php:3 +#, php-format +msgid "" +"

Open issues: %%open%%

\n" +"

Closed issues: %%closed%%

" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:3 +msgid "A new issue has been created and assigned to you:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:4 +msgid "A new issue has been created:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:8 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:11 +msgid "Reported by:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:12 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:19 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:17 +msgid "Issue:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:3 +msgid "The following issue you are owning has been updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:4 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:3 +msgid "The following issue has been updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:4 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:4 +#, php-format +msgid "By %%who%%, %%c.creation_dtime%%:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:10 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:9 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:12 +msgid "URL:" +msgstr "URL:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:12 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:11 +msgid "Comments (last first):" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/search.html.php:3 +#, php-format +msgid "" +"\n" +"

Found open issues: %%open%%

\n" +"

Found closed issues: %%closed" +"%%

" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/search.html.php:6 +#, php-format +msgid "" +"

Label:\n" +"%%tag.class%%:" +"%%tag.name%%

" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:3 +msgid "View all open issues." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:4 +msgid "Create an issue." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:5 +#, php-format +msgid "" +"The issue tracker is empty.
Create your " +"first issue." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:6 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:4 +#, php-format +msgid "Unresolved: By %%key%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:7 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:5 +msgid "Status Summary" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:8 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:6 +msgid "Unresolved: By Assignee" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html~.php:3 +#, php-format +msgid "" +"The issue tracker is empty.
You can create your first issue here." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:3 +#, php-format +msgid "" +"See the %%nb_submit_closed%% closed." +msgid_plural "" +"See the %%nb_submit_closed%% closed." +msgstr[0] "" +msgstr[1] "" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:4 +#, php-format +msgid "" +"See the %%nb_owner_closed%% closed." +msgid_plural "" +"See the %%nb_owner_closed%% closed." +msgstr[0] "" +msgstr[1] "" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:6 +#: IDF/gettexttemplates/idf/user/dashboard.html.php:7 +msgid "Submitted issues:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:7 +#: IDF/gettexttemplates/idf/user/dashboard.html.php:6 +msgid "Working issues:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:3 +#, php-format +msgid "Reported by %%submitter%%, %%c.creation_dtime%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:4 +#: IDF/gettexttemplates/idf/review/view.html.php:22 +#, php-format +msgid "" +"Comment %%i%% by %%submitter%%, %%c.creation_dtime%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:5 +#, php-format +msgid "Sign in to reply to this comment." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:6 +msgid "" +"This issue is marked as closed, add a comment only if you think this issue " +"is still valid and more work is needed to fully fix it." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:8 +#, php-format +msgid "%%interested%% person" +msgid_plural "%%interested%% persons" +msgstr[0] "" +msgstr[1] "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:9 +#, php-format +msgid "This issue %%verb%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:10 +msgid "Remove this issue from your watch list" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:11 +msgid "Add this issue to your watch list" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:12 +msgid "View the previous closed issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:13 +msgid "View the previous open issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:14 +msgid "View the next closed issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:15 +msgid "View the next open issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:16 +msgid "download" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:17 +msgid "view" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:23 +msgid "The form contains some errors. Please correct them to change the issue." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:25 +msgid "Submit Changes" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:32 +msgid "Followed by:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:3 +#, fuzzy, php-format +msgid "1 project" +msgid_plural "%%label.project_count%% projects" +msgstr[0] "projeto" +msgstr[1] "projeto" + +#: IDF/gettexttemplates/idf/listProjects.html.php:4 +#, php-format +msgid "Remove filter for %%tag%%" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:5 +msgid "No projects managed with InDefero were found." +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:7 +msgid "Filter projects by label" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:8 +#, fuzzy +msgid "No projects with labels found." +msgstr "Projeto \"%s\" não encontrado." + +#: IDF/gettexttemplates/idf/listProjects.html.php:9 +msgid "Order" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:10 +#, fuzzy +msgid "By name" +msgstr "nome" + +#: IDF/gettexttemplates/idf/listProjects.html.php:11 +msgid "By activity" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:12 +msgid "Filtered project stats" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:13 +msgid "Members:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:14 +msgid "Issues:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:15 +msgid "Commits:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:16 +msgid "Documentations:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:18 +msgid "Code reviews:" +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:3 +#, php-format +msgid "" +"You can create an account if you don't have one yet." +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:4 +msgid "What is your account information?" +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:5 +msgid "My login is" +msgstr "Meu usuário é" + +#: IDF/gettexttemplates/idf/login_form.html.php:6 +msgid "My password is" +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:7 +msgid "Sign in" +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:8 +msgid "I lost my password!" +msgstr "Perdi minha senha!" + +#: IDF/gettexttemplates/idf/login_form.html.php:9 +msgid "Welcome." +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:10 +msgid "It takes less than a minute to create your account." +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:3 +#, php-format +msgid "" +"Welcome, %%user%%." +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:4 +msgid "Sign Out" +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:5 +msgid "Sign in or create your account" +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:10 IDF/Views/Admin.php:40 +msgid "Forge Management" +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:11 +msgid "Help and accessibility features" +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:12 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:14 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:14 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:15 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:13 +msgid "Help" +msgstr "Ajuda" + +#: IDF/gettexttemplates/idf/project/home.html.php:3 +#: IDF/gettexttemplates/idf/project/timeline.html.php:4 IDF/Views.php:46 +msgid "Welcome" +msgstr "" + +#: IDF/gettexttemplates/idf/project/home.html.php:4 +#: IDF/gettexttemplates/idf/project/timeline.html.php:5 +msgid "Latest Updates" +msgstr "Últimas Atualizações" + +#: IDF/gettexttemplates/idf/project/home.html.php:5 +msgid "Featured Downloads" +msgstr "" + +#: IDF/gettexttemplates/idf/project/home.html.php:6 +msgid "Show more featured downloads" +msgstr "" + +#: IDF/gettexttemplates/idf/project/home.html.php:7 +#: IDF/gettexttemplates/idf/project/home.html.php:10 +msgid "show more..." +msgstr "" + +#: IDF/gettexttemplates/idf/project/home.html.php:8 +msgid "Featured Documentation" +msgstr "" + +#: IDF/gettexttemplates/idf/project/home.html.php:9 +msgid "Show more featured documentation" +msgstr "" + +#: IDF/gettexttemplates/idf/project/home.html.php:11 +msgid "Development Team" +msgstr "" + +#: IDF/gettexttemplates/idf/project/home.html.php:12 +msgid "Admins" +msgstr "Administradores" + +#: IDF/gettexttemplates/idf/project/home.html.php:13 +msgid "Happy Crew" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:3 +msgid "Latest updates" +msgstr "Últimas atualizações" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:6 +#: IDF/Views/Project.php:90 +msgid "All Updates" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:7 +msgid "Filter by type" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:8 +msgid "Subscribe to this timeline" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:9 +msgid "RSS" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:10 +msgid "Atom feed" +msgstr "" + +#: IDF/gettexttemplates/idf/project-list.html.php:3 +msgid "Project activity: %%activity%%%" +msgstr "" + +#: IDF/gettexttemplates/idf/project-list.html.php:9 +msgid "n/a" +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation-email.txt.php:3 +#, php-format +msgid "" +"Hello,\n" +"\n" +"You have requested the creation of an account to\n" +"participate in the life of a software project.\n" +"\n" +"To confirm the account please follow this link:\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following confirmation key:\n" +"\n" +"%%key%%\n" +"\n" +"If you are not interested any longer in taking\n" +"part in the life of the software project or if\n" +"you can't remember having requested the creation\n" +"of an account, please excuse us and simply ignore\n" +"this email. \n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:3 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:3 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:3 +msgid "Oops, please check the form for errors." +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:5 +msgid "Email:" +msgstr "E-mail:" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:6 +msgid "Enable Your Account" +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:8 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:8 +msgid "" +"This is the last step, but just be sure to have the cookies enabled to log in afterwards." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:3 +msgid "" +"Read the terms and conditions – " +"basically \"Please be nice, we respect you\"." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:4 +#, php-format +msgid "" +"If you have just forgotten your login information, then there is no need to " +"create a new account. You can just recover your login " +"name and password." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:5 +#, php-format +msgid "" +"With your account, you will able to participate in the life of all the " +"projects hosted here. Participating in a software project must be fun, so if " +"you have troubles, you can let us know about your issues " +"at anytime!" +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:6 +msgid "Oops, please check the provided login and email address to register." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:7 IDF/Views.php:137 +msgid "Create Your Account" +msgstr "Crie sua conta" + +#: IDF/gettexttemplates/idf/register/index.html.php:9 +msgid "" +"Be sure to provide a valid email address, as we are sending a validation " +"link by email." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:10 +msgid "Did you know?" +msgstr "" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:3 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:3 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:3 +msgid "Oops, we found an error in the form." +msgstr "" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:4 +msgid "Confirm Your Account" +msgstr "" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:7 +msgid "" +"Use your email software to read your emails and open your confirmation " +"email. Either click directly on the confirmation link or copy/paste the " +"confirmation key in the box and submit the form." +msgstr "" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:8 +msgid "" +"Just after providing the confirmation key, you will be able to set your " +"password and start using this website fully." +msgstr "" + +#: IDF/gettexttemplates/idf/review/base-full.html.php:3 +#: IDF/gettexttemplates/idf/review/base.html.php:3 +msgid "Open Reviews" +msgstr "" + +#: IDF/gettexttemplates/idf/review/base.html.php:4 +#: IDF/gettexttemplates/idf/review/create.html.php:11 +#: IDF/gettexttemplates/idf/review/index.html.php:3 IDF/Views/Review.php:83 +msgid "Start Code Review" +msgstr "" + +#: IDF/gettexttemplates/idf/review/create.html.php:3 +msgid "" +"

To start a code review, you need to provide:

\n" +"
    \n" +"
  • A commit or revision of the current code in the repository from which " +"you started your work.
  • \n" +"
  • A patch describing your changes with respect to the reference commit.\n" +"
  • Check your patch does not provide any password or confidential " +"information!
  • \n" +"
" +msgstr "" + +#: IDF/gettexttemplates/idf/review/create.html.php:9 +msgid "" +"The form contains some errors. Please correct them to submit the code review." +msgstr "" + +#: IDF/gettexttemplates/idf/review/create.html.php:10 +msgid "" +"Select the commit against which you created your patch to be sure it applies " +"correctly." +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:3 +msgid "The following review has been created:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:16 +msgid "Review:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:3 +msgid "The following review has been updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:5 +#, php-format +msgid "" +"By %%who%%, %%c.creation_dtime%%, on file:\n" +"%%c.cfile%%\n" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:14 +msgid "General comments (last first):" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:15 +msgid "Detailed file comments (last first):" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:3 +msgid "" +"Code review is a process in which\n" +"after or before changes are commited into the code repository,\n" +"different people discuss the code changes. The goal is\n" +"to improve the quality of the code and the\n" +"contributions, as such, you must be pragmatic when writing\n" +"your review. Correctly mention the line numbers (in the old or in the\n" +"new file) and try to keep a good balance between seriousness and fun.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:11 +msgid "" +"\n" +"Proposing code for review is intimidating, you know\n" +"you will receive critics, so please, as a reviewer, keep this\n" +"process fun, use it to help your contributor learn your\n" +"coding standards and the structure of the code and make them want\n" +"to propose more contributions.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:18 +#: IDF/gettexttemplates/idf/source/commit.html.php:3 +#: IDF/gettexttemplates/idf/source/commit.html~.php:3 +#, php-format +msgid "%%ndiff%% diff" +msgid_plural "%%ndiff%% diffs" +msgstr[0] "" +msgstr[1] "" + +#: IDF/gettexttemplates/idf/review/view.html.php:19 +#, php-format +msgid "%%nc%% comment" +msgid_plural "%%nc%% comments" +msgstr[0] "" +msgstr[1] "" + +#: IDF/gettexttemplates/idf/review/view.html.php:20 +#, php-format +msgid "" +"Comment %%i%% by %%who%%, " +"%%c.creation_dtime%%" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:21 +#, php-format +msgid "Your comments on the changes in file %%file%%:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:23 +#, php-format +msgid "Sign in to participate in the review." +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:24 +msgid "" +"The form contains some errors. Please correct them to submit your review." +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:25 +msgid "How to Participate in a Code Review" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:28 +#: IDF/gettexttemplates/idf/source/commit.html.php:5 +#: IDF/gettexttemplates/idf/source/commit.html~.php:5 +msgid "Author:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:29 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/source/commit.html.php:7 +#: IDF/gettexttemplates/idf/source/commit.html~.php:7 +msgid "Commit:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:30 +#: IDF/gettexttemplates/idf/source/commit.html.php:8 +#: IDF/gettexttemplates/idf/source/commit.html~.php:8 +msgid "View corresponding source tree" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:32 +msgid "Reviewers:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:33 +msgid "No reviewers at the moment." +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:34 +msgid "Files:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:36 +#: IDF/gettexttemplates/idf/source/commit.html.php:24 +#: IDF/gettexttemplates/idf/source/commit.html~.php:23 +msgid "Download the corresponding diff file" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:37 +msgid "General Comments" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:40 +msgid "Submit Code Review" +msgstr "" + +#: IDF/gettexttemplates/idf/source/base.html.php:3 +msgid "Source Tree" +msgstr "" + +#: IDF/gettexttemplates/idf/source/base.html.php:4 +msgid "Change Log" +msgstr "" + +#: IDF/gettexttemplates/idf/source/base.html.php:6 +msgid "How To Get The Code" +msgstr "" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:3 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:8 +#: IDF/Views/Project.php:190 +msgid "Age" +msgstr "" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:4 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:10 +msgid "Message" +msgstr "" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:5 +msgid "Parent:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:6 +#: IDF/gettexttemplates/idf/source/commit.html.php:10 +#: IDF/gettexttemplates/idf/source/commit.html~.php:10 +msgid "View corresponding commit" +msgstr "" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:8 +msgid "by" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:3 +msgid "A new commit has been created:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:8 +msgid "Created by:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:8 +msgid "Created at:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:8 +msgid "Content:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:10 +msgid "Commit details:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:4 +#: IDF/gettexttemplates/idf/source/commit.html~.php:4 +msgid "Date:" +msgstr "Data:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:6 +#: IDF/gettexttemplates/idf/source/commit.html~.php:6 +msgid "Branch:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:9 +#: IDF/gettexttemplates/idf/source/commit.html~.php:9 +msgid "Parents:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:11 +#: IDF/gettexttemplates/idf/source/commit.html~.php:11 +msgid "Message:" +msgstr "Mensagem:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:12 +#: IDF/gettexttemplates/idf/source/commit.html~.php:12 +#: IDF/gettexttemplates/idf/wiki/feedfragment-page.xml.php:3 +#: IDF/gettexttemplates/idf/wiki/feedfragment-resource.xml.php:3 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:10 +msgid "Changes:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:13 +#: IDF/gettexttemplates/idf/source/commit.html~.php:13 +msgid "deleted" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:14 +#: IDF/gettexttemplates/idf/source/commit.html.php:18 +#: IDF/gettexttemplates/idf/source/commit.html~.php:14 +#: IDF/gettexttemplates/idf/source/commit.html~.php:17 +msgid "full" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:15 +#: IDF/gettexttemplates/idf/source/commit.html~.php:15 +msgid "renamed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:16 +msgid "copied" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:17 +#: IDF/gettexttemplates/idf/source/commit.html~.php:16 +msgid "added" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:19 +#: IDF/gettexttemplates/idf/source/commit.html~.php:18 +msgid "modified" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:20 +msgid "properties changed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:21 +#: IDF/gettexttemplates/idf/source/commit.html~.php:20 +msgid "removed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:22 +#: IDF/gettexttemplates/idf/source/commit.html~.php:21 +msgid "File differences" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html~.php:19 +msgid "properies changed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:3 +#, php-format +msgid "" +"The revision identifier %%commit%% is ambiguous and can be\n" +"expanded to multiple valid revisions - please choose one:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:5 +msgid "Title" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:6 +msgid "Author" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:7 +msgid "Date" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:8 +msgid "Branch" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:9 +msgid "Revision" +msgstr "" + +#: IDF/gettexttemplates/idf/source/feedfragment.xml.php:3 +#, php-format +msgid "%%cproject.name%%: Commit %%c.scm_id%%" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:3 +msgid "Branches" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:4 +msgid "filter branches" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:5 +msgid "Tags" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:6 +msgid "filter tags" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/file.html.php:3 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:4 +#, php-format +msgid "" +"Source at commit %%commit%% created " +"%%cobject.date%%." +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/file.html.php:4 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:5 +#, php-format +msgid "By %%cobject.author%%, %%cobject.title%%" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/file.html.php:5 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:6 +msgid "Root" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the git software to manage the source\n" +"code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:6 +#, php-format +msgid "" +"You may need to provide your SSH key. The " +"synchronization of your SSH key can take a couple of minutes. You can learn " +"more about SSH key authentication." +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:6 +msgid "To make a first commit in the repository, perform the following steps:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:8 +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:7 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:7 +#, php-format +msgid "Find here more details on how to access %%project%% source code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:9 +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:8 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:8 +msgid "Command-Line Access" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:10 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:9 +msgid "First Commit" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:11 +#: IDF/Views/Download.php:66 IDF/Views/Download.php:348 +msgid "Size" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:12 +msgid ":" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:13 +msgid "Download this version" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:13 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:13 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:14 +msgid "or" +msgstr "" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:3 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:3 +#, php-format +msgid "" +"The branch or revision %%commit%% is not valid or does not exist\n" +"in this repository." +msgstr "" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:5 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:5 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:5 +msgid "The following list shows all available branches:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:6 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:6 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:6 +#, php-format +msgid "" +"If this is a new repository, the reason for this error\n" +"could be that you have not committed and / or pushed any change so far.\n" +"In this case please take a look at the Help page\n" +"how to access your repository." +msgstr "" + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the Mercurial software to manage the source\n" +"code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:6 +#, php-format +msgid "" +"To get write access to the repository, you need to use your username and " +"your extra password." +msgstr "" + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:9 +msgid "Write Access Authentication" +msgstr "" + +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:3 +#, php-format +msgid "Property %%prop%% set to %%val%%" +msgstr "" + +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the monotone software to manage the source\n" +"code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/changelog.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/commit.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/commit.html~.php:3 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:14 +msgid "Revision:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/changelog.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/commit.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/commit.html~.php:4 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:10 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:15 +msgid "Switch" +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the subversion software to manage the source\n" +"code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:3 +#, php-format +msgid "" +"The revision %%commit%% is not valid or does not exist\n" +"in this repository." +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:9 +msgid "Rev" +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:16 +msgid "Branches:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:17 +msgid "Tags:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/changeemail-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"To confirm that you want %%email%%\n" +"to be your new email address, just follow this link:\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following verification key:\n" +"\n" +"%%key%%\n" +"\n" +"If you do not want to change your email address, \n" +"just ignore this message.\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/user/changeemail.html.php:4 +msgid "Confirm Your New Email Address" +msgstr "" + +#: IDF/gettexttemplates/idf/user/changeemail.html.php:7 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:7 +msgid "" +"Use your email software to read your emails and open your verification " +"email. Either click directly on the verification link or copy/paste the " +"verification key in the box and submit the form." +msgstr "" + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:3 +#, php-format +msgid "Update your account." +msgstr "" + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:4 +#, php-format +msgid "See your public profile." +msgstr "" + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:5 +#, php-format +msgid "See your forge issue watch list." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:6 +msgid "Key Management" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:7 +msgid "Secondary Emails" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:8 +msgid "Extra password" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:9 +msgid "" +"This password is used to access some of the external systems managed by our " +"infrastructure. It will be regenerated if you change your password." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:10 +msgid "API key" +msgstr "chave API" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:11 +msgid "" +"Your API key will be regenerated automatically if you change your password." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:12 +msgid "Update Your Account" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:14 +msgid "Your Current Public Keys" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:15 +msgid "Delete this key" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:16 +msgid "Your additional email addresses" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:17 +msgid "Delete this address" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:18 +msgid "" +"If possible, use your real name. By using your real name, people will have " +"more trust in your comments and remarks." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:19 +msgid "" +"The extra password is used to access some of the external systems and the " +"API key is used to interact with this website using a program." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:20 +msgid "Show API key and extra password" +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:3 +msgid "" +"Oops, please check the provided login or email address to recover your " +"password." +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:4 +msgid "Recover My Password" +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:6 +msgid "" +"Provide either your login or email address, if a corresponding user is found " +"in the database, we will send you an email with the details on how to reset " +"your password." +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"You lost your password and wanted to recover it.\n" +"To provide a new password for your account, you\n" +"just have to follow the provided link. You will\n" +"get a simple form to provide a new password.\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following verification key:\n" +"\n" +"%%key%%\n" +"\n" +"If you are not the one who requested to reset\n" +"your password, simply ignore this email, your\n" +"password will not be changed.\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:4 +msgid "Recover Your Password" +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:8 +msgid "" +"Just after providing the confirmation key, you will be able to reset your " +"password and use this website fully." +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:6 +msgid "Reset Your Password" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:3 +#, php-format +msgid "You are looking at the public profile of %%member%%." +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:5 +msgid "Twitter:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:6 +msgid "Public Email:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:7 +msgid "Website:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:8 +msgid "Last time seen:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:9 +msgid "Member since:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:3 +msgid "List Pages" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:4 +msgid "List Resources" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:5 +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:4 +#: IDF/gettexttemplates/idf/wiki/search.html.php:3 IDF/Views/Wiki.php:211 +msgid "New Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:6 +#: IDF/gettexttemplates/idf/wiki/listResources.html.php:3 +#: IDF/Views/Wiki.php:256 +msgid "New Resource" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:7 +msgid "Update This Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:8 +msgid "Update This Resource" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:3 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:3 +msgid "Preview of the Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:7 +msgid "The form contains some errors. Please correct them to create the page." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:6 +msgid "Create Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:3 +msgid "" +"\n" +"Wiki resources are later addressed in wiki pages by their title, so ensure " +"that you\n" +"give your resource a unique and an easy to remember name.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:8 +#, fuzzy +msgid "Create Resource" +msgstr "Crie sua conta" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:3 +msgid "" +"If you delete this documentation page, it will be removed from the database " +"with all the associated revisions and you will not be able to " +"recover it." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:6 +msgid "Delete Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:14 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:15 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:15 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:17 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:18 +msgid "Old Revisions" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:3 +#, php-format +msgid "" +"You are looking at an old revision (%%oldrev.summary%%) of the " +"page \n" +"%%page.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:5 +msgid "" +"If you delete this old revision, it will be removed from the database and " +"you will not be able to recover it." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:8 +msgid "Delete Revision" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:3 +msgid "" +"If you delete this documentation resource, it will be removed from the " +"database with all the associated revisions \n" +"and you will not be able to recover it. Any documentation " +"pages that reference this resource,\n" +"will no longer be able to render it, but won't be deleted." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:8 +msgid "Delete Resource" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:10 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:8 +#, fuzzy +msgid "File size" +msgstr "tamanho do arquivo" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:9 +#: IDF/Views/Wiki.php:101 +#, fuzzy +msgid "MIME type" +msgstr "tipo" + +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:3 +#, php-format +msgid "" +"You are looking at an old revision (%%oldrev.summary%%) of the " +"resource \n" +"%%resource.title%%. This revision was created by " +"%%submitter%%." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/edit-info.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

The content of the page can use the Markdown syntax with the Extra extension.

\n" +"

Website addresses are automatically linked and you can link to another " +"page in the documentation using double square brackets like that " +"[[AnotherPage]].

\n" +"

If you want to embed uploaded resources, use the [[!ResourceName]] syntax for that. This is described more in detail in the FAQ.

\n" +"

To directly include a file content from the repository, embrace its path " +"with triple square brackets: [[[my/file.txt]]].

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/feedfragment-resource.xml.php:4 +msgid "Initial creation" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:3 +#, php-format +msgid "See the deprecated pages." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:5 +msgid "Number of pages:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/listResources.html.php:4 +msgid "Number of resources:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/search.html.php:4 +msgid "Pages found:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:3 +msgid "The form contains some errors. Please correct them to update the page." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:6 +msgid "Update Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:10 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:11 +msgid "Delete this page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:4 +msgid "Update Resource" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:8 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:9 +msgid "Delete this resource" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:3 +msgid "" +"Attention! This page is marked as deprecated, \n" +"use it as reference only if you are sure you need these specific information." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:5 +#, php-format +msgid "" +"You are looking at an old revision of the page \n" +"%%page.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:10 +msgid "Table of Content" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:13 +msgid "Delete this revision" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:3 +#, php-format +msgid "" +"You are looking at an old revision of the resource \n" +"%%resource.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:14 +msgid "Page Usage" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:15 +msgid "This resource is not used on any pages yet." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:3 +msgid "A new documentation page has been created:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:14 +msgid "Documentation page:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:3 +msgid "The following documentation page has been updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:7 +msgid "Updated by:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:13 +msgid "New content:" +msgstr "" + +#: IDF/Issue.php:76 +msgid "owner" +msgstr "proprietário" + +#: IDF/Issue.php:84 IDF/Wiki/Page.php:86 +msgid "interested users" +msgstr "" + +#: IDF/Issue.php:85 +msgid "" +"Interested users will get an email notification when the issue is changed." +msgstr "" + +#: IDF/Issue.php:92 IDF/Project.php:94 IDF/Review.php:95 IDF/Upload.php:99 +#: IDF/Wiki/Page.php:94 +msgid "labels" +msgstr "" + +#: IDF/Issue.php:111 IDF/IssueFile.php:102 IDF/Review.php:114 +#: IDF/Upload.php:118 IDF/Wiki/Page.php:106 IDF/Wiki/Resource.php:101 +msgid "modification date" +msgstr "data de modificação" + +#: IDF/Issue.php:212 IDF/IssueComment.php:143 +#, php-format +msgid "" +"Issue %3$d, %4$s" +msgstr "" + +#: IDF/Issue.php:214 +#, fuzzy, php-format +msgid "Creation of issue %3$d, by %4$s" +msgstr "Comentário sobre problema %d, por %s" + +#: IDF/Issue.php:224 +#, php-format +msgid "%1$s: Issue %2$d created - %3$s" +msgstr "" + +#: IDF/Issue.php:307 +#, php-format +msgid "Issue %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Issue.php:311 +#, php-format +msgid "Updated Issue %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/IssueComment.php:51 IDF/IssueRelation.php:47 +msgid "issue" +msgstr "" + +#: IDF/IssueComment.php:58 IDF/IssueFile.php:49 IDF/Review/Comment.php:62 +#: IDF/Review/FileComment.php:49 IDF/Review/FileComment.php:69 +msgid "comment" +msgstr "comentário" + +#: IDF/IssueComment.php:72 IDF/Review/Comment.php:75 IDF/Upload.php:63 +#: IDF/Wiki/PageRevision.php:85 +msgid "changes" +msgstr "alterações" + +#: IDF/IssueComment.php:73 +msgid "Serialized array of the changes in the issue." +msgstr "" + +#: IDF/IssueComment.php:180 +#, fuzzy, php-format +msgid "Comment on issue %3$d, by %4$s" +msgstr "Comentário sobre problema %d, por %s" + +#: IDF/IssueComment.php:191 +#, fuzzy, php-format +msgid "%1$s: Comment on issue %2$d - %3$s" +msgstr "%s: Comenta sobre problema %d - %s" + +#: IDF/IssueFile.php:64 +msgid "file name" +msgstr "nome do arquivo" + +#: IDF/IssueFile.php:70 +msgid "the file" +msgstr "o arquivo" + +#: IDF/IssueFile.php:76 +msgid "file size" +msgstr "tamanho do arquivo" + +#: IDF/IssueFile.php:84 +msgid "type" +msgstr "tipo" + +#: IDF/IssueFile.php:86 +msgid "Image" +msgstr "Imagem" + +#: IDF/IssueFile.php:87 +msgid "Other" +msgstr "Outro" + +#: IDF/IssueRelation.php:54 +msgid "verb" +msgstr "" + +#: IDF/IssueRelation.php:61 +msgid "other issue" +msgstr "" + +#: IDF/Key.php:55 +msgid "public key" +msgstr "" + +#: IDF/Key.php:90 +msgid "Invalid or unknown key data detected." +msgstr "" + +#: IDF/Plugin/SyncMercurial.php:78 IDF/Plugin/SyncSvn.php:81 +#, php-format +msgid "The repository %s already exists." +msgstr "" + +#: IDF/Plugin/SyncMercurial.php:142 +#, php-format +msgid "%s does not exist or is not writable." +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:107 IDF/Plugin/SyncMonotone.php:492 +msgid "\"mtn_repositories\" must be defined in your configuration file" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:114 IDF/Plugin/SyncMonotone.php:482 +msgid "\"mtn_usher_conf\" does not exist or is not writable" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:121 +#, php-format +msgid "Could not find mtn-post-push script \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:155 +#, php-format +msgid "The configuration file \"%s\" is missing" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:164 +#, php-format +msgid "The project path \"%s\" already exists" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:170 +#, php-format +msgid "The project path \"%s\" could not be created" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:208 +#, php-format +msgid "The key directory \"%s\" could not be created" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:227 +#, php-format +msgid "Could not parse key information: %s" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:265 +#, php-format +msgid "Could not create configuration directory \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:275 +#, php-format +msgid "Could not create symlink for configuration file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:293 +#, php-format +msgid "Could not write configuration file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:309 IDF/Plugin/SyncMonotone.php:525 +#, php-format +msgid "Could not parse usher configuration in \"%1$s\": %2$s" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:320 +#, php-format +msgid "usher configuration already contains a server entry named \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:345 IDF/Plugin/SyncMonotone.php:546 +#, php-format +msgid "Could not write usher configuration file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:395 +#, php-format +msgid "Could not write write-permissions file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:420 +#, php-format +msgid "Could not write read-permissions file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:438 +#, php-format +msgid "Could not remove symlink \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:446 +#, php-format +msgid "Could not create symlink \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:500 +#, php-format +msgid "One or more paths underneath %s could not be deleted" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:512 +#, php-format +msgid "Could not delete client private key \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:599 IDF/Plugin/SyncMonotone.php:718 +#, php-format +msgid "Could not parse read-permissions for project \"%1$s\": %2$s" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:643 IDF/Plugin/SyncMonotone.php:741 +#, php-format +msgid "Could not write read-permissions for project \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:657 IDF/Plugin/SyncMonotone.php:760 +#, php-format +msgid "Could not write write-permissions file for project \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:813 +msgid "\"mtn_repositories\" must be defined in your configuration file." +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:820 +#, php-format +msgid "The project path %s does not exists." +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:838 +#, php-format +msgid "The command \"%s\" could not be executed." +msgstr "" + +#: IDF/Project.php:62 IDF/Tag.php:66 +msgid "name" +msgstr "nome" + +#: IDF/Project.php:69 +msgid "short name" +msgstr "abreviatura" + +#: IDF/Project.php:70 +msgid "" +"Used in the URL to access the project, must be short with only letters and " +"numbers." +msgstr "" + +#: IDF/Project.php:78 +msgid "short description" +msgstr "descrição curta" + +#: IDF/Project.php:86 IDF/Review/Patch.php:74 +msgid "description" +msgstr "descrição" + +#: IDF/Project.php:87 +msgid "The description can be extended using the Markdown syntax." +msgstr "" + +#: IDF/Project.php:100 +msgid "private" +msgstr "privado" + +#: IDF/Project.php:108 +msgid "current project activity" +msgstr "" + +#: IDF/Project.php:159 +#, php-format +msgid "Project \"%s\" not found." +msgstr "Projeto \"%s\" não encontrado." + +#: IDF/ProjectActivity.php:56 +msgid "date" +msgstr "" + +#: IDF/Review/Comment.php:55 IDF/Review/Patch.php:80 +msgid "patch" +msgstr "" + +#: IDF/Review/Comment.php:83 +msgid "vote" +msgstr "" + +#: IDF/Review/Comment.php:139 IDF/Review/Patch.php:151 +#, php-format +msgid "" +"Review %3$d, %4$s" +msgstr "" + +#: IDF/Review/Comment.php:141 +#, fuzzy, php-format +msgid "Update of review %3$d, by %4$s" +msgstr "Comentário sobre problema %d, por %s" + +#: IDF/Review/Comment.php:151 +#, php-format +msgid "%1$s: Updated review %2$d - %3$s" +msgstr "" + +#: IDF/Review/Comment.php:222 +#, php-format +msgid "Updated Code Review %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Review/Patch.php:52 +msgid "review" +msgstr "" + +#: IDF/Review/Patch.php:67 +msgid "commit" +msgstr "" + +#: IDF/Review/Patch.php:153 +#, fuzzy, php-format +msgid "Creation of review %3$d, by %4$s" +msgstr "Comentário sobre problema %d, por %s" + +#: IDF/Review/Patch.php:163 +#, fuzzy, php-format +msgid "%1$s: Creation of Review %2$d - %3$s" +msgstr "%s: Comenta sobre problema %d - %s" + +#: IDF/Review/Patch.php:208 +#, php-format +msgid "New Code Review %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Scm/Git.php:309 IDF/Scm/Mercurial.php:199 +#, php-format +msgid "Folder %1$s not found in commit %2$s." +msgstr "" + +#: IDF/Scm/Git.php:433 IDF/Scm/Mercurial.php:216 +#, php-format +msgid "Not a valid tree: %s." +msgstr "" + +#: IDF/Scm/Monotone/Stdio.php:81 +msgid "Monotone client key name or hash not in project conf." +msgstr "" + +#: IDF/Scm/Monotone/Stdio.php:89 +#, php-format +msgid "The key directory %s could not be created." +msgstr "" + +#: IDF/Scm/Monotone/Stdio.php:100 +#, php-format +msgid "Could not write client key \"%s\"" +msgstr "" + +#: IDF/Search/Occ.php:33 +msgid "occurrence" +msgstr "" + +#: IDF/Search/Occ.php:49 +msgid "word" +msgstr "" + +#: IDF/Search/Occ.php:75 +msgid "occurrences" +msgstr "" + +#: IDF/Search/Occ.php:81 +msgid "ponderated occurrence" +msgstr "" + +#: IDF/Tag.php:59 +msgid "tag class" +msgstr "" + +#: IDF/Tag.php:60 +msgid "The class of the tag." +msgstr "" + +#: IDF/Tag.php:73 +msgid "lcname" +msgstr "" + +#: IDF/Tag.php:74 +msgid "Lower case version of the name for fast searching." +msgstr "" + +#: IDF/Template/Markdown.php:84 +msgid "Create this documentation page" +msgstr "" + +#: IDF/Template/Markdown.php:97 +msgid "You are not allowed to access the wiki." +msgstr "" + +#: IDF/Template/Markdown.php:106 +msgid "The wiki resource has not been found." +msgstr "" + +#: IDF/Template/Markdown.php:113 +msgid "The wiki resource has not been found. Create it!" +msgstr "" + +#: IDF/Template/Markdown.php:146 +msgid "This revision of the resource is no longer available." +msgstr "" + +#: IDF/Template/ShowUser.php:51 +msgid "Anonymous" +msgstr "" + +#: IDF/Template/ShowUser.php:54 +msgid "Me" +msgstr "" + +#: IDF/Timeline/Paginator.php:49 +msgid "Today" +msgstr "" + +#: IDF/Upload.php:70 +msgid "file" +msgstr "arquivo" + +#: IDF/Upload.php:71 +msgid "The path is relative to the upload path." +msgstr "" + +#: IDF/Upload.php:78 IDF/Wiki/ResourceRevision.php:71 +msgid "file size in bytes" +msgstr "tamanho do arquivo em bytes" + +#: IDF/Upload.php:84 +msgid "MD5" +msgstr "" + +#: IDF/Upload.php:106 +msgid "number of downloads" +msgstr "número de downloads" + +#: IDF/Upload.php:201 +#, php-format +msgid "Download %2$d, %3$s" +msgstr "" + +#: IDF/Upload.php:204 +#, fuzzy, php-format +msgid "Addition of download %2$d, by %3$s" +msgstr "Criação da página %s, por %s" + +#: IDF/Upload.php:214 +#, fuzzy, php-format +msgid "%1$s: Download %2$d added - %3$s" +msgstr "%s: Página de documentação %s adicionada - %s" + +#: IDF/Upload.php:301 +#, php-format +msgid "New download - %1$s (%2$s)" +msgstr "" + +#: IDF/Upload.php:305 +#, php-format +msgid "Updated download - %1$s (%2$s)" +msgstr "" + +#: IDF/Views/Admin.php:47 +msgid "The forge configuration has been saved." +msgstr "" + +#: IDF/Views/Admin.php:80 +msgid "This table shows the projects in the forge." +msgstr "" + +#: IDF/Views/Admin.php:85 +msgid "Short Name" +msgstr "" + +#: IDF/Views/Admin.php:87 +msgid "Repository Size" +msgstr "" + +#: IDF/Views/Admin.php:93 +msgid "No projects were found." +msgstr "" + +#: IDF/Views/Admin.php:116 +msgid "The label configuration has been saved." +msgstr "" + +#: IDF/Views/Admin.php:147 IDF/Views/Admin.php:314 IDF/Views/Wiki.php:484 +#: IDF/Views/Wiki.php:536 +#, php-format +msgid "Update %s" +msgstr "" + +#: IDF/Views/Admin.php:155 IDF/Views/Project.php:304 +msgid "The project has been updated." +msgstr "" + +#: IDF/Views/Admin.php:192 +msgid "The project has been created." +msgstr "" + +#: IDF/Views/Admin.php:223 +#, php-format +msgid "Delete %s Project" +msgstr "" + +#: IDF/Views/Admin.php:230 +msgid "The project has been deleted." +msgstr "" + +#: IDF/Views/Admin.php:260 +msgid "Not Validated User List" +msgstr "" + +#: IDF/Views/Admin.php:268 +msgid "This table shows the users in the forge." +msgstr "" + +#: IDF/Views/Admin.php:272 +msgid "login" +msgstr "" + +#: IDF/Views/Admin.php:275 +msgid "Admin" +msgstr "" + +#: IDF/Views/Admin.php:277 +msgid "Last Login" +msgstr "" + +#: IDF/Views/Admin.php:284 +msgid "No users were found." +msgstr "" + +#: IDF/Views/Admin.php:321 +msgid "You do not have the rights to update this user." +msgstr "" + +#: IDF/Views/Admin.php:339 +msgid "The user has been updated." +msgstr "" + +#: IDF/Views/Admin.php:372 +#, php-format +msgid "The user %s has been created." +msgstr "" + +#: IDF/Views/Admin.php:379 +msgid "Add User" +msgstr "" + +#: IDF/Views/Admin.php:395 +msgid "Usher management" +msgstr "" + +#: IDF/Views/Admin.php:432 +msgid "Usher configuration has been reloaded" +msgstr "" + +#: IDF/Views/Admin.php:436 +msgid "Usher has been shut down" +msgstr "" + +#: IDF/Views/Admin.php:441 +msgid "Usher has been started up" +msgstr "" + +#: IDF/Views/Admin.php:479 +#, php-format +msgid "The server \"%s\" has been started" +msgstr "" + +#: IDF/Views/Admin.php:483 +#, php-format +msgid "The server \"%s\" has been stopped" +msgstr "" + +#: IDF/Views/Admin.php:488 +#, php-format +msgid "The server \"%s\" has been killed" +msgstr "" + +#: IDF/Views/Admin.php:508 +#, php-format +msgid "Open connections for \"%s\"" +msgstr "" + +#: IDF/Views/Admin.php:513 +#, php-format +msgid "no connections for server \"%s\"" +msgstr "" + +#: IDF/Views/Admin.php:534 +msgid "Yes" +msgstr "Sim" + +#: IDF/Views/Admin.php:534 +msgid "No" +msgstr "" + +#: IDF/Views/Download.php:45 +#, php-format +msgid "%s Downloads" +msgstr "" + +#: IDF/Views/Download.php:51 +msgid "This table shows the files to download." +msgstr "" + +#: IDF/Views/Download.php:67 IDF/Views/Download.php:349 +msgid "Uploaded" +msgstr "" + +#: IDF/Views/Download.php:71 IDF/Views/Download.php:353 +msgid "No downloads were found." +msgstr "" + +#: IDF/Views/Download.php:94 +#, php-format +msgid "Download %s" +msgstr "" + +#: IDF/Views/Download.php:111 +#, php-format +msgid "The file %2$s has been updated." +msgstr "" + +#: IDF/Views/Download.php:144 +#, php-format +msgid "Delete Download %s" +msgstr "" + +#: IDF/Views/Download.php:177 +msgid "The file has been deleted." +msgstr "" + +#: IDF/Views/Download.php:244 +#, php-format +msgid "The file has been uploaded." +msgstr "" + +#: IDF/Views/Download.php:271 +msgid "New Downloads from Archive" +msgstr "" + +#: IDF/Views/Download.php:278 +msgid "The archive has been uploaded and processed." +msgstr "" + +#: IDF/Views/Download.php:331 +#, php-format +msgid "%1$s Downloads with Label %2$s" +msgstr "" + +#: IDF/Views/Download.php:341 +#, php-format +msgid "This table shows the downloads with label %s." +msgstr "" + +#: IDF/Views/Issue.php:41 +#, php-format +msgid "%s Open Issues" +msgstr "" + +#: IDF/Views/Issue.php:51 IDF/Views/Issue.php:382 IDF/Views/User.php:75 +msgid "This table shows the open issues." +msgstr "" + +#: IDF/Views/Issue.php:61 IDF/Views/Issue.php:220 IDF/Views/Issue.php:301 +#: IDF/Views/Issue.php:390 IDF/Views/Issue.php:542 IDF/Views/Issue.php:765 +#: IDF/Views/Issue.php:824 IDF/Views/Review.php:57 IDF/Views/User.php:81 +msgid "Id" +msgstr "" + +#: IDF/Views/Issue.php:64 IDF/Views/Issue.php:223 IDF/Views/Issue.php:305 +#: IDF/Views/Issue.php:393 IDF/Views/Issue.php:545 IDF/Views/Issue.php:768 +#: IDF/Views/Issue.php:827 IDF/Views/Review.php:60 IDF/Views/User.php:85 +msgid "Last Updated" +msgstr "" + +#: IDF/Views/Issue.php:68 IDF/Views/Issue.php:227 IDF/Views/Issue.php:309 +#: IDF/Views/Issue.php:397 IDF/Views/Issue.php:549 IDF/Views/Issue.php:772 +#: IDF/Views/Issue.php:831 +msgid "No issues were found." +msgstr "" + +#: IDF/Views/Issue.php:113 +msgid "Not assigned" +msgstr "" + +#: IDF/Views/Issue.php:149 +#, php-format +msgid "Summary of tracked issues in %s." +msgstr "" + +#: IDF/Views/Issue.php:194 +#, php-format +msgid "Watch List: Closed Issues for %s" +msgstr "" + +#: IDF/Views/Issue.php:195 +#, php-format +msgid "This table shows the closed issues in your watch list for %s project." +msgstr "" + +#: IDF/Views/Issue.php:200 +#, php-format +msgid "Watch List: Open Issues for %s" +msgstr "" + +#: IDF/Views/Issue.php:201 +#, php-format +msgid "This table shows the open issues in your watch list for %s project." +msgstr "" + +#: IDF/Views/Issue.php:277 +msgid "Watch List: Closed Issues" +msgstr "" + +#: IDF/Views/Issue.php:278 +msgid "This table shows the closed issues in your watch list." +msgstr "" + +#: IDF/Views/Issue.php:283 +msgid "Watch List: Open Issues" +msgstr "" + +#: IDF/Views/Issue.php:284 +msgid "This table shows the open issues in your watch list." +msgstr "" + +#: IDF/Views/Issue.php:303 IDF/Views/User.php:82 +msgid "Project" +msgstr "" + +#: IDF/Views/Issue.php:344 +#, php-format +msgid "%1$s %2$s Submitted %3$s Issues" +msgstr "" + +#: IDF/Views/Issue.php:348 +#, php-format +msgid "%1$s %2$s Closed Submitted %3$s Issues" +msgstr "" + +#: IDF/Views/Issue.php:352 +#, php-format +msgid "%1$s %2$s Closed Working %3$s Issues" +msgstr "" + +#: IDF/Views/Issue.php:356 +#, php-format +msgid "%1$s %2$s Working %3$s Issues" +msgstr "" + +#: IDF/Views/Issue.php:417 +msgid "Submit a new issue" +msgstr "" + +#: IDF/Views/Issue.php:433 +#, php-format +msgid "Issue %2$d has been created." +msgstr "" + +#: IDF/Views/Issue.php:490 +#, php-format +msgid "Search issues - %s" +msgstr "" + +#: IDF/Views/Issue.php:492 +#, php-format +msgid "Search closed issues - %s" +msgstr "" + +#: IDF/Views/Issue.php:539 +msgid "This table shows the found issues." +msgstr "" + +#: IDF/Views/Issue.php:604 +#, php-format +msgid "Issue %2$d: %3$s" +msgstr "" + +#: IDF/Views/Issue.php:628 +#, php-format +msgid "Issue %2$d has been updated." +msgstr "" + +#: IDF/Views/Issue.php:718 +#, php-format +msgid "View %s" +msgstr "" + +#: IDF/Views/Issue.php:745 +#, php-format +msgid "%s Closed Issues" +msgstr "" + +#: IDF/Views/Issue.php:755 +msgid "This table shows the closed issues." +msgstr "" + +#: IDF/Views/Issue.php:798 +#, php-format +msgid "%1$s Issues with Label %2$s" +msgstr "" + +#: IDF/Views/Issue.php:801 +#, php-format +msgid "%1$s Closed Issues with Label %2$s" +msgstr "" + +#: IDF/Views/Issue.php:814 +#, php-format +msgid "This table shows the issues with label %s." +msgstr "" + +#: IDF/Views/Issue.php:937 +msgid "The issue has been removed from your watch list." +msgstr "" + +#: IDF/Views/Issue.php:940 +msgid "The issue has been added to your watch list." +msgstr "" + +#: IDF/Views/Issue.php:1037 +msgid "On your watch list." +msgstr "" + +#: IDF/Views/Project.php:95 +msgid "Issues and Comments" +msgstr "" + +#: IDF/Views/Project.php:99 +msgid "Documents" +msgstr "" + +#: IDF/Views/Project.php:101 +msgid "Reviews and Patches" +msgstr "" + +#: IDF/Views/Project.php:180 +msgid "This table shows the project updates." +msgstr "" + +#: IDF/Views/Project.php:191 +msgid "Change" +msgstr "" + +#: IDF/Views/Project.php:195 +msgid "No changes were found." +msgstr "" + +#: IDF/Views/Project.php:296 +#, php-format +msgid "%s Project Summary" +msgstr "" + +#: IDF/Views/Project.php:335 +#, php-format +msgid "%s Issue Tracking Configuration" +msgstr "" + +#: IDF/Views/Project.php:344 +msgid "The issue tracking configuration has been saved." +msgstr "" + +#: IDF/Views/Project.php:381 +#, php-format +msgid "%s Downloads Configuration" +msgstr "" + +#: IDF/Views/Project.php:393 +msgid "The downloads configuration has been saved." +msgstr "" + +#: IDF/Views/Project.php:428 +#, php-format +msgid "%s Documentation Configuration" +msgstr "" + +#: IDF/Views/Project.php:437 +msgid "The documentation configuration has been saved." +msgstr "" + +#: IDF/Views/Project.php:471 +#, php-format +msgid "%s Project Members" +msgstr "" + +#: IDF/Views/Project.php:480 +msgid "The project membership has been saved." +msgstr "" + +#: IDF/Views/Project.php:503 +#, php-format +msgid "%s Tabs Access Rights" +msgstr "" + +#: IDF/Views/Project.php:517 +msgid "" +"The project tabs access rights and notification settings have been saved." +msgstr "" + +#: IDF/Views/Project.php:566 +#, php-format +msgid "%s Source" +msgstr "" + +#: IDF/Views/Project.php:580 +msgid "The project source configuration has been saved." +msgstr "" + +#: IDF/Views/Review.php:41 +#, php-format +msgid "%s Code Reviews" +msgstr "" + +#: IDF/Views/Review.php:48 +msgid "This table shows the latest reviews." +msgstr "" + +#: IDF/Views/Review.php:64 +msgid "No reviews were found." +msgstr "" + +#: IDF/Views/Review.php:94 +#, php-format +msgid "The code review %2$d has been created." +msgstr "" + +#: IDF/Views/Review.php:140 +#, php-format +msgid "Review %2$d: %3$s" +msgstr "" + +#: IDF/Views/Review.php:160 +#, php-format +msgid "Your code review %2$d has been published." +msgstr "" + +#: IDF/Views/Source.php:40 +#, php-format +msgid "%s Source Help" +msgstr "" + +#: IDF/Views/Source.php:58 +#, php-format +msgid "%s Invalid Revision" +msgstr "" + +#: IDF/Views/Source.php:82 +#, php-format +msgid "%s Ambiguous Revision" +msgstr "" + +#: IDF/Views/Source.php:107 +#, php-format +msgid "%1$s %2$s Change Log" +msgstr "" + +#: IDF/Views/Source.php:153 IDF/Views/Source.php:234 IDF/Views/Source.php:362 +#, php-format +msgid "%1$s %2$s Source Tree" +msgstr "" + +#: IDF/Views/Source.php:310 +#, php-format +msgid "%s Commit Details" +msgstr "" + +#: IDF/Views/Source.php:311 +#, php-format +msgid "%1$s Commit Details - %2$s" +msgstr "" + +#: IDF/Views/User.php:59 +msgid "Your Dashboard - Working Issues" +msgstr "" + +#: IDF/Views/User.php:62 +msgid "Your Dashboard - Submitted Issues" +msgstr "" + +#: IDF/Views/User.php:89 +msgid "No issues are assigned to you, yeah!" +msgstr "" + +#: IDF/Views/User.php:89 +msgid "All the issues you submitted are fixed, yeah!" +msgstr "" + +#: IDF/Views/User.php:121 +msgid "Your personal information has been updated." +msgstr "" + +#: IDF/Views/User.php:133 +msgid "Your Account" +msgstr "" + +#: IDF/Views/User.php:157 +msgid "The public key has been deleted." +msgstr "" + +#: IDF/Views/User.php:177 +msgid "The address has been deleted." +msgstr "" + +#: IDF/Views/User.php:200 +msgid "Confirm The Email Change" +msgstr "" + +#: IDF/Views/User.php:232 +#, php-format +msgid "Your new email address \"%s\" has been validated. Thank you!" +msgstr "" + +#: IDF/Views/Wiki.php:41 +#, php-format +msgid "%s Documentation" +msgstr "" + +#: IDF/Views/Wiki.php:48 +msgid "This table shows the documentation pages." +msgstr "" + +#: IDF/Views/Wiki.php:61 IDF/Views/Wiki.php:144 IDF/Views/Wiki.php:185 +msgid "Page Title" +msgstr "" + +#: IDF/Views/Wiki.php:63 IDF/Views/Wiki.php:103 IDF/Views/Wiki.php:146 +#: IDF/Views/Wiki.php:187 +msgid "Updated" +msgstr "" + +#: IDF/Views/Wiki.php:67 IDF/Views/Wiki.php:191 +msgid "No documentation pages were found." +msgstr "" + +#: IDF/Views/Wiki.php:88 +#, fuzzy, php-format +msgid "%s Documentation Resources" +msgstr "%s: Página de documentação %s adicionada - %s" + +#: IDF/Views/Wiki.php:94 +msgid "This table shows the resources that can be used on documentation pages." +msgstr "" + +#: IDF/Views/Wiki.php:100 +msgid "Resource Title" +msgstr "" + +#: IDF/Views/Wiki.php:107 +msgid "No resources were found." +msgstr "" + +#: IDF/Views/Wiki.php:128 +#, php-format +msgid "Documentation Search - %s" +msgstr "" + +#: IDF/Views/Wiki.php:139 +msgid "This table shows the pages found." +msgstr "" + +#: IDF/Views/Wiki.php:150 +msgid "No pages were found." +msgstr "" + +#: IDF/Views/Wiki.php:169 +#, php-format +msgid "%1$s Documentation Pages with Label %2$s" +msgstr "" + +#: IDF/Views/Wiki.php:179 +#, php-format +msgid "This table shows the documentation pages with label %s." +msgstr "" + +#: IDF/Views/Wiki.php:222 +#, php-format +msgid "The page %2$s has been created." +msgstr "" + +#: IDF/Views/Wiki.php:265 +#, php-format +msgid "The resource %2$s has been created." +msgstr "" + +#: IDF/Views/Wiki.php:409 IDF/Views/Wiki.php:448 +msgid "The old revision has been deleted." +msgstr "" + +#: IDF/Views/Wiki.php:415 IDF/Views/Wiki.php:454 +#, php-format +msgid "Delete Old Revision of %s" +msgstr "" + +#: IDF/Views/Wiki.php:496 +#, php-format +msgid "The page %2$s has been updated." +msgstr "" + +#: IDF/Views/Wiki.php:548 +#, php-format +msgid "The resource %2$s has been updated." +msgstr "" + +#: IDF/Views/Wiki.php:583 +msgid "The documentation page has been deleted." +msgstr "" + +#: IDF/Views/Wiki.php:591 +#, php-format +msgid "Delete Page %s" +msgstr "" + +#: IDF/Views/Wiki.php:623 +msgid "The documentation resource has been deleted." +msgstr "" + +#: IDF/Views/Wiki.php:631 +#, php-format +msgid "Delete Resource %s" +msgstr "" + +#: IDF/Views.php:173 IDF/Views.php:199 +msgid "Confirm Your Account Creation" +msgstr "Confirme a criação de sua conta" + +#: IDF/Views.php:219 +msgid "Welcome! You can now participate in the life of your project of choice." +msgstr "" + +#: IDF/Views.php:245 IDF/Views.php:269 IDF/Views.php:310 +msgid "Password Recovery" +msgstr "Recuperação de Senha" + +#: IDF/Views.php:289 +msgid "" +"Welcome back! Next time, you can use your broswer options to remember the " +"password." +msgstr "" + +#: IDF/Views.php:331 +msgid "Here to Help You!" +msgstr "" + +#: IDF/Views.php:347 +msgid "InDefero Upload Archive Format" +msgstr "" + +#: IDF/Views.php:363 +msgid "InDefero API (Application Programming Interface)" +msgstr "InDefero API (Application Programming Interface)" + +#: IDF/Wiki/Page.php:62 IDF/Wiki/Resource.php:64 +msgid "title" +msgstr "título" + +#: IDF/Wiki/Page.php:63 +msgid "" +"The title of the page must only contain letters, digits or the dash " +"character. For example: My-new-Wiki-Page." +msgstr "" + +#: IDF/Wiki/Page.php:71 +msgid "A one line description of the page content." +msgstr "" + +#: IDF/Wiki/Page.php:196 IDF/Wiki/PageRevision.php:196 +#, php-format +msgid "%2$s, %3$s" +msgstr "" + +#: IDF/Wiki/Page.php:198 +#, fuzzy, php-format +msgid "Creation of page %2$s, by %3$s" +msgstr "Criação da página %s, por %s" + +#: IDF/Wiki/Page.php:208 +#, fuzzy, php-format +msgid "%1$s: Documentation page %2$s added - %3$s" +msgstr "%s: Página de documentação %s adicionada - %s" + +#: IDF/Wiki/PageRevision.php:48 +msgid "page" +msgstr "página" + +#: IDF/Wiki/PageRevision.php:66 IDF/Wiki/ResourceRevision.php:64 +msgid "A one line description of the changes." +msgstr "" + +#: IDF/Wiki/PageRevision.php:72 +msgid "content" +msgstr "conteúdo" + +#: IDF/Wiki/PageRevision.php:218 IDF/Wiki/ResourceRevision.php:311 +#, fuzzy, php-format +msgid "Change of %2$s, by %3$s" +msgstr "Criação da página %s, por %s" + +#: IDF/Wiki/PageRevision.php:231 +#, fuzzy, php-format +msgid "%1$s: Documentation page %2$s updated - %3$s" +msgstr "%s: Página de documentação %s adicionada - %s" + +#: IDF/Wiki/PageRevision.php:293 +#, fuzzy, php-format +msgid "New Documentation Page %1$s - %2$s (%3$s)" +msgstr "%s: Página de documentação %s adicionada - %s" + +#: IDF/Wiki/PageRevision.php:297 +#, fuzzy, php-format +msgid "Documentation Page Changed %1$s - %2$s (%3$s)" +msgstr "%s: Página de documentação %s adicionada - %s" + +#: IDF/Wiki/Resource.php:65 +msgid "" +"The title of the resource must only contain letters, digits, dots or the " +"dash character. For example: my-resource.png." +msgstr "" + +#: IDF/Wiki/Resource.php:72 +msgid "MIME media type" +msgstr "" + +#: IDF/Wiki/Resource.php:73 +msgid "The MIME media type of the resource." +msgstr "" + +#: IDF/Wiki/Resource.php:81 +#, fuzzy +msgid "A one line description of the resource." +msgstr "Descrição do projeto em uma linha." + +#: IDF/Wiki/Resource.php:176 IDF/Wiki/ResourceRevision.php:308 +#, php-format +msgid "%2$s, %3$s" +msgstr "" + +#: IDF/Wiki/Resource.php:178 +#, fuzzy, php-format +msgid "Creation of resource %2$s, by %3$s" +msgstr "Criação da página %s, por %s" + +#: IDF/Wiki/Resource.php:188 +#, fuzzy, php-format +msgid "%1$s: Documentation resource %2$s added - %3$s" +msgstr "%s: Página de documentação %s adicionada - %s" + +#: IDF/Wiki/ResourceRevision.php:47 +#, fuzzy +msgid "resource" +msgstr "Código Fonte" + +#: IDF/Wiki/ResourceRevision.php:78 +msgid "File extension" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:79 +msgid "The file extension of the uploaded resource." +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:94 +msgid "page usage" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:116 +#, php-format +msgid "id %d: %s" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:263 +#, php-format +msgid "Download (%s)" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:270 +msgid "View resource details" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:324 +#, fuzzy, php-format +msgid "%1$s: Documentation resource %2$s updated - %3$s" +msgstr "%s: Página de documentação %s adicionada - %s" diff --git a/indefero/src/IDF/locale/ru/idf.po b/indefero/src/IDF/locale/ru/idf.po new file mode 100644 index 0000000..e5cb1bf --- /dev/null +++ b/indefero/src/IDF/locale/ru/idf.po @@ -0,0 +1,5874 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Denis , 2011. +# , 2011. +# , 2011. +# William MARTIN , 2011. +msgid "" +msgstr "" +"Project-Id-Version: Indefero\n" +"Report-Msgid-Bugs-To: http://projects.ceondo.com/p/indefero/issues/\n" +"POT-Creation-Date: 2012-03-22 01:16+0100\n" +"PO-Revision-Date: 2011-11-01 07:10+0000\n" +"Last-Translator: Denis \n" +"Language-Team: Russian (http://www.transifex.net/projects/p/indefero/team/" +"ru/)\n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" + +#: IDF/Commit.php:55 IDF/Conf.php:54 IDF/Issue.php:52 +#: IDF/ProjectActivity.php:49 IDF/Review.php:65 IDF/Search/Occ.php:69 +#: IDF/Tag.php:52 IDF/Upload.php:49 IDF/Wiki/Page.php:54 +#: IDF/Wiki/Resource.php:56 +msgid "project" +msgstr "проект" + +#: IDF/Commit.php:63 IDF/Issue.php:67 IDF/IssueComment.php:65 +#: IDF/IssueFile.php:57 IDF/IssueRelation.php:69 IDF/Review/Comment.php:69 +#: IDF/Review.php:80 IDF/Upload.php:91 IDF/Wiki/Page.php:78 +#: IDF/Wiki/PageRevision.php:79 IDF/Wiki/Resource.php:88 +#: IDF/Wiki/ResourceRevision.php:86 +msgid "submitter" +msgstr "отправитель" + +#: IDF/Commit.php:87 IDF/Issue.php:60 IDF/Review/Patch.php:60 +#: IDF/Review.php:73 IDF/Upload.php:57 IDF/Wiki/Page.php:70 +#: IDF/Wiki/PageRevision.php:65 IDF/Wiki/Resource.php:80 +#: IDF/Wiki/ResourceRevision.php:63 +msgid "summary" +msgstr "краткое описание" + +#: IDF/Commit.php:93 +msgid "changelog" +msgstr "история изменений" + +#: IDF/Commit.php:100 IDF/Issue.php:105 IDF/IssueComment.php:79 +#: IDF/IssueFile.php:96 IDF/IssueRelation.php:75 IDF/Review/Comment.php:90 +#: IDF/Review/FileComment.php:75 IDF/Review/Patch.php:87 IDF/Review.php:108 +#: IDF/Upload.php:112 IDF/Wiki/Page.php:100 IDF/Wiki/PageRevision.php:92 +#: IDF/Wiki/Resource.php:95 IDF/Wiki/ResourceRevision.php:101 +msgid "creation date" +msgstr "дата создания" + +#: IDF/Commit.php:238 +#, fuzzy, php-format +msgid "Commit %1$s, by %2$s" +msgstr "Комит %s, %s" + +#: IDF/Commit.php:337 +#, fuzzy, php-format +msgid "New Commit %1$s - %2$s (%3$s)" +msgstr "Новый комит %s - %s (%s)" + +#: IDF/Conf.php:61 IDF/Gconf.php:73 +msgid "key" +msgstr "ключ" + +#: IDF/Conf.php:67 IDF/Gconf.php:79 IDF/ProjectActivity.php:62 +msgid "value" +msgstr "значение" + +#: IDF/Diff.php:460 +msgid "Old" +msgstr "Старый" + +#: IDF/Diff.php:460 +msgid "New" +msgstr "Новый" + +#: IDF/EmailAddress.php:49 IDF/Key.php:49 +msgid "user" +msgstr "пользователь" + +#: IDF/EmailAddress.php:55 +msgid "email" +msgstr "" + +#: IDF/Form/Admin/ForgeConf.php:34 +msgid "Custom forge page enabled" +msgstr "" + +#: IDF/Form/Admin/ForgeConf.php:39 IDF/Form/WikiPageCreate.php:80 +#: IDF/Form/WikiPageUpdate.php:72 +msgid "Content" +msgstr "Содержание" + +#: IDF/Form/Admin/LabelConf.php:40 +#, fuzzy +msgid "Predefined project labels" +msgstr "Предопределенные ярлыки для проблемы" + +#: IDF/Form/Admin/LabelConf.php:55 +#, php-format +msgid "" +"The label \"%s\" is invalid: A label must only consist of alphanumeric " +"characters and dashes, and can optionally contain a \":\" with a group " +"prefix." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:38 IDF/Views/Project.php:600 +msgid "git" +msgstr "git" + +#: IDF/Form/Admin/ProjectCreate.php:39 IDF/Views/Project.php:601 +msgid "Subversion" +msgstr "Subversion" + +#: IDF/Form/Admin/ProjectCreate.php:40 IDF/Views/Project.php:602 +msgid "mercurial" +msgstr "mercurial" + +#: IDF/Form/Admin/ProjectCreate.php:41 IDF/Views/Project.php:603 +msgid "monotone" +msgstr "monotone" + +#: IDF/Form/Admin/ProjectCreate.php:49 IDF/Form/Admin/ProjectUpdate.php:44 +#: IDF/Form/ProjectConf.php:39 IDF/Views/Admin.php:86 IDF/Views/Admin.php:273 +msgid "Name" +msgstr "Имя" + +#: IDF/Form/Admin/ProjectCreate.php:55 IDF/Form/TabsConf.php:101 +#: IDF/gettexttemplates/idf/base-full.html.php:5 +#: IDF/gettexttemplates/idf/base-full.html~.php:5 +#: IDF/gettexttemplates/idf/base.html.php:5 +#: IDF/gettexttemplates/idf/base.html~.php:5 +#: IDF/gettexttemplates/idf/main-menu.html.php:9 +#: IDF/gettexttemplates/idf/project-list.html.php:5 +#: IDF/gettexttemplates/idf/project-list.html.php:7 +msgid "Private project" +msgstr "Частный проект" + +#: IDF/Form/Admin/ProjectCreate.php:62 +msgid "Shortname" +msgstr "Краткое имя" + +#: IDF/Form/Admin/ProjectCreate.php:64 +msgid "" +"It must be unique for each project and composed only of letters, digits and " +"dash (-) like \"my-project\"." +msgstr "" +"Должно быть уникальным для каждого проекта и состоять только из латинских " +"букв, цифр и дефиса (-), например \"my-project\"." + +#: IDF/Form/Admin/ProjectCreate.php:69 IDF/Form/Admin/ProjectUpdate.php:50 +msgid "Short description" +msgstr "Краткое описание" + +#: IDF/Form/Admin/ProjectCreate.php:70 IDF/Form/Admin/ProjectUpdate.php:51 +#: IDF/Project.php:79 +msgid "A one line description of the project." +msgstr "Краткое описание проекта." + +#: IDF/Form/Admin/ProjectCreate.php:77 IDF/Form/Admin/ProjectUpdate.php:58 +#: IDF/Form/ProjectConf.php:56 +msgid "External URL" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:84 +msgid "Repository type" +msgstr "Тип репозитория" + +#: IDF/Form/Admin/ProjectCreate.php:92 +msgid "Remote Subversion repository" +msgstr "Удаленная репозитория Subversion" + +#: IDF/Form/Admin/ProjectCreate.php:99 IDF/Form/SourceConf.php:40 +msgid "Repository username" +msgstr "Логин репозитории" + +#: IDF/Form/Admin/ProjectCreate.php:106 IDF/Form/SourceConf.php:47 +msgid "Repository password" +msgstr "Пароль репозитории" + +#: IDF/Form/Admin/ProjectCreate.php:113 IDF/Form/Admin/ProjectUpdate.php:66 +msgid "Master branch" +msgstr "Основная ветка" + +#: IDF/Form/Admin/ProjectCreate.php:116 IDF/Form/Admin/ProjectUpdate.php:69 +msgid "" +"This should be a world-wide unique identifier for your project. A reverse " +"DNS notation like \"com.my-domain.my-project\" is a good idea." +msgstr "" +"Это должен быть уникальный в мировом маштабе идентификатор проекта. Обратная " +"запись DNS как \"com.my-domain.my-проект\" является хорошей идеей." + +#: IDF/Form/Admin/ProjectCreate.php:121 IDF/Form/Admin/ProjectUpdate.php:95 +#: IDF/Form/MembersConf.php:46 IDF/Form/TabsConf.php:53 +#: IDF/Form/TabsConf.php:72 +msgid "Project owners" +msgstr "Владельцы проекта" + +#: IDF/Form/Admin/ProjectCreate.php:130 IDF/Form/Admin/ProjectUpdate.php:103 +#: IDF/Form/MembersConf.php:54 IDF/Form/TabsConf.php:52 +#: IDF/Form/TabsConf.php:78 +msgid "Project members" +msgstr "Участники проекта" + +#: IDF/Form/Admin/ProjectCreate.php:140 IDF/Form/Admin/ProjectUpdate.php:85 +#: IDF/Form/IssueCreate.php:168 IDF/Form/IssueUpdate.php:164 +#: IDF/Form/ProjectConf.php:73 IDF/Form/UpdateUpload.php:71 +#: IDF/Form/Upload.php:70 IDF/Form/WikiPageCreate.php:93 +#: IDF/Form/WikiPageUpdate.php:104 +msgid "Labels" +msgstr "Ярлыки" + +#: IDF/Form/Admin/ProjectCreate.php:155 +msgid "Project template" +msgstr "Шаблон проекта" + +#: IDF/Form/Admin/ProjectCreate.php:157 +msgid "" +"Use the given project to initialize the new project. Access rights and " +"general configuration will be taken from the template project." +msgstr "" +"Использовать указанный проект для инициализации нового проекта. Права " +"доступа и общая конфигурация будут взяты из исходного проекта." + +#: IDF/Form/Admin/ProjectCreate.php:204 +msgid "" +"Only a remote repository available through HTTP or HTTPS is allowed. For " +"example \"http://somewhere.com/svn/trunk\"." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:220 IDF/Form/Admin/ProjectUpdate.php:117 +msgid "" +"The master branch is empty or contains illegal characters, please use only " +"letters, digits, dashes and dots as separators." +msgstr "" +"Мастер бранч пустой или содержит недопустимые символы, пожалуйста, " +"используйте только латинские буквы, цифры, дефисы и точки в качестве " +"разделителей." + +#: IDF/Form/Admin/ProjectCreate.php:230 IDF/Form/Admin/ProjectUpdate.php:128 +msgid "This master branch is already used. Please select another one." +msgstr "Этот мастер бранч уже используется. Пожалуйста, выберите другой." + +#: IDF/Form/Admin/ProjectCreate.php:241 +msgid "" +"This shortname contains illegal characters, please use only letters, digits " +"and dash (-)." +msgstr "" +"Краткое имя содержит недопустимые символы. Пожалуйста, используйте только " +"буквы, цифры и дефис (-)." + +#: IDF/Form/Admin/ProjectCreate.php:244 +msgid "The shortname cannot start with the dash (-) character." +msgstr "Краткое имя не может начинаться с прочерка (-)." + +#: IDF/Form/Admin/ProjectCreate.php:247 +msgid "The shortname cannot end with the dash (-) character." +msgstr "Краткое имя не может заканчиваться прочером (-)." + +#: IDF/Form/Admin/ProjectCreate.php:252 +msgid "This shortname is already used. Please select another one." +msgstr "Краткое имя уже используется. Пожалуйста, выберите другое." + +#: IDF/Form/Admin/ProjectCreate.php:303 IDF/Form/Admin/ProjectDelete.php:78 +#: IDF/Form/Admin/ProjectUpdate.php:153 IDF/Form/Admin/UserCreate.php:106 +#: IDF/Form/Admin/UserUpdate.php:191 IDF/Form/IssueCreate.php:338 +#: IDF/Form/IssueUpdate.php:329 IDF/Form/MembersConf.php:64 +#: IDF/Form/Password.php:76 IDF/Form/Register.php:112 +#: IDF/Form/ReviewCreate.php:187 IDF/Form/ReviewFileComment.php:143 +#: IDF/Form/TabsConf.php:122 IDF/Form/UpdateUpload.php:126 +#: IDF/Form/Upload.php:149 IDF/Form/UploadArchive.php:137 +#: IDF/Form/UserAccount.php:216 IDF/Form/UserChangeEmail.php:80 +#: IDF/Form/WikiPageCreate.php:167 IDF/Form/WikiPageDelete.php:59 +#: IDF/Form/WikiPageUpdate.php:178 IDF/Form/WikiResourceCreate.php:123 +#: IDF/Form/WikiResourceDelete.php:59 IDF/Form/WikiResourceUpdate.php:124 +msgid "Cannot save the model from an invalid form." +msgstr "Не удается сохранить модель из недействительной формы." + +#: IDF/Form/Admin/ProjectCreate.php:341 +msgid "" +"Click on the Project Management tab to set the description of your project." +msgstr "" +"Кликните на закладку Управление проектом, чтобы задать описание Вашего " +"проекта." + +#: IDF/Form/Admin/ProjectCreate.php:426 +msgid "This project is not available." +msgstr "Этот проект не доступен." + +#: IDF/Form/Admin/ProjectDelete.php:41 +msgid "Confirmation code" +msgstr "Код подтверждения" + +#: IDF/Form/Admin/ProjectDelete.php:46 +msgid "I have made a backup of all the important data of this project." +msgstr "Я сделал резервную копию всех важных данных этого проекта." + +#: IDF/Form/Admin/ProjectDelete.php:55 +msgid "" +"The confirmation code does not match. Please provide a valid confirmation " +"code to delete the project." +msgstr "" +"Код проверки не совпадает. Пожалуйста, укажите правильный код проверки для " +"удаления проекта." + +#: IDF/Form/Admin/ProjectDelete.php:63 +msgid "Sorry, you really need to backup your data before deletion." +msgstr "" +"Извините, но вы действительно должны сделать резервную копию всех важных " +"данных перед удалением." + +#: IDF/Form/Admin/UserCreate.php:37 IDF/Form/Admin/UserUpdate.php:38 +#: IDF/Form/RegisterConfirmation.php:50 IDF/Form/UserAccount.php:40 +msgid "First name" +msgstr "Имя" + +#: IDF/Form/Admin/UserCreate.php:46 IDF/Form/Admin/UserUpdate.php:47 +#: IDF/Form/RegisterConfirmation.php:59 IDF/Form/UserAccount.php:49 +msgid "Last name" +msgstr "Фамилия" + +#: IDF/Form/Admin/UserCreate.php:56 +msgid "Login" +msgstr "Логин" + +#: IDF/Form/Admin/UserCreate.php:60 +msgid "" +"The login must be between 3 and 15 characters long and contains only letters " +"and digits." +msgstr "" +"Логин должен быть от 3-х до 15-ти символов и содержать только латинские " +"буквы и цифры." + +#: IDF/Form/Admin/UserCreate.php:69 IDF/Form/Admin/UserUpdate.php:57 +msgid "Email" +msgstr "Эл. адрес" + +#: IDF/Form/Admin/UserCreate.php:71 +msgid "" +"Double check the email address as the password is sent directly to the user." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:76 IDF/Form/Admin/UserUpdate.php:67 +#: IDF/Form/UserAccount.php:66 +msgid "Language" +msgstr "Язык" + +#: IDF/Form/Admin/UserCreate.php:87 IDF/Form/UserAccount.php:161 +msgid "Add a public key" +msgstr "Добавить открытый ключ." + +#: IDF/Form/Admin/UserCreate.php:92 +msgid "" +"Paste a SSH or monotone public key. Be careful to not provide your private " +"key here!" +msgstr "" +"Вставьте публичный ключ SSH или monotone. Будьте внимательны и не " +"перепутайте с Вашим личным ключом!" + +#: IDF/Form/Admin/UserCreate.php:157 +msgid "Your details to access your forge." +msgstr "Ваши данные для доступа к хранилищу." + +#: IDF/Form/Admin/UserCreate.php:189 IDF/Form/UserAccount.php:429 +#: IDF/Form/UserAccount.php:438 +#, php-format +msgid "The email \"%s\" is already used." +msgstr "Эл. адрес \"%s\" уже используется." + +#: IDF/Form/Admin/UserCreate.php:198 IDF/Form/Register.php:72 +#, php-format +msgid "The login \"%s\" can only contain letters and digits." +msgstr "Логин \"%s\" может содержать только латинские буквы и цифры." + +#: IDF/Form/Admin/UserCreate.php:203 IDF/Form/Register.php:77 +#, php-format +msgid "The login \"%s\" is already used, please find another one." +msgstr "Логин \"%s\" уже используется. Пожалуйста, выберите другой логин." + +#: IDF/Form/Admin/UserUpdate.php:78 +msgid "Password" +msgstr "Пароль" + +#: IDF/Form/Admin/UserUpdate.php:81 +msgid "Leave blank if you do not want to change the password." +msgstr "Оставьте пустым если Вы не хотите менять пароль." + +#: IDF/Form/Admin/UserUpdate.php:81 +msgid "" +"The password must be hard for other people to guess, but easy for the user " +"to remember." +msgstr "" +"Пароль должен быть сложен для угадывания другими, но легок для запоминания " +"пользователем." + +#: IDF/Form/Admin/UserUpdate.php:89 +msgid "Confirm password" +msgstr "Подтверждение пароля" + +#: IDF/Form/Admin/UserUpdate.php:100 IDF/Form/IssueCreate.php:66 +#: IDF/Form/ProjectConf.php:48 IDF/Form/ReviewCreate.php:54 +#: IDF/Form/UpdateUpload.php:51 IDF/Form/Upload.php:49 +#: IDF/Form/UserAccount.php:101 IDF/Form/WikiPageCreate.php:70 +#: IDF/Form/WikiPageUpdate.php:60 IDF/Form/WikiResourceCreate.php:54 +#: IDF/Form/WikiResourceUpdate.php:46 IDF/Views/Wiki.php:102 +msgid "Description" +msgstr "Описание" + +#: IDF/Form/Admin/UserUpdate.php:109 IDF/Form/UserAccount.php:110 +msgid "Twitter username" +msgstr "Имя пользователя Twitter." + +#: IDF/Form/Admin/UserUpdate.php:119 IDF/Form/UserAccount.php:120 +msgid "Public email address" +msgstr "Публичный адрес эл. почты" + +#: IDF/Form/Admin/UserUpdate.php:129 IDF/Form/UserAccount.php:130 +msgid "Website URL" +msgstr "Веб-сайт" + +#: IDF/Form/Admin/UserUpdate.php:139 IDF/Form/UserAccount.php:140 +msgid "Upload custom avatar" +msgstr "Загрузить свой аватар" + +#: IDF/Form/Admin/UserUpdate.php:146 IDF/Form/UserAccount.php:147 +msgid "" +"An image file with a width and height not larger than 60 pixels (bigger " +"images are scaled down)." +msgstr "" +"Графический файл с шириной и высотой не более 60 пикселов (большое " +"изображение маштабируется автоматически)." + +#: IDF/Form/Admin/UserUpdate.php:151 IDF/Form/UserAccount.php:152 +msgid "Remove custom avatar" +msgstr "Удалить свой аватар" + +#: IDF/Form/Admin/UserUpdate.php:155 IDF/Form/UserAccount.php:156 +msgid "Tick this to delete the custom avatar." +msgstr "Выберите для удаления аватара." + +#: IDF/Form/Admin/UserUpdate.php:161 IDF/Views/Admin.php:274 +msgid "Staff" +msgstr "Персонал" + +#: IDF/Form/Admin/UserUpdate.php:164 +msgid "If you give staff rights to a user, you really need to trust him." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:172 IDF/Views/Admin.php:276 +msgid "Active" +msgstr "Активный" + +#: IDF/Form/Admin/UserUpdate.php:176 +msgid "" +"If the user is not getting the confirmation email or is abusing the system, " +"you can directly enable or disable their account here." +msgstr "" +"Если пользователь не получает подтверждение по электронной почте или " +"злоупотребляет системой, вы можете напрямую включить или отключить его " +"учетную запись здесь." + +#: IDF/Form/Admin/UserUpdate.php:274 +msgid "--- is not a valid first name." +msgstr "--- неправильное имя." + +#: IDF/Form/Admin/UserUpdate.php:290 +msgid "" +"A user with this email already exists, please provide another email address." +msgstr "" +"Пользователь с таким адресом эл. почты уже существует. Пожалуйста, укажите " +"другой адрес." + +#: IDF/Form/Admin/UserUpdate.php:301 IDF/Form/UserAccount.php:398 +msgid "For security reason, you cannot upload a file with this extension." +msgstr "В целях безопасности, вы не можете загрузить файл с таким расширением." + +#: IDF/Form/Admin/UserUpdate.php:316 IDF/Form/UserAccount.php:461 +msgid "The passwords do not match. Please give them again." +msgstr "Пароли не совпадают. Пожалуйста, повторите ввод." + +#: IDF/Form/Field/EmailList.php:45 +msgid "Please enter one or more valid email addresses." +msgstr "" +"Пожалуйста, введите один или несколько правильных адресов электронной почты." + +#: IDF/Form/IssueCreate.php:57 IDF/Form/IssueUpdate.php:46 +#: IDF/Form/ReviewCreate.php:45 IDF/Form/ReviewFileComment.php:73 +#: IDF/Form/UpdateUpload.php:42 IDF/Form/Upload.php:40 +#: IDF/gettexttemplates/idf/issues/base.html.php:3 IDF/Views/Download.php:65 +#: IDF/Views/Download.php:347 IDF/Views/Issue.php:62 IDF/Views/Issue.php:221 +#: IDF/Views/Issue.php:302 IDF/Views/Issue.php:391 IDF/Views/Issue.php:543 +#: IDF/Views/Issue.php:766 IDF/Views/Issue.php:825 IDF/Views/Review.php:58 +#: IDF/Views/User.php:83 IDF/Views/Wiki.php:62 IDF/Views/Wiki.php:145 +#: IDF/Views/Wiki.php:186 +msgid "Summary" +msgstr "Краткое описание" + +#: IDF/Form/IssueCreate.php:76 IDF/Form/IssueUpdate.php:66 +#: IDF/Form/ReviewCreate.php:83 +msgid "The \"upload_issue_path\" configuration variable was not set." +msgstr "Переменная конфигурации \"upload_issue_path\" не была задана." + +#: IDF/Form/IssueCreate.php:86 IDF/Form/IssueUpdate.php:76 +msgid "Attach a file" +msgstr "Приложить файл" + +#: IDF/Form/IssueCreate.php:99 IDF/Form/IssueUpdate.php:89 +#: IDF/Form/ReviewCreate.php:103 IDF/Form/ReviewFileComment.php:83 +#: IDF/Views/Issue.php:63 IDF/Views/Issue.php:222 IDF/Views/Issue.php:304 +#: IDF/Views/Issue.php:392 IDF/Views/Issue.php:544 IDF/Views/Issue.php:767 +#: IDF/Views/Issue.php:826 IDF/Views/Review.php:59 IDF/Views/User.php:84 +msgid "Status" +msgstr "Статус" + +#: IDF/Form/IssueCreate.php:108 IDF/Form/IssueUpdate.php:99 +msgid "Owner" +msgstr "Владелец" + +#: IDF/Form/IssueCreate.php:118 IDF/Form/IssueUpdate.php:112 +#: IDF/Form/IssueUpdate.php:129 +msgid "This issue" +msgstr "Эта проблема" + +#: IDF/Form/IssueCreate.php:210 +msgid "You cannot add a label with the \"Status\" prefix to an issue." +msgstr "Вы не можете добавить ярлык с префиксом \"Статус\" к проблеме." + +#: IDF/Form/IssueCreate.php:211 IDF/Form/IssueCreate.php:218 +#: IDF/Form/UpdateUpload.php:110 IDF/Form/Upload.php:121 +#: IDF/Form/WikiPageCreate.php:151 IDF/Form/WikiPageUpdate.php:162 +msgid "You provided an invalid label." +msgstr "Вы ввели недопустимый ярлык." + +#: IDF/Form/IssueCreate.php:217 IDF/Form/UpdateUpload.php:109 +#, fuzzy, php-format +msgid "You cannot provide more than one label from the %s class to an issue." +msgstr "Вы не можете указать больше чем метку из класса %s к проблеме." + +#: IDF/Form/IssueCreate.php:228 IDF/Form/IssueUpdate.php:194 +msgid "You need to provide a description of the issue." +msgstr "Вам необходимо ввести описание проблемы." + +#: IDF/Form/IssueCreate.php:251 IDF/Form/ReviewCreate.php:159 +msgid "You provided an invalid status." +msgstr "Вы ввели неверный статус." + +#: IDF/Form/IssueCreate.php:272 +msgid "You provided an invalid relation type." +msgstr "Вы ввели неверный тип отношений." + +#: IDF/Form/IssueCreate.php:294 +#, php-format +msgid "The value \"%s\" is not a valid issue id." +msgstr "" + +#: IDF/Form/IssueCreate.php:300 +#, php-format +msgid "The issue \"%s\" does not exist." +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:86 +msgid "is related to" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:87 +msgid "blocks" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:88 +msgid "is blocked by" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:89 +msgid "duplicates" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:90 +msgid "is duplicated by" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:97 +msgid "" +"Define an issue template to hint the reporter to provide certain information" +msgstr "Определите шаблон для предоставления детального описания проблемы." + +#: IDF/Form/IssueTrackingConf.php:106 +msgid "Open issue status values" +msgstr "Значения статуса открытой проблемы" + +#: IDF/Form/IssueTrackingConf.php:114 +msgid "Closed issue status values" +msgstr "Значения статуса закрытой проблемы" + +#: IDF/Form/IssueTrackingConf.php:123 +msgid "Predefined issue labels" +msgstr "Предопределенные ярлыки для проблемы" + +#: IDF/Form/IssueTrackingConf.php:125 +msgid "" +"The first \"Type:\" and \"Priority:\" entries found in this list are " +"automatically chosen as defaults for new issues." +msgstr "" +"Первые записи \"Тип:\" и \"Приоритет:\", найденные в этом листе, " +"автоматически выбраны как значения по умолчанию для новых проблем." + +#: IDF/Form/IssueTrackingConf.php:133 +#, fuzzy +msgid "Each issue may have at most one label with each of these classes." +msgstr "" +"Каждая проблема может иметь не более одной метки c каждым из этих классов" + +#: IDF/Form/IssueTrackingConf.php:140 +msgid "Issue relations" +msgstr "Связи проблемы" + +#: IDF/Form/IssueTrackingConf.php:142 +msgid "" +"You can define bidirectional relations like \"is related to\" or \"blocks, " +"is blocked by\". For standard relations pre-configured translations exist, " +"new relations should however be defined in a language that is understood by " +"all project members." +msgstr "" + +#: IDF/Form/IssueUpdate.php:56 IDF/Form/ReviewFileComment.php:45 +#: IDF/Form/WikiPageUpdate.php:82 IDF/Form/WikiResourceUpdate.php:66 +msgid "Comment" +msgstr "Комментарий" + +#: IDF/Form/IssueUpdate.php:316 +msgid "No changes were entered." +msgstr "Никакие изменения не были введены." + +#: IDF/Form/MembersConf.php:104 +#, php-format +msgid "The following login is invalid: %s." +msgid_plural "The following logins are invalid: %s." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: IDF/Form/Password.php:34 +msgid "Your login or email" +msgstr "Ваш логин или эл. адрес" + +#: IDF/Form/Password.php:35 +msgid "Provide either your login or your email to recover your password." +msgstr "Для восстановления пароля введите ваш логин или адреса эл. почты." + +#: IDF/Form/Password.php:49 IDF/Form/Password.php:64 +msgid "" +"Sorry, we cannot find a user with this email address or login. Feel free to " +"try again." +msgstr "" +"К сожалению мы не можем найти пользователя с этим адресом электронной почты " +"или логином. Не стесняйтесь попробовать еще раз." + +#: IDF/Form/Password.php:100 +msgid "Password Recovery - InDefero" +msgstr "Восстановение пароля - InDefero" + +#: IDF/Form/PasswordInputKey.php:36 IDF/Form/PasswordReset.php:39 +#: IDF/Form/UserChangeEmail.php:36 +msgid "Your verification key" +msgstr "Код подтверждения" + +#: IDF/Form/PasswordInputKey.php:50 IDF/Form/PasswordReset.php:89 +msgid "" +"We are sorry but this validation key is not valid. Maybe you should directly " +"copy/paste it from your validation email." +msgstr "" +"Мы сожалеем но этот проверочный ключ не действителен. Возможно Вам нужно " +"скопировать его из проверочного письма." + +#: IDF/Form/PasswordInputKey.php:61 IDF/Form/PasswordReset.php:100 +msgid "" +"Sorry, but this verification key has expired, please restart the password " +"recovery sequence. For security reasons, the verification key is only valid " +"24h." +msgstr "" +"Извините, но проверочный ключ больше не действителен. Пожалуйста начните с " +"восстановления пароля. В целях безопасности проверочный ключ действителен " +"только 24 часа." + +#: IDF/Form/PasswordInputKey.php:76 IDF/Form/PasswordReset.php:108 +#: IDF/Form/RegisterConfirmation.php:137 IDF/Form/RegisterInputKey.php:72 +msgid "Cannot save an invalid form." +msgstr "Немогу сохранить неправильную форму." + +#: IDF/Form/PasswordReset.php:45 IDF/Form/RegisterConfirmation.php:69 +#: IDF/Form/UserAccount.php:77 +msgid "Your password" +msgstr "Пароль" + +#: IDF/Form/PasswordReset.php:48 IDF/Form/UserAccount.php:80 +msgid "" +"Your password must be hard for other people to find it, but easy for you to " +"remember." +msgstr "" +"Ваш пароль должен быть сложен для угадывания другими, но легок для " +"запоминания Вами." + +#: IDF/Form/PasswordReset.php:56 IDF/Form/RegisterConfirmation.php:80 +#: IDF/Form/UserAccount.php:89 +msgid "Confirm your password" +msgstr "Подтверждение пароля" + +#: IDF/Form/PasswordReset.php:74 IDF/Form/RegisterConfirmation.php:122 +msgid "The two passwords must be the same." +msgstr "Пароли должны совпадать." + +#: IDF/Form/PasswordReset.php:77 +msgid "" +"This account is not active. Please contact the forge administrator to " +"activate it." +msgstr "" +"Эта учетная запись не активна. Пожалуйста, свяжитесь с администратором " +"хранилища, чтобы активировать его." + +#: IDF/Form/ProjectConf.php:43 +msgid "Short Description" +msgstr "Краткое описание" + +#: IDF/Form/ProjectConf.php:85 +msgid "The \"upload_path\" configuration variable was not set." +msgstr "" + +#: IDF/Form/ProjectConf.php:90 +msgid "Update the logo" +msgstr "" + +#: IDF/Form/ProjectConf.php:92 +msgid "The logo must be a picture with a size of 32 by 32." +msgstr "" + +#: IDF/Form/ProjectConf.php:103 +msgid "Remove the current logo" +msgstr "" + +#: IDF/Form/ProjectConf.php:139 +msgid "Could not determine the size of the uploaded picture." +msgstr "" + +#: IDF/Form/ProjectConf.php:143 +msgid "The picture must have a size of 32 by 32." +msgstr "" + +#: IDF/Form/ProjectConf.php:164 +msgid "The entered URL is invalid. Only http and https URLs are allowed." +msgstr "" + +#: IDF/Form/Register.php:41 +msgid "Your login" +msgstr "Ваш логин" + +#: IDF/Form/Register.php:45 +msgid "" +"The login must be between 3 and 15 characters long and contain only letters " +"and digits." +msgstr "" +"Логин должен быть длиной от 3 до 15 символов и содержать только буквы и " +"цифры." + +#: IDF/Form/Register.php:53 IDF/Form/UserAccount.php:59 +msgid "Your email" +msgstr "Ваш эл. адрес" + +#: IDF/Form/Register.php:55 +msgid "We will never send you any unsolicited emails. We hate spam too!" +msgstr "" + +#: IDF/Form/Register.php:60 +msgid "I agree to the terms and conditions." +msgstr "Я согласен с правилами и условиями." + +#: IDF/Form/Register.php:88 +msgid "" +"We know, this is boring, but you need to agree with the terms and conditions." +msgstr "" +"Мы знаем, что это скучно, но вы должны согласиться с правилами и условиями." + +#: IDF/Form/Register.php:97 +#, php-format +msgid "" +"The email \"%1$s\" is already used. If you need to, you can recover your password." +msgstr "" + +#: IDF/Form/Register.php:148 +msgid "Confirm the creation of your account." +msgstr "Подтвердите создание вашей учетной записи." + +#: IDF/Form/RegisterConfirmation.php:40 IDF/Form/RegisterInputKey.php:36 +msgid "Your confirmation key" +msgstr "Ваш код подтверждения" + +#: IDF/Form/RegisterConfirmation.php:72 +msgid "" +"Your password must be hard for other people to guess, but easy for you to " +"remember." +msgstr "" +"Ваш пароль должен быть сложен для угадывания другими, но легок для " +"запоминания Вами." + +#: IDF/Form/RegisterConfirmation.php:99 IDF/Form/RegisterInputKey.php:50 +msgid "" +"We are sorry but this confirmation key is not valid. Maybe you should " +"directly copy/paste it from your confirmation email." +msgstr "" +"Мы сожалеем но этот проверочный ключ не действителен. Возможно Вам нужно " +"скопировать его из проверочного письма." + +#: IDF/Form/RegisterConfirmation.php:110 +#, fuzzy, php-format +msgid "" +"This account has already been confirmed. Maybe should you try to recover your password." +msgstr "" +"Эта учетная запись уже была подтверждена. Может быть, вы должны попытаться " +"восстановить свой пароль, используя ссылку на помощь." + +#: IDF/Form/ReviewCreate.php:74 +#: IDF/gettexttemplates/idf/source/base.html.php:5 +#: IDF/gettexttemplates/idf/source/changelog.html.php:7 +msgid "Commit" +msgstr "Комит" + +#: IDF/Form/ReviewCreate.php:92 +msgid "Patch" +msgstr "Патч" + +#: IDF/Form/ReviewCreate.php:119 +msgid "We were not able to parse your patch. Please provide a valid patch." +msgstr "Мы были не в состоянии разобрать ваш патч. Укажите правильный патч." + +#: IDF/Form/ReviewCreate.php:128 +msgid "You provided an invalid commit." +msgstr "Вы ввели неверный комит." + +#: IDF/Form/ReviewCreate.php:202 +msgid "Initial patch to be reviewed." +msgstr "Первоначальный патч для рецензирования." + +#: IDF/Form/ReviewFileComment.php:56 +msgid "General comment" +msgstr "Общий комментарий" + +#: IDF/Form/ReviewFileComment.php:113 +msgid "" +"You need to provide your general comment about the proposal, or comments on " +"at least one file." +msgstr "" +"Вы должны предоставить Ваши общие замечания по поводу предложения или " +"комментарии по крайней мере на один файл." + +#: IDF/Form/ReviewFileComment.php:124 +msgid "The status have been updated." +msgstr "" + +#: IDF/Form/ReviewFileComment.php:130 +msgid "This field is required." +msgstr "" + +#: IDF/Form/SourceConf.php:54 IDF/Form/UploadConf.php:70 +msgid "Webhook URL" +msgstr "" + +#: IDF/Form/TabsConf.php:38 IDF/gettexttemplates/idf/admin/base.html.php:4 +#: IDF/gettexttemplates/idf/base-full.html.php:8 +#: IDF/gettexttemplates/idf/base-full.html~.php:7 +#: IDF/gettexttemplates/idf/base.html.php:8 +#: IDF/gettexttemplates/idf/base.html~.php:7 +#: IDF/gettexttemplates/idf/downloads/base.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:14 +#: IDF/Views/Project.php:97 +msgid "Downloads" +msgstr "Файлы" + +#: IDF/Form/TabsConf.php:39 IDF/gettexttemplates/idf/base-full.html.php:12 +#: IDF/gettexttemplates/idf/base-full.html~.php:11 +#: IDF/gettexttemplates/idf/base.html.php:12 +#: IDF/gettexttemplates/idf/base.html~.php:11 +msgid "Code Review" +msgstr "Рецензирование кода" + +#: IDF/Form/TabsConf.php:40 IDF/gettexttemplates/idf/admin/base.html.php:5 +#: IDF/gettexttemplates/idf/base-full.html.php:9 +#: IDF/gettexttemplates/idf/base-full.html~.php:8 +#: IDF/gettexttemplates/idf/base.html.php:9 +#: IDF/gettexttemplates/idf/base.html~.php:8 +msgid "Documentation" +msgstr "Документация" + +#: IDF/Form/TabsConf.php:41 IDF/gettexttemplates/idf/admin/base.html.php:7 +#: IDF/gettexttemplates/idf/base-full.html.php:11 +#: IDF/gettexttemplates/idf/base-full.html~.php:10 +#: IDF/gettexttemplates/idf/base.html.php:11 +#: IDF/gettexttemplates/idf/base.html~.php:10 +msgid "Source" +msgstr "Исходный код" + +#: IDF/Form/TabsConf.php:42 IDF/gettexttemplates/idf/base-full.html.php:10 +#: IDF/gettexttemplates/idf/base-full.html~.php:9 +#: IDF/gettexttemplates/idf/base.html.php:10 +#: IDF/gettexttemplates/idf/base.html~.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:17 +msgid "Issues" +msgstr "Проблемы" + +#: IDF/Form/TabsConf.php:50 +msgid "Open to all" +msgstr "Открыто для всех" + +#: IDF/Form/TabsConf.php:51 +msgid "Signed in users" +msgstr "Вошедшие пользователи" + +#: IDF/Form/TabsConf.php:54 +msgid "Closed" +msgstr "Закрытый" + +#: IDF/Form/TabsConf.php:84 +#, fuzzy +msgid "Others" +msgstr "Другой" + +#: IDF/Form/TabsConf.php:107 +msgid "Extra authorized users" +msgstr "Дополнительные авторизованные пользователи" + +#: IDF/Form/Upload.php:59 IDF/Form/WikiResourceCreate.php:65 +#: IDF/Form/WikiResourceUpdate.php:56 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:7 +#: IDF/Views/Download.php:64 IDF/Views/Download.php:346 +msgid "File" +msgstr "Файл" + +#: IDF/Form/Upload.php:87 IDF/Form/WikiResourceCreate.php:96 +#: IDF/Form/WikiResourceUpdate.php:83 +msgid "For security reasons, you cannot upload a file with this extension." +msgstr "В целях безопасности нельзя загружать файлы с данным расширением." + +#: IDF/Form/Upload.php:120 +#, fuzzy, php-format +msgid "You cannot provide more than one label from the %s class to a download." +msgstr "Вы не может указать больше чем метки из %s класса страницы." + +#: IDF/Form/UploadArchive.php:41 +#, fuzzy +msgid "Archive file" +msgstr "Архив" + +#: IDF/Form/UploadArchive.php:67 +#, fuzzy, php-format +msgid "" +"For security reasons, you cannot upload a file (%s) with this extension." +msgstr "В целях безопасности нельзя загружать файлы с данным расширением." + +#: IDF/Form/UploadArchive.php:98 +#, fuzzy, php-format +msgid "" +"You cannot provide more than label from the %1$s class to a download (%2$s)." +msgstr "Вы не можете указать больше чем метку из класса %s к проблеме." + +#: IDF/Form/UploadArchive.php:109 +#, php-format +msgid "" +"A file with the name \"%s\" has already been uploaded and is not marked to " +"be replaced." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:41 +msgid "The archive does not exist." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:48 +#, php-format +msgid "The archive could not be read (code %d)." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:53 +msgid "The archive does not contain a manifest.xml." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:61 +#, php-format +msgid "The archive's manifest is invalid: %s" +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:77 +#, php-format +msgid "The entry %d in the manifest is missing a file name." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:82 +#, php-format +msgid "The entry %d in the manifest is missing a summary." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:86 +msgid "The manifest must not reference itself." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:91 +#, php-format +msgid "The entry %s in the manifest does not exist in the archive." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:96 +#, php-format +msgid "The entry %s in the manifest is referenced more than once." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:108 +#, php-format +msgid "The entry %s in the manifest has more than the six allowed labels set." +msgstr "" + +#: IDF/Form/UploadConf.php:53 +msgid "Predefined download labels" +msgstr "Предопределенные метки скачивания" + +#: IDF/Form/UploadConf.php:62 +msgid "Each download may have at most one label with each of these classes" +msgstr "Каждый файл может иметь не более одной метки с каждым из этих классов" + +#: IDF/Form/UserAccount.php:61 +msgid "" +"If you change your email address, an email will be sent to the new address " +"to confirm it." +msgstr "" +"Если Вы измените адрес эл. почты, то на него будет выслано письмо для " +"подтверждения адреса." + +#: IDF/Form/UserAccount.php:80 +msgid "Leave blank if you do not want to change your password." +msgstr "Оставьте поле пустым, если Вы не хотите менять пароль." + +#: IDF/Form/UserAccount.php:166 +msgid "" +"Paste an SSH or monotone public key. Be careful to not provide your private " +"key here!" +msgstr "" +"Вставьте публичный ключ SSH или monotone. Будьте внимательны и не " +"перепутайте с Вашим личным ключом!" + +#: IDF/Form/UserAccount.php:171 +#, fuzzy +msgid "Add a secondary email address" +msgstr "Добавить дополнительный e-mail" + +#: IDF/Form/UserAccount.php:173 +#, fuzzy +msgid "You will get an email to confirm that you own the address you specify." +msgstr "Вы получите письмо для подтверждения введенного адреса." + +#: IDF/Form/UserAccount.php:200 +msgid "Confirm your new email address." +msgstr "Подтвердите ваш новый адрес электронной почты." + +#: IDF/Form/UserAccount.php:203 +#, php-format +msgid "" +"A validation email has been sent to \"%s\" to validate the email address " +"change." +msgstr "" +"Проверочное письмо было отправлено на адрес \"%s\" для подтверждения " +"изменения адреса." + +#: IDF/Form/UserAccount.php:341 +msgid "" +"Please check the key as it does not appear to be a valid SSH public key." +msgstr "" +"Пожалуйста, проверьте ключ, поскольку он не выглядит как публичный SSH ключ." + +#: IDF/Form/UserAccount.php:363 +msgid "" +"Please check the key as it does not appear to be a valid monotone public key." +msgstr "" +"Пожалуйста, проверьте ключ, поскольку он не выглядит действительным открытым " +"ключом monotone." + +#: IDF/Form/UserAccount.php:371 +msgid "Public key looks like neither an SSH nor monotone public key." +msgstr "Публичный ключ не выглядит ни как SSH, ни как monotone ключ." + +#: IDF/Form/UserAccount.php:383 +msgid "You already have uploaded this key." +msgstr "Вы уже загружали это ключ." + +#: IDF/Form/UserChangeEmail.php:63 +msgid "" +"The validation key is not valid. Please copy/paste it from your confirmation " +"email." +msgstr "" +"Неверный проверочный ключ. Пожалуйста, скопируйте / вставьте его из письма с " +"подтверждением." + +#: IDF/Form/WikiConf.php:49 +msgid "Predefined documentation page labels" +msgstr "Предопределенные метки страницы документации" + +#: IDF/Form/WikiConf.php:58 +msgid "" +"Each documentation page may have at most one label with each of these classes" +msgstr "" +"Каждая страница документации может иметь не более одной метки с каждым из " +"этих классов" + +#: IDF/Form/WikiPageCreate.php:38 +msgid "" +"# Introduction\n" +"\n" +"Add your content here.\n" +"\n" +"\n" +"# Details\n" +"\n" +"Add your content here. Format your content with:\n" +"\n" +"* Text in **bold** or *italic*.\n" +"* Headings, paragraphs, and lists.\n" +"* Links to other [[WikiPage]].\n" +msgstr "" + +#: IDF/Form/WikiPageCreate.php:57 +msgid "PageName" +msgstr "ИмяСтраницы" + +#: IDF/Form/WikiPageCreate.php:60 IDF/Form/WikiPageUpdate.php:50 +msgid "Page title" +msgstr "Заголовок страницы" + +#: IDF/Form/WikiPageCreate.php:66 IDF/Form/WikiPageUpdate.php:56 +msgid "" +"The page name must contains only letters, digits and the dash (-) character." +msgstr "Имя страницы должно содержать только буквы, цифры и прочерк (-)." + +#: IDF/Form/WikiPageCreate.php:71 IDF/Form/WikiPageUpdate.php:61 +msgid "This one line description is displayed in the list of pages." +msgstr "Это однострочное описание отображается в списке страниц ." + +#: IDF/Form/WikiPageCreate.php:108 IDF/Form/WikiPageUpdate.php:119 +#: IDF/Form/WikiResourceCreate.php:78 +msgid "The title contains invalid characters." +msgstr "Название содержит недопустимые символы." + +#: IDF/Form/WikiPageCreate.php:114 IDF/Form/WikiPageUpdate.php:125 +msgid "A page with this title already exists." +msgstr "Страница с таким заголовком уже существует." + +#: IDF/Form/WikiPageCreate.php:150 IDF/Form/WikiPageUpdate.php:161 +#, fuzzy, php-format +msgid "You cannot provide more than one label from the %s class to a page." +msgstr "Вы не может указать больше чем метки из %s класса страницы." + +#: IDF/Form/WikiPageCreate.php:200 +msgid "Initial page creation" +msgstr "Создание первоначальной страницы" + +#: IDF/Form/WikiPageDelete.php:39 +msgid "Yes, I understand that the page and all its revisions will be deleted." +msgstr "Да, я понимаю, что страница и все ее версии будут удалены." + +#: IDF/Form/WikiPageDelete.php:50 IDF/Form/WikiResourceDelete.php:50 +msgid "You need to confirm the deletion." +msgstr "Вам необходимо подтвердить удаление." + +#: IDF/Form/WikiPageUpdate.php:83 IDF/Form/WikiResourceUpdate.php:67 +msgid "One line to describe the changes you made." +msgstr "Одна строка для описания внесенных изменений." + +#: IDF/Form/WikiResourceCreate.php:40 +msgid "ResourceName" +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:44 +msgid "Resource title" +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:50 +#, fuzzy +msgid "" +"The resource name must contains only letters, digits and the dash (-) " +"character." +msgstr "Имя страницы должно содержать только буквы, цифры и прочерк (-)." + +#: IDF/Form/WikiResourceCreate.php:55 IDF/Form/WikiResourceUpdate.php:47 +#, fuzzy +msgid "This one line description is displayed in the list of resources." +msgstr "Это однострочное описание отображается в списке страниц ." + +#: IDF/Form/WikiResourceCreate.php:84 +#, fuzzy +msgid "A resource with this title already exists." +msgstr "Страница с таким заголовком уже существует." + +#: IDF/Form/WikiResourceCreate.php:142 +#, fuzzy +msgid "Initial resource creation" +msgstr "Создание первоначальной страницы" + +#: IDF/Form/WikiResourceDelete.php:39 +#, fuzzy +msgid "" +"Yes, I understand that the resource and all its revisions will be deleted." +msgstr "Да, я понимаю, что страница и все ее версии будут удалены." + +#: IDF/Form/WikiResourceUpdate.php:89 +#, php-format +msgid "" +"The mime type of the uploaded file \"%1$s\" does not match the mime type of " +"this resource \"%2$s\"" +msgstr "" + +#: IDF/Form/WikiResourceUpdate.php:97 +msgid "The current version of the resource and the uploaded file are equal." +msgstr "" + +#: IDF/Gconf.php:60 IDF/Search/Occ.php:56 +msgid "model class" +msgstr "класс модели" + +#: IDF/Gconf.php:66 IDF/Search/Occ.php:62 +msgid "model id" +msgstr "ID модели" + +#: IDF/gettexttemplates/idf/admin/base.html.php:3 +msgid "Project Summary" +msgstr "Краткое описание проекта" + +#: IDF/gettexttemplates/idf/admin/base.html.php:6 +msgid "Issue Tracking" +msgstr "Слежение за проблемами" + +#: IDF/gettexttemplates/idf/admin/base.html.php:8 +msgid "Project Members" +msgstr "Участники проекта" + +#: IDF/gettexttemplates/idf/admin/base.html.php:9 +msgid "Tabs Access and Notifications" +msgstr "Права и уведомления" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:3 +#: IDF/gettexttemplates/idf/admin/issue-tracking.html.php:3 +#: IDF/gettexttemplates/idf/admin/wiki.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/labels.html.php:3 +msgid "" +"\n" +"

Instructions:

\n" +"

List one status value per line in desired sort-order.

\n" +"

Optionally, use an equals-sign to document the meaning of each status " +"value.

\n" +msgstr "" +"\n" +"

Инструкции:

\n" +"

Указывайте значение статуса по одному на строку в нужном порядке.

\n" +"

При необходимости, используйте знак равенства для описания значение " +"каждого статуса.

\n" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:8 +msgid "" +"

The webhook URL setting specifies an URL to which a HTTP PUT\n" +"request is sent after a new download has been added or to which a HTTP " +"POST\n" +"request is sent after an existing download has been updated.\n" +"If this field is empty, notifications are disabled.

\n" +"\n" +"

Only properly-escaped HTTP URLs are supported, for " +"example:

\n" +"\n" +"
    \n" +"
  • http://domain.com/upload
  • \n" +"
  • http://domain.com/upload?my%20param
  • \n" +"
\n" +"\n" +"

In addition, the URL may contain the following \"%\" notation, which\n" +"will be replaced with specific project values for each download:

\n" +"\n" +"
    \n" +"
  • %p - project name
  • \n" +"
  • %d - download id
  • \n" +"
\n" +"\n" +"

For example, updating download 123 of project 'my-project' with\n" +"web hook URL http://mydomain.com/%p/%d would send a POST " +"request to\n" +"http://mydomain.com/my-project/123.

" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:31 +#: IDF/gettexttemplates/idf/admin/source.html.php:30 +msgid "Web-Hook authentication key:" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:32 +#: IDF/gettexttemplates/idf/admin/issue-tracking.html.php:8 +#: IDF/gettexttemplates/idf/admin/members.html.php:13 +#: IDF/gettexttemplates/idf/admin/source.html.php:31 +#: IDF/gettexttemplates/idf/admin/summary.html.php:11 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:12 +#: IDF/gettexttemplates/idf/admin/wiki.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/forge/index.html.php:13 +#: IDF/gettexttemplates/idf/gadmin/projects/labels.html.php:8 +msgid "Save Changes" +msgstr "Сохранить изменения" + +#: IDF/gettexttemplates/idf/admin/members.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:3 +msgid "" +"\n" +"

Instructions:

\n" +"

Specify each person by its login. Each person must have already " +"registered with the given login.

\n" +"

Separate the logins with commas and/or new lines.

\n" +msgstr "" +"\n" +"

Инструкция:

\n" +"

Укажите логин каждого участника. Каждый участник должен быть уже " +"зарегистрирован с этим логином.

\n" +"

Разделяйте логины запятыми и/или новой строкой.

\n" + +#: IDF/gettexttemplates/idf/admin/members.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:8 +msgid "" +"\n" +"

Notes:

\n" +"

A project owner may make any change to this project, including removing " +"other project owners. You need to be carefull when you give owner rights.\n" +"

A project member will not have access to the administration area but will " +"have more options available in the use of the project.

\n" +msgstr "" +"\n" +"

Замечание:

\n" +"

Владелец проекта может вносить любые изменения в проект, включая удаление " +"других владельцев проекта.

\n" +"

Участники проекта не будут иметь доступа к администрированию но будут " +"иметь расширенные права при пользовании проектом.

\n" + +#: IDF/gettexttemplates/idf/admin/source.html.php:3 +msgid "You can find here the current repository configuration of your project." +msgstr "Вы можете найти здесь текущую конфигурацию репозитория вашего проекта." + +#: IDF/gettexttemplates/idf/admin/source.html.php:4 +msgid "" +"

The webhook URL setting specifies an URL to which a HTTP \n" +"%%hook_request_method%% request is sent after each " +"repository\n" +"commit. If this field is empty, notifications are disabled.

\n" +"\n" +"

Only properly-escaped HTTP URLs are supported, for " +"example:

\n" +"\n" +"
    \n" +"
  • http://domain.com/commit
  • \n" +"
  • http://domain.com/commit?my%20param
  • \n" +"
\n" +"\n" +"

In addition, the URL may contain the following \"%\" notation, which\n" +"will be replaced with specific project values for each commit:

\n" +"\n" +"
    \n" +"
  • %p - project name
  • \n" +"
  • %r - revision number
  • \n" +"
\n" +"\n" +"

For example, committing revision 123 to project 'my-project' with\n" +"post-commit URL http://mydomain.com/%p/%r would send a request " +"to\n" +"http://mydomain.com/my-project/123.

" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:26 +msgid "" +"The form contains some errors. Please correct them to update the source " +"configuration." +msgstr "" +"Форма содержит ошибки. Пожалуйста исправте их чтобы обновить настройки " +"исходного кода." + +#: IDF/gettexttemplates/idf/admin/source.html.php:27 +msgid "Repository type:" +msgstr "Тип репозитория:" + +#: IDF/gettexttemplates/idf/admin/source.html.php:28 +msgid "Repository access:" +msgstr "Доступ к репозиторию:" + +#: IDF/gettexttemplates/idf/admin/source.html.php:29 +msgid "Repository size:" +msgstr "Размер репозитория:" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

The description of the project can be improved using the Markdown syntax.

\n" +msgstr "" +"\n" +"

Инструкции:

\n" +"

Описание проекта может быть оформлено с использованием Markdown синтаксиса.

\n" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:7 +msgid "" +"The form contains some errors. Please correct them to update the summary." +msgstr "" +"Форма содержит ошибки. Пожалуйста исправте их чтобы обновить краткое " +"описание." + +#: IDF/gettexttemplates/idf/admin/summary.html.php:8 +msgid "Current logo" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:9 +#: IDF/gettexttemplates/idf/base-full.html.php:4 +#: IDF/gettexttemplates/idf/base-full.html~.php:4 +#: IDF/gettexttemplates/idf/base.html.php:4 +#: IDF/gettexttemplates/idf/base.html~.php:4 +#: IDF/gettexttemplates/idf/main-menu.html.php:8 +#: IDF/gettexttemplates/idf/project-list.html.php:4 +msgid "Project logo" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:10 +msgid "Your project does not have a logo configured yet." +msgstr "Ваш проект не имеет настроеного логотипа." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:3 +#, fuzzy +msgid "" +"This section allows you to configure project tabs access rights and " +"notifications." +msgstr "" +"Вы можете настроить здесь права доступа к вкладкам проекта и уведомлений." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:4 +msgid "" +"Tab access controls whether a single user can navigate into a particular " +"section of your project via the main menu or automatically generated object " +"links." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:5 +#, fuzzy +msgid "" +"If you mark a project as private, only the project members and " +"administrators, together with the extra authorized users you provide will " +"have access to the project as a whole. You will still be able to define " +"further access rights for the different tabs but the \"Open to all\" and " +"\"Signed in users\" will default to authorized users only." +msgstr "" +"Если вы отметите проект как частный, только участники проекта и " +"администраторы, а также дополнительные авторизованные пользователи будут " +"иметь доступ к проекту. Вы по-прежнему сможете изменить права доступа для " +"разных вкладок, но \"Открыто для всех\" и \"Зарегистрированные участники\" " +"по умолчанию будет доступно только авторизованным пользователям." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:6 +#, fuzzy +msgid "" +"For the extra authorized user list, specify each person by its login. Each " +"person must have already registered with the given login. Separate the " +"logins with commas and/or new lines." +msgstr "" +"Укажите логин каждого участника. Каждый участник должен быть уже " +"зарегистрирован с этим логином. Разделяйте логины запятыми и/или новой " +"строкой." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:7 +#, fuzzy +msgid "" +"Only project members and admins have write access to the source. If you " +"restrict the access to the source, anonymous access is not provided and the " +"users must authenticate themselves with their password or SSH key." +msgstr "" +"\n" +"Только участники и администраторы проекта имеют возможность изменять " +"исходный код.
\n" +"Если Вы ограничили доступ к исходному коду, анонимный доступ закрыт. Для " +"получения доступа к исходному коду пользователи должны авторизоваться " +"используя пароль или SSH ключ." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:8 +#, php-format +msgid "" +"Here you can configure who should be notified about changes in a particular " +"section. You can also configure additional addresses, like the one of a " +"mailing list, that should be notified. (Keep in mind that you might have to " +"register the sender address %%from_email%% to let the " +"mailing list actually accept notification emails.) Multiple email addresses " +"must be separated through commas (',')." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:9 +msgid "" +"The form contains some errors. Please correct them to update the access " +"rights." +msgstr "" +"Форма содержит ошибки. Пожалуйста исправте их чтобы обновить права доступа." + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:10 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:13 +msgid "Access Rights" +msgstr "Права доступа" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:11 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:14 +#, fuzzy +msgid "Notifications" +msgstr "Уведомление по электронной почте" + +#: IDF/gettexttemplates/idf/base-full.html.php:3 +#: IDF/gettexttemplates/idf/base-full.html~.php:3 +#: IDF/gettexttemplates/idf/base.html.php:3 +#: IDF/gettexttemplates/idf/base.html~.php:3 +#, php-format +msgid "" +"Sign in or create your account to create issues or " +"add comments" +msgstr "" +"Войдите или зарегистрируйтесь что бы добавить " +"проблему или комментарий" + +#: IDF/gettexttemplates/idf/base-full.html.php:6 +#: IDF/gettexttemplates/idf/base.html.php:6 +#: IDF/gettexttemplates/idf/project-list.html.php:6 +msgid "External link to project" +msgstr "" + +#: IDF/gettexttemplates/idf/base-full.html.php:7 +#: IDF/gettexttemplates/idf/base-full.html~.php:6 +#: IDF/gettexttemplates/idf/base.html.php:7 +#: IDF/gettexttemplates/idf/base.html~.php:6 +msgid "Project Home" +msgstr "Проект" + +#: IDF/gettexttemplates/idf/base-full.html.php:13 +#: IDF/gettexttemplates/idf/base-full.html~.php:12 +#: IDF/gettexttemplates/idf/base.html.php:13 +#: IDF/gettexttemplates/idf/base.html~.php:12 +msgid "Project Management" +msgstr "Управление проектом" + +#: IDF/gettexttemplates/idf/downloads/base.html.php:4 +#: IDF/gettexttemplates/idf/downloads/index.html.php:4 +#: IDF/Views/Download.php:235 +msgid "New Download" +msgstr "Добавить файл" + +#: IDF/gettexttemplates/idf/downloads/base.html.php:5 +#, fuzzy +msgid "Upload Archive" +msgstr "Архив" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:3 +msgid "" +"Each file must have a distinct name and file contents\n" +"cannot be changed, so be sure to include release numbers in each file\n" +"name." +msgstr "" +"Каждый файл должен иметь уникальное имя. Содержимое файла не может быть " +"изменено, так что не забудьте включить номер релиза в имя файла." + +#: IDF/gettexttemplates/idf/downloads/create.html.php:6 +#, php-format +msgid "" +"You can use the Markdown syntax for the description." +msgstr "" +"В описании Вы можете использовать Markdown синтаксис." + +#: IDF/gettexttemplates/idf/downloads/create.html.php:7 +msgid "The form contains some errors. Please correct them to submit the file." +msgstr "Форма содержит ошибки. Пожалуйста исправте их чтобы отправить файл." + +#: IDF/gettexttemplates/idf/downloads/create.html.php:8 +msgid "Submit File" +msgstr "Послать файл" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:9 +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:8 +#: IDF/gettexttemplates/idf/downloads/delete.html.php:7 +#: IDF/gettexttemplates/idf/downloads/view.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:21 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:14 +#: IDF/gettexttemplates/idf/issues/create.html.php:14 +#: IDF/gettexttemplates/idf/issues/view.html.php:27 +#: IDF/gettexttemplates/idf/register/confirmation.html.php:7 +#: IDF/gettexttemplates/idf/register/index.html.php:8 +#: IDF/gettexttemplates/idf/register/inputkey.html.php:5 +#: IDF/gettexttemplates/idf/review/create.html.php:12 +#: IDF/gettexttemplates/idf/review/view.html.php:41 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:5 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:13 +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:7 +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:9 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:5 +msgid "Cancel" +msgstr "Отмена" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:10 +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:9 +#: IDF/gettexttemplates/idf/register/inputkey.html.php:6 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:6 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:6 +msgid "Instructions" +msgstr "Инструкции" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:3 +msgid "" +"The archive must include a manifest.xml file with meta " +"information about the\n" +"files to process inside the archive. All processed files must be unique or " +"replace existing files explicitely." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:5 +#, fuzzy, php-format +msgid "" +"You can learn more about the archive format here." +msgstr "" +"Если у Вас еще нет учетной записи Вы можете создать ее здесь." + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:6 +#, fuzzy +msgid "" +"The form contains some errors. Please correct them to submit the archive." +msgstr "Форма содержит ошибки. Пожалуйста исправте их чтобы отправить файл." + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:7 +#, fuzzy +msgid "Submit Archive" +msgstr "Послать файл" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:3 +msgid "" +"Attention! If you want to delete a specific version of your " +"software, maybe, someone is depending on this specific version to run his " +"systems. Are you sure, you will not affect anybody when removing this file?" +msgstr "" +"Внимание! Если вы хотите удалить определенную версию " +"программного обеспечения, имейте ввиду, что может быть работоспособность чей-" +"то системы зависит от этой определенной версии. Вы уверены, что удаление " +"этого файла не повлияет на чью-то систему?" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:4 +#, php-format +msgid "" +"Instead of deleting the file, you could mark it as " +"deprecated." +msgstr "" +"Вместо удаление файла, вы можете пометь его как " +"устаревший." + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:5 +#: IDF/gettexttemplates/idf/downloads/view.html.php:4 +#: IDF/gettexttemplates/idf/issues/attachment.html.php:4 +#: IDF/gettexttemplates/idf/issues/view.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:5 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:7 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:7 +#, php-format +msgid "by %%submitter%%" +msgstr "%%submitter%%" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:6 +msgid "Delete File" +msgstr "Удалить файл" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:8 +#: IDF/gettexttemplates/idf/downloads/view.html.php:14 +msgid "Uploaded:" +msgstr "Загружено:" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:9 +#: IDF/gettexttemplates/idf/downloads/view.html.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:29 +#: IDF/gettexttemplates/idf/review/view.html.php:27 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:12 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:14 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:14 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:15 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:17 +msgid "Updated:" +msgstr "Обновлено:" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:10 +#: IDF/gettexttemplates/idf/downloads/view.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:6 +#: IDF/gettexttemplates/idf/listProjects.html.php:17 +msgid "Downloads:" +msgstr "Файлы:" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:11 +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:7 +#: IDF/gettexttemplates/idf/downloads/view.html.php:17 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:6 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:6 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:11 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:16 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:10 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:21 +#: IDF/gettexttemplates/idf/issues/view.html.php:33 +#: IDF/gettexttemplates/idf/project-list.html.php:8 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:6 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:13 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:16 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:12 +#: IDF/IssueComment.php:157 IDF/Wiki/PageRevision.php:204 +msgid "Labels:" +msgstr "Ярлыки:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:3 +msgid "A new file is available for download:" +msgstr "Новый файл доступен для скачивания:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:4 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:6 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:5 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:8 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:4 +msgid "Hello," +msgstr "Привет," + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:6 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:5 +msgid "Project:" +msgstr "Проект: " + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:6 +msgid "Submitted by:" +msgstr "Размещен:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:8 +msgid "Download:" +msgstr "Загрузить:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/view.html.php:31 +#: IDF/gettexttemplates/idf/user/public.html.php:4 +msgid "Description:" +msgstr "Описание:" + +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:3 +msgid "A file download was updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/feedfragment.xml.php:3 +msgid "Details" +msgstr "Детали" + +#: IDF/gettexttemplates/idf/downloads/index.html.php:3 +#, php-format +msgid "See the deprecated files." +msgstr "Смотреть устаревшие файлы." + +#: IDF/gettexttemplates/idf/downloads/index.html.php:5 +msgid "Number of files:" +msgstr "Количество файлов:" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:3 +msgid "" +"Attention! This file is marked as deprecated, download it " +"only if you are sure you need this specific version." +msgstr "" +"Внимание! Этот файл помечен как устаревший. Скачивайте его, " +"только если вы уверены, что вам необходима именно эта конкретная версия." + +#: IDF/gettexttemplates/idf/downloads/view.html.php:5 +msgid "md5:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:6 +msgid "Changes" +msgstr "Изменения" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:7 +msgid "The form contains some errors. Please correct them to update the file." +msgstr "Форма содержит ошибки. Пожалуйста исправьте их для обновления файла." + +#: IDF/gettexttemplates/idf/downloads/view.html.php:8 +msgid "Update File" +msgstr "Обновить файл" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:10 +#: IDF/gettexttemplates/idf/downloads/view.html.php:12 +msgid "Remove this file" +msgstr "Удалить этот файл" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:11 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:18 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:7 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:12 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:12 +msgid "Trash" +msgstr "Мусор" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:13 +msgid "Delete this file" +msgstr "Удалить этот файл" + +#: IDF/gettexttemplates/idf/faq-api.html.php:3 +#: IDF/gettexttemplates/idf/faq-archive-format.html.php:3 +#: IDF/gettexttemplates/idf/faq.html.php:65 +msgid "Here we are, just to help you." +msgstr "Мы здесь, чтобы помогать Вам." + +#: IDF/gettexttemplates/idf/faq-api.html.php:4 +#: IDF/gettexttemplates/idf/faq-archive-format.html.php:4 +#: IDF/gettexttemplates/idf/faq.html.php:66 +#: IDF/gettexttemplates/idf/gadmin/base.html.php:4 +#: IDF/gettexttemplates/idf/index.html.php:4 IDF/Views/Admin.php:77 +#: IDF/Views.php:91 +msgid "Projects" +msgstr "Проекты" + +#: IDF/gettexttemplates/idf/faq.html.php:3 +#, fuzzy +msgid "" +"

This is simple:

\n" +"
    \n" +"
  1. Write in the comments \"This is a duplicate of issue 123\" or - if you " +"are a member of the crew -\n" +"directly add the \"duplicates\" relation with the value \"123\" below the " +"comment field. Change \"123\"\n" +"with the corresponding issue number.
  2. \n" +"
  3. Change the status of the current issue to Duplicate.
  4. \n" +"
  5. Submit the changes.
  6. \n" +"
" +msgstr "" +"

Это просто:

\n" +"
  1. Напишите в комментарии \"Это дубликат проблемы 123\", замените 123 " +"на соответствующий номер проблемы.
  2. \n" +"
  3. Измените статус текущей проблемы на Дубликат.
  4. \n" +"
  5. Отправьте изменения.
" + +#: IDF/gettexttemplates/idf/faq.html.php:11 +msgid "" +"You need to create an account on Gravatar, this takes about 5 minutes and is free." +msgstr "" +"Вам необходимо создать учетную запись на Gravatar, это займет около 5 минут и это бесплатно." + +#: IDF/gettexttemplates/idf/faq.html.php:12 +msgid "" +"\n" +"

To embed any previously uploaded resource into your wiki page, you can " +"use the [[!ResourceName]] syntax.

\n" +"\n" +"

The rendering of the resource can then be further fine-tuned:\n" +"

    \n" +"
  • [[!ImageResource, align=right, width=200]] renders " +"\"ImageResource\" right-aligned and scale its width to 200
  • \n" +"
  • [[!TextResource, align=center, width=300, height=300]] " +"renders \"TextResource\" in a centered, 300 by 300 px iframe
  • \n" +"
  • [[!AnyResource, preview=no]] does not render a preview of " +"the resource, but only provides a download link (default for binary " +"resources)
  • \n" +"
  • [[!BinaryResource, title=Download]] renders the download " +"link of \"BinaryResource\" with an alternative title
  • \n" +"
\n" +"

\n" +"\n" +"Resources are versioned, just like wiki pages. If you update a resource, old " +"wiki pages still show the state of the resource\n" +"at the time when the wiki page was edited. If you specifically want to " +"update a resource on a page, you therefor need to update\n" +"the resource at first and then also the page where it is referenced, " +"otherwise the change won't be visible until the next regular edit. \n" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:28 +msgid "" +"

If you have to publish many files at once for a new release, it is a very " +"tedious task\n" +"to upload them one after another and enter meta information like a summary, " +"a description or additional\n" +"labels for each of them.

\n" +"

InDefero therefore supports a special archive format that is basically a " +"standard zip file which comes with\n" +"some meta information. These meta information are kept in a special manifest " +"file, which is distinctly kept from\n" +"the rest of the files in the archive that should be published.

\n" +"

Once this archive has been uploaded, InDefero reads in the meta " +"information, unpacks the other files from\n" +"the archive and creates new individual downloads for each of them.

" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:36 +#, fuzzy, php-format +msgid "Learn more about the archive format." +msgstr "Узнать больше об API." + +#: IDF/gettexttemplates/idf/faq.html.php:37 +msgid "" +"The API (Application Programming Interface) is used to interact with " +"InDefero with another program. For example, this can be used to create a " +"desktop program to submit new tickets easily." +msgstr "" +"API (Application Programming Interface) используется для взаимодействия " +"InDefero с другой программой. Например, это может быть использовано для " +"создания пользовательских программ для легкого добавления проблем в трекер." + +#: IDF/gettexttemplates/idf/faq.html.php:38 +#, php-format +msgid "Learn more about the API." +msgstr "Узнать больше об API." + +#: IDF/gettexttemplates/idf/faq.html.php:39 +#: IDF/gettexttemplates/idf/faq.html.php:45 +msgid "What are the keyboard shortcuts?" +msgstr "Какие есть сочетания клавиш?" + +#: IDF/gettexttemplates/idf/faq.html.php:40 +#: IDF/gettexttemplates/idf/faq.html.php:60 +msgid "How to mark an issue as duplicate?" +msgstr "Как пометить проблему как дублирующую?" + +#: IDF/gettexttemplates/idf/faq.html.php:41 +#: IDF/gettexttemplates/idf/faq.html.php:61 +msgid "How can I display my head next to my comments?" +msgstr "Как я могу вставить мое лицо рядом с моими комментариями?" + +#: IDF/gettexttemplates/idf/faq.html.php:42 +#: IDF/gettexttemplates/idf/faq.html.php:62 +msgid "How can I embed images and other resources in my documentation pages?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:43 +#: IDF/gettexttemplates/idf/faq.html.php:63 +msgid "What is this \"Upload Archive\" functionality about?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:44 +#: IDF/gettexttemplates/idf/faq.html.php:64 +msgid "What is the API and how is it used?" +msgstr "Что такое API и как это используется?" + +#: IDF/gettexttemplates/idf/faq.html.php:46 +msgid "Shift+h: This help page." +msgstr "Shift+h: Эта помощь." + +#: IDF/gettexttemplates/idf/faq.html.php:47 +msgid "If you are in a project, you have the following shortcuts:" +msgstr "Находясь в проекте можете использовать следующие клавиши:" + +#: IDF/gettexttemplates/idf/faq.html.php:48 +msgid "Shift+u: Project updates." +msgstr "Shift+u: Обновления проекта." + +#: IDF/gettexttemplates/idf/faq.html.php:49 +msgid "Shift+d: Downloads." +msgstr "Shift+d: Файлы." + +#: IDF/gettexttemplates/idf/faq.html.php:50 +msgid "Shift+o: Documentation." +msgstr "Shift+o: Документация." + +#: IDF/gettexttemplates/idf/faq.html.php:51 +msgid "Shift+a: Create a new issue." +msgstr "Shift+a: Добавить новую проблему." + +#: IDF/gettexttemplates/idf/faq.html.php:52 +msgid "Shift+i: List of open issues." +msgstr "Shift+i: Список открытых проблем." + +#: IDF/gettexttemplates/idf/faq.html.php:53 +msgid "Shift+m: The issues you submitted." +msgstr "Shift+m: Проблемы добавленные Вами." + +#: IDF/gettexttemplates/idf/faq.html.php:54 +msgid "Shift+w: The issues assigned to you." +msgstr "Shift+w: Проблемы назначенные на Вас." + +#: IDF/gettexttemplates/idf/faq.html.php:55 +msgid "Shift+s: Source." +msgstr "Shift+s: Исходный код." + +#: IDF/gettexttemplates/idf/faq.html.php:56 +msgid "You also have the standard access keys:" +msgstr "У вас также есть стандартные клавиши:" + +#: IDF/gettexttemplates/idf/faq.html.php:57 +msgid "Alt+1: Home." +msgstr "Alt+1: Домой." + +#: IDF/gettexttemplates/idf/faq.html.php:58 +msgid "Alt+2: Skip the menus." +msgstr "Alt+2: Пропустить меню." + +#: IDF/gettexttemplates/idf/faq.html.php:59 +msgid "Alt+4: Search (when available)." +msgstr "Alt+4: Поиск (если доступен)." + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:3 +msgid "Forge" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:5 +msgid "People" +msgstr "Люди" + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:6 +msgid "Usher" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/forge/base.html.php:3 +#, fuzzy +msgid "Frontpage" +msgstr "страница" + +#: IDF/gettexttemplates/idf/gadmin/forge/index.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

You can set up a custom forge page that is used as entry page for the " +"forge instead of the plain project listing. This page is then also " +"accessible via the 'Home' link in main menu bar.

\n" +"

The content of the page can use the Markdown syntax with the Extra extension.

\n" +"

Additionally, the following macros are available:
\n" +"

    \n" +"
  • {projectlist, label=..., order=(name|activity), limit=...} - Renders a project list that can optionally be filtered by label, " +"ordered by 'name' or 'activity' and / or limited to a specific number of " +"projects.
  • \n" +"
\n" +"

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:3 +#: IDF/gettexttemplates/idf/main-menu.html.php:7 +msgid "Project List" +msgstr "Список проектов" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:4 +#: IDF/Views/Admin.php:110 +#, fuzzy +msgid "Project Labels" +msgstr "Список проектов" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:16 +#: IDF/gettexttemplates/idf/listProjects.html.php:6 IDF/Views/Admin.php:186 +msgid "Create Project" +msgstr "Создать проект" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:6 +msgid "Change Project Details" +msgstr "Изменить данные о проекте" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:3 +msgid "" +"You can select the type of repository you want. In the case of subversion, " +"you can use optionally a remote repository instead of the local one." +msgstr "" +"Вы можете выбрать желаемый тип хранилища. В случае subversion, вы можете " +"использовать удаленное хранилище вместо локального." + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:4 +msgid "" +"Once you have defined the repository type, you cannot change it." +msgstr "" +"После того как вы определили тип репозитория, вы не сможете его " +"изменить." + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:5 +msgid "" +"\n" +"

Specify each person by its login. Each person must have already " +"registered with the given login.

\n" +"

Separate the logins with commas and/or new lines.

\n" +msgstr "" +"\n" +"

Укажите пользователя используя его логин. Каждый пользователь должен быть " +"уже зарегистрирован с этим логином.

\n" +"

Разделяйте логины запятыми и/или новой строкой.

\n" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:14 +msgid "" +"The form contains some errors. Please correct them to create the project." +msgstr "Форма содержит ошибки. Пожалуйста исправте их чтобы создать проект." + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:15 +msgid "Provide at least one owner for the project or use a template." +msgstr "Укажите как минимум одного владельца проекта или используйте шаблон." + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:15 +msgid "Instructions:" +msgstr "Инструкции:" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:3 +#, php-format +msgid "" +"Confirmation code to confirm the deletion of the project: \n" +"%%code%%." +msgstr "" +"Код подтверждения для удаления проекта:\n" +"%%code%%." + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:5 +msgid "" +"\n" +"Attention! Deleting a project is a one second operation\n" +"with the consequences that all the data related to the \n" +"project will be deleted.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:10 +msgid "" +"The form contains some errors. Please correct them to delete the project." +msgstr "Форма содержит ошибки. Пожалуйста исправте их чтобы удалить проект." + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:11 +msgid "Project Statistics" +msgstr "Статистика проекта" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:12 +msgid "Tab" +msgstr "Табуляция" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:13 +msgid "Number" +msgstr "Номер" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:15 +msgid "Code reviews" +msgstr "Рецензировании кода" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:16 +#: IDF/Views/Project.php:93 +msgid "Commits" +msgstr "Коммиты" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:18 +msgid "Documentation pages" +msgstr "Страница документации" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:19 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:20 +msgid "Delete Project" +msgstr "Удалить проект" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:22 +msgid "" +"For large projects, the suppression can take a while, please be patient." +msgstr "" +"Для больших проектов, подавление может занять некоторое время, пожалуйста, " +"будьте терпеливы." + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:3 +msgid "Space Usage Statistics" +msgstr "Статистика использования простанства" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:4 +msgid "Repositories:" +msgstr "Репозитории:" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:5 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:11 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:18 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:16 +msgid "Attachments:" +msgstr "Вложения:" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:7 +msgid "Database:" +msgstr "Базы данных:" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:8 +msgid "Total Forge:" +msgstr "Всего в хранилище:" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:13 +msgid "" +"The form contains some errors. Please correct them to update the project." +msgstr "Форма содержит ошибки. Пожалуйста исправте их чтобы обновить проект." + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:14 +msgid "Provide at least one owner for the project." +msgstr "Укажите по крайней мере одного владельца проекта." + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:15 +msgid "Update Project" +msgstr "Обновить проект" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:19 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:20 +msgid "Delete this project" +msgstr "Удалить этот проект" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:21 +msgid "You will be asked to confirm." +msgstr "Будет выдан запрос для подтвеждения." + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:3 +#: IDF/Views/Admin.php:264 +msgid "User List" +msgstr "Список пользователей" + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:13 +msgid "Update User" +msgstr "Обновить пользователя" + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:4 +msgid "Create User" +msgstr "Создать пользователя" + +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:3 +msgid "The form contains some errors. Please correct them to create the user." +msgstr "" +"Форма содержит некоторые ошибки. Пожалуйста, исправьте их, чтобы создать " +"пользователя." + +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:6 +msgid "The user password will be sent by email to the user." +msgstr "Пароль пользователя будет выслан ему по электронной почте." + +#: IDF/gettexttemplates/idf/gadmin/users/createuser-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"An account on the forge has been created for you by\n" +"the administrator %%admin%%.\n" +"\n" +"Please find here your details to access the forge:\n" +"\n" +" Address: %%url%%\n" +" Login: %%user.login%%\n" +" Password: %%password%%\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" +"Здравствуйте %%user%%,\n" +"\n" +"Учетная запись в хранилище была создана для Вас\n" +"администратором %%admin%%.\n" +"\n" +"Данные для доступа в хранилище:\n" +"\n" +" Адрес: %%url%%\n" +" Логин: %%user.login%%\n" +" Пароль: %%password%%\n" +"\n" +"С уважением,\n" +"Команда разработчиков\n" + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:3 +#, php-format +msgid "See not validated users." +msgstr "Смотреть не проверенных пользователей." + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:4 +msgid "

You have here an overview of the users registered in the forge.

" +msgstr "

Обзор всех пользователей, зарегистрированных на сервере.

" + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:5 +msgid "Number of users:" +msgstr "Количество пользователей:" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:3 +msgid "" +"If you are changing the email address of the user, you\n" +"need to ensure that you are providing a valid email\n" +"address" +msgstr "" +"Если вы хотите изменить адрес электронной почты\n" +"пользователя, вы должны убедиться, что\n" +"предоставляете действительный адрес." + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:6 +msgid "" +"If you give the user staff rights, the user will be\n" +"able to create new projects and update other non staff users.\n" +msgstr "" +"Если вы даете пользователю права персонала, пользователь сможет\n" +"создавать новые проекты и обновлять других пользователей не имеющих права " +"персонала.\n" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:9 +msgid "The form contains some errors. Please correct them to update the user." +msgstr "" +"Форма содержит ошибки. Пожалуйста исправте их чтобы обновить пользователя." + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:10 +#: IDF/gettexttemplates/idf/register/confirmation.html.php:4 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:4 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:4 +msgid "Login:" +msgstr "Логин:" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:11 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:5 +msgid "Public Profile" +msgstr "Публичный профиль" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:12 +msgid "Administrative" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/base.html.php:3 +msgid "Configured servers" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/base.html.php:4 +#: IDF/Views/Admin.php:421 +msgid "Usher control" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html~.php:3 +msgid "address" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html~.php:4 +msgid "port" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:5 +msgid "No connections found." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:3 +msgid "current server status:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:4 +msgid "startup" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:5 +msgid "shutdown" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:6 +msgid "reload server configuration:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:7 +msgid "reload" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:11 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:11 +msgid "Status explanation" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:9 +msgid "active with n total open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:10 +msgid "waiting for new connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:11 +msgid "usher is being shut down, not accepting connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:12 +msgid "" +"usher is shut down, all local servers are stopped and not accepting " +"connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:3 +msgid "server name" +msgstr "имя сервера" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:4 IDF/Issue.php:99 +#: IDF/Review.php:102 +msgid "status" +msgstr "статус" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:5 +msgid "action" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:6 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:6 +msgid "No monotone servers configured." +msgstr "Monotone сервера не сконфигурированы." + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:7 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:7 +msgid "stop" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:8 +msgid "start" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:9 +msgid "kill" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:10 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:10 +msgid "active connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:12 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:12 +msgid "remote server without open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:13 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:13 +msgid "server with n open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:14 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:14 +msgid "local server running, without open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:15 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:15 +msgid "local server not running, waiting for connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:16 +msgid "local server is about to stop, n connections still open" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:17 +msgid "local server not running, not accepting connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:18 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:18 +msgid "usher is shut down, not running and not accepting connections" +msgstr "" + +#: IDF/gettexttemplates/idf/index.atom.php:3 +#, php-format +msgid "Personal project feed for %%user%%." +msgstr "Personal project feed for %%user%%." + +#: IDF/gettexttemplates/idf/index.html.php:3 +#: IDF/gettexttemplates/idf/main-menu.html.php:6 +msgid "Home" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:3 +#, php-format +msgid "Attachment to issue %%issue.id%%" +msgstr "Вложение к тикету %%issue.id%%" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:5 +#: IDF/gettexttemplates/idf/review/view.html.php:35 +#: IDF/gettexttemplates/idf/source/commit.html.php:23 +#: IDF/gettexttemplates/idf/source/commit.html~.php:22 +#: IDF/gettexttemplates/idf/source/git/file.html.php:6 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:7 +msgid "Archive" +msgstr "Архив" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:6 +#: IDF/gettexttemplates/idf/source/git/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:12 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:12 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:10 +msgid "Download this file" +msgstr "Скачать этот файл" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:7 +#: IDF/gettexttemplates/idf/issues/view.html.php:28 +#: IDF/gettexttemplates/idf/review/view.html.php:26 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:13 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:14 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:16 +msgid "Created:" +msgstr "Создан:" + +#: IDF/gettexttemplates/idf/issues/base.html.php:4 +msgid "All Issues" +msgstr "Все проблемы" + +#: IDF/gettexttemplates/idf/issues/base.html.php:5 +msgid "My Issues" +msgstr "Мои проблемы" + +#: IDF/gettexttemplates/idf/issues/base.html.php:6 +msgid "My watch list" +msgstr "Мой список слежения" + +#: IDF/gettexttemplates/idf/issues/base.html.php:7 +#: IDF/gettexttemplates/idf/issues/by-label.html.php:6 +#: IDF/gettexttemplates/idf/issues/index.html.php:5 +#: IDF/gettexttemplates/idf/issues/project-watchlist.html.php:5 +#: IDF/gettexttemplates/idf/issues/search.html.php:8 +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:5 +msgid "New Issue" +msgstr "Новая проблема" + +#: IDF/gettexttemplates/idf/issues/base.html.php:8 +#: IDF/gettexttemplates/idf/wiki/base.html.php:9 +msgid "Search" +msgstr "Искать" + +#: IDF/gettexttemplates/idf/issues/base.html.php:9 +msgid "Back to the issue" +msgstr "Назад к проблеме" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:3 +#, php-format +msgid "" +"

Open issues: %%open%%

\n" +"

Closed issues: %%closed%%

\n" +msgstr "" +"

Открытых проблем: %%open%%\n" +"

Закрытых проблем: %%closed%%

\n" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:7 +msgid "Label:" +msgstr "Ярлык:" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:8 +msgid "Completion:" +msgstr "Завершение:" + +#: IDF/gettexttemplates/idf/issues/create.html.php:3 +msgid "" +"

When you submit the issue do not forget to provide the following " +"information:

\n" +"
    \n" +"
  • The steps to reproduce the problem.
  • \n" +"
  • The version of the software and your operating system.
  • \n" +"
  • Any information that can help the developers to solve the issue.
  • \n" +"
  • Do not provide any password or confidential information!
  • \n" +"
" +msgstr "" +"

Когда вы отправляете проблему не забудьте указать следующую информацию: " +"

\n" +"
  • Шаги по воспроизведению проблемы.
  • \n" +"
  • Версии программного обеспечения и операционной системы.
  • \n" +"
  • Любая информация, которая поможет разработчикам решить проблему.
  • \n" +"
  • Не добавляйте никаких паролей или конфиденциальной информации!
  • \n" +"
" + +#: IDF/gettexttemplates/idf/issues/create.html.php:10 +msgid "The form contains some errors. Please correct them to submit the issue." +msgstr "Форма содержит ошибки. Пожалуйста исправте их чтобы добавить проблему." + +#: IDF/gettexttemplates/idf/issues/create.html.php:11 +#: IDF/gettexttemplates/idf/issues/create.html.php:13 +#: IDF/gettexttemplates/idf/issues/view.html.php:24 +#: IDF/gettexttemplates/idf/issues/view.html.php:26 +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:5 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:5 +msgid "Preview" +msgstr "Предпросмотр" + +#: IDF/gettexttemplates/idf/issues/create.html.php:12 +msgid "Submit Issue" +msgstr "Отправить проблему" + +#: IDF/gettexttemplates/idf/issues/create.html.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:34 +msgid "Attach file" +msgstr "Приложить файл" + +#: IDF/gettexttemplates/idf/issues/create.html.php:16 +#: IDF/gettexttemplates/idf/issues/create.html.php:17 +#: IDF/gettexttemplates/idf/issues/view.html.php:35 +#: IDF/gettexttemplates/idf/issues/view.html.php:36 +msgid "Attach another file" +msgstr "Приложить еще один файл" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:3 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:3 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:13 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:12 +#: IDF/gettexttemplates/idf/issues/view.html.php:18 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:3 +#: IDF/gettexttemplates/idf/review/view.html.php:38 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:11 +#: IDF/IssueComment.php:151 +msgid "Summary:" +msgstr "Краткое описание:" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:4 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:4 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:8 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:14 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:13 +#: IDF/gettexttemplates/idf/issues/view.html.php:19 +#: IDF/gettexttemplates/idf/issues/view.html.php:30 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:4 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/view.html.php:39 IDF/IssueComment.php:153 +msgid "Status:" +msgstr "Статус:" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:5 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:15 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:14 +#: IDF/gettexttemplates/idf/issues/view.html.php:20 +#: IDF/gettexttemplates/idf/issues/view.html.php:31 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:5 +#: IDF/IssueComment.php:155 +msgid "Owner:" +msgstr "Владелец:" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:17 +#: IDF/gettexttemplates/idf/issues/view.html.php:22 IDF/IssueComment.php:159 +msgid "Relations:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/forge-watchlist.html.php:3 +#: IDF/gettexttemplates/idf/issues/index.html.php:3 +#: IDF/gettexttemplates/idf/issues/project-watchlist.html.php:3 +#, php-format +msgid "" +"

Open issues: %%open%%

\n" +"

Closed issues: %%closed%%

" +msgstr "" +"

Открытых проблем: %%open%%\n" +"

Закрытых проблем: %%closed%%

" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:3 +#, fuzzy +msgid "A new issue has been created and assigned to you:" +msgstr "" +"Новая проблема была создана и назначена\n" +"на Вас:" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:4 +#, fuzzy +msgid "A new issue has been created:" +msgstr "Новые комит был создан:" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:8 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:11 +msgid "Reported by:" +msgstr "Сообщил:" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:12 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:19 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:17 +msgid "Issue:" +msgstr "Проблема:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:3 +#, fuzzy +msgid "The following issue you are owning has been updated:" +msgstr "Следующая проблема была обновлена:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:4 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:3 +msgid "The following issue has been updated:" +msgstr "Следующая проблема была обновлена:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:4 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:4 +#, php-format +msgid "By %%who%%, %%c.creation_dtime%%:" +msgstr "%%who%%, %%c.creation_dtime%%:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:10 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:9 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:12 +msgid "URL:" +msgstr "URL:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:12 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:11 +msgid "Comments (last first):" +msgstr "Комментарии (последние первыми):" + +#: IDF/gettexttemplates/idf/issues/search.html.php:3 +#, php-format +msgid "" +"\n" +"

Found open issues: %%open%%

\n" +"

Found closed issues: %%closed" +"%%

" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/search.html.php:6 +#, php-format +msgid "" +"

Label:\n" +"%%tag.class%%:" +"%%tag.name%%

" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:3 +#, fuzzy +msgid "View all open issues." +msgstr "Таблица показывает открытые проблемы." + +#: IDF/gettexttemplates/idf/issues/summary.html.php:4 +#, fuzzy +msgid "Create an issue." +msgstr "Создать пользователя" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:5 +#, php-format +msgid "" +"The issue tracker is empty.
Create your " +"first issue." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:6 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:4 +#, php-format +msgid "Unresolved: By %%key%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:7 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:5 +msgid "Status Summary" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:8 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:6 +msgid "Unresolved: By Assignee" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html~.php:3 +#, php-format +msgid "" +"The issue tracker is empty.
You can create your first issue here." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:3 +#, php-format +msgid "" +"See the %%nb_submit_closed%% closed." +msgid_plural "" +"See the %%nb_submit_closed%% closed." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:4 +#, php-format +msgid "" +"See the %%nb_owner_closed%% closed." +msgid_plural "" +"See the %%nb_owner_closed%% closed." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:6 +#: IDF/gettexttemplates/idf/user/dashboard.html.php:7 +msgid "Submitted issues:" +msgstr "Отправленные проблемы:" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:7 +#: IDF/gettexttemplates/idf/user/dashboard.html.php:6 +msgid "Working issues:" +msgstr "Проблемы в работе:" + +#: IDF/gettexttemplates/idf/issues/view.html.php:3 +#, php-format +msgid "Reported by %%submitter%%, %%c.creation_dtime%%" +msgstr "Сообщено %%submitter%%, %%c.creation_dtime%%" + +#: IDF/gettexttemplates/idf/issues/view.html.php:4 +#: IDF/gettexttemplates/idf/review/view.html.php:22 +#, php-format +msgid "" +"Comment %%i%% by %%submitter%%, %%c.creation_dtime%%" +msgstr "" +"Комментированно %%i%% %%submitter%%, %%c." +"creation_dtime%%" + +#: IDF/gettexttemplates/idf/issues/view.html.php:5 +#, php-format +msgid "Sign in to reply to this comment." +msgstr "Войдите, чтобы ответить на комментарий." + +#: IDF/gettexttemplates/idf/issues/view.html.php:6 +msgid "" +"This issue is marked as closed, add a comment only if you think this issue " +"is still valid and more work is needed to fully fix it." +msgstr "" +"Эта проблема отмечена как закрытая. Добавляйте комментарий, только если вы " +"думаете, что этот вопрос остается в силе и многое еще предстоит сделать, " +"чтобы полностью исправить ее." + +#: IDF/gettexttemplates/idf/issues/view.html.php:8 +#, php-format +msgid "%%interested%% person" +msgid_plural "%%interested%% persons" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:9 +#, php-format +msgid "This issue %%verb%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:10 +msgid "Remove this issue from your watch list" +msgstr "Удалить проблему из Вашего листа слежения." + +#: IDF/gettexttemplates/idf/issues/view.html.php:11 +msgid "Add this issue to your watch list" +msgstr "Добавить проблему в Ваш лист слежения." + +#: IDF/gettexttemplates/idf/issues/view.html.php:12 +#, fuzzy +msgid "View the previous closed issue" +msgstr "Таблица показывает закрытые проблемы." + +#: IDF/gettexttemplates/idf/issues/view.html.php:13 +msgid "View the previous open issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:14 +#, fuzzy +msgid "View the next closed issue" +msgstr "Таблица показывает закрытые проблемы." + +#: IDF/gettexttemplates/idf/issues/view.html.php:15 +#, fuzzy +msgid "View the next open issue" +msgstr "Таблица показывает открытые проблемы." + +#: IDF/gettexttemplates/idf/issues/view.html.php:16 +msgid "download" +msgstr "скачать" + +#: IDF/gettexttemplates/idf/issues/view.html.php:17 +msgid "view" +msgstr "просмотр" + +#: IDF/gettexttemplates/idf/issues/view.html.php:23 +msgid "The form contains some errors. Please correct them to change the issue." +msgstr "Форма содержит ошибки. Пожалуйста исправте их чтобы изменить проблему." + +#: IDF/gettexttemplates/idf/issues/view.html.php:25 +msgid "Submit Changes" +msgstr "Сохранить изменения" + +#: IDF/gettexttemplates/idf/issues/view.html.php:32 +msgid "Followed by:" +msgstr "Наблюдатели:" + +#: IDF/gettexttemplates/idf/listProjects.html.php:3 +#, fuzzy, php-format +msgid "1 project" +msgid_plural "%%label.project_count%% projects" +msgstr[0] "проект" +msgstr[1] "проект" +msgstr[2] "проект" + +#: IDF/gettexttemplates/idf/listProjects.html.php:4 +#, php-format +msgid "Remove filter for %%tag%%" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:5 +msgid "No projects managed with InDefero were found." +msgstr "Проектов под управлением InDefero не найдено." + +#: IDF/gettexttemplates/idf/listProjects.html.php:7 +msgid "Filter projects by label" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:8 +#, fuzzy +msgid "No projects with labels found." +msgstr "Проектов не найдено." + +#: IDF/gettexttemplates/idf/listProjects.html.php:9 +msgid "Order" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:10 +#, fuzzy +msgid "By name" +msgstr "имя" + +#: IDF/gettexttemplates/idf/listProjects.html.php:11 +msgid "By activity" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:12 +msgid "Filtered project stats" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:13 +msgid "Members:" +msgstr "Участников:" + +#: IDF/gettexttemplates/idf/listProjects.html.php:14 +msgid "Issues:" +msgstr "Проблем:" + +#: IDF/gettexttemplates/idf/listProjects.html.php:15 +msgid "Commits:" +msgstr "Коммитов:" + +#: IDF/gettexttemplates/idf/listProjects.html.php:16 +msgid "Documentations:" +msgstr "Документаций:" + +#: IDF/gettexttemplates/idf/listProjects.html.php:18 +msgid "Code reviews:" +msgstr "Рецензий кода:" + +#: IDF/gettexttemplates/idf/login_form.html.php:3 +#, fuzzy, php-format +msgid "" +"You can create an account if you don't have one yet." +msgstr "" +"В описании Вы можете использовать Markdown синтаксис." + +#: IDF/gettexttemplates/idf/login_form.html.php:4 +msgid "What is your account information?" +msgstr "Каковы данные Вашей учетной записи?" + +#: IDF/gettexttemplates/idf/login_form.html.php:5 +msgid "My login is" +msgstr "Мой логин" + +#: IDF/gettexttemplates/idf/login_form.html.php:6 +msgid "My password is" +msgstr "Мой пароль" + +#: IDF/gettexttemplates/idf/login_form.html.php:7 +msgid "Sign in" +msgstr "Войти" + +#: IDF/gettexttemplates/idf/login_form.html.php:8 +msgid "I lost my password!" +msgstr "Я забыл пароль!" + +#: IDF/gettexttemplates/idf/login_form.html.php:9 +msgid "Welcome." +msgstr "Добро пожаловать." + +#: IDF/gettexttemplates/idf/login_form.html.php:10 +msgid "It takes less than a minute to create your account." +msgstr "Создание учетной записи займет меньше минуты." + +#: IDF/gettexttemplates/idf/main-menu.html.php:3 +#, php-format +msgid "" +"Welcome, %%user%%." +msgstr "" +"Привет, %%user%%." + +#: IDF/gettexttemplates/idf/main-menu.html.php:4 +msgid "Sign Out" +msgstr "Выход" + +#: IDF/gettexttemplates/idf/main-menu.html.php:5 +msgid "Sign in or create your account" +msgstr "Войти или создать учетную запись" + +#: IDF/gettexttemplates/idf/main-menu.html.php:10 IDF/Views/Admin.php:40 +msgid "Forge Management" +msgstr "Управление хранилищем" + +#: IDF/gettexttemplates/idf/main-menu.html.php:11 +msgid "Help and accessibility features" +msgstr "Справка и специальные возможности" + +#: IDF/gettexttemplates/idf/main-menu.html.php:12 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:14 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:14 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:15 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:13 +msgid "Help" +msgstr "Помощь" + +#: IDF/gettexttemplates/idf/project/home.html.php:3 +#: IDF/gettexttemplates/idf/project/timeline.html.php:4 IDF/Views.php:46 +msgid "Welcome" +msgstr "Добро пожаловать" + +#: IDF/gettexttemplates/idf/project/home.html.php:4 +#: IDF/gettexttemplates/idf/project/timeline.html.php:5 +msgid "Latest Updates" +msgstr "Последние изменения" + +#: IDF/gettexttemplates/idf/project/home.html.php:5 +msgid "Featured Downloads" +msgstr "Рекомендуемые загрузки" + +#: IDF/gettexttemplates/idf/project/home.html.php:6 +#, fuzzy +msgid "Show more featured downloads" +msgstr "Рекомендуемые загрузки" + +#: IDF/gettexttemplates/idf/project/home.html.php:7 +#: IDF/gettexttemplates/idf/project/home.html.php:10 +msgid "show more..." +msgstr "еще..." + +#: IDF/gettexttemplates/idf/project/home.html.php:8 +msgid "Featured Documentation" +msgstr "Рекомендуемая документация" + +#: IDF/gettexttemplates/idf/project/home.html.php:9 +#, fuzzy +msgid "Show more featured documentation" +msgstr "Рекомендуемая документация" + +#: IDF/gettexttemplates/idf/project/home.html.php:11 +msgid "Development Team" +msgstr "Команда разработчиков" + +#: IDF/gettexttemplates/idf/project/home.html.php:12 +msgid "Admins" +msgstr "Администраторы" + +#: IDF/gettexttemplates/idf/project/home.html.php:13 +msgid "Happy Crew" +msgstr "Счастливая комманда" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:3 +msgid "Latest updates" +msgstr "Последние изменения" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:6 +#: IDF/Views/Project.php:90 +msgid "All Updates" +msgstr "Обновления" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:7 +msgid "Filter by type" +msgstr "Фильтр по типу" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:8 +msgid "Subscribe to this timeline" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:9 +msgid "RSS" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:10 +msgid "Atom feed" +msgstr "" + +#: IDF/gettexttemplates/idf/project-list.html.php:3 +msgid "Project activity: %%activity%%%" +msgstr "" + +#: IDF/gettexttemplates/idf/project-list.html.php:9 +msgid "n/a" +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation-email.txt.php:3 +#, php-format +msgid "" +"Hello,\n" +"\n" +"You have requested the creation of an account to\n" +"participate in the life of a software project.\n" +"\n" +"To confirm the account please follow this link:\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following confirmation key:\n" +"\n" +"%%key%%\n" +"\n" +"If you are not interested any longer in taking\n" +"part in the life of the software project or if\n" +"you can't remember having requested the creation\n" +"of an account, please excuse us and simply ignore\n" +"this email. \n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" +"Здравствуйте,\n" +"\n" +"Вы запросили создание учетной записи для\n" +"участия в жизни проекта.\n" +"\n" +"Для подтверждения учетной записи пожалуйста перейдите по ссылке:\n" +"\n" +"%%url%%\n" +"\n" +"Или перейдите на страницу:\n" +"\n" +"%%urlik%%\n" +"\n" +"и введите следующий ключ:\n" +"\n" +"%%key%%\n" +"\n" +"Если вы больше не заинтересованы в\n" +"участии в жизни проекта или если\n" +"вы не можете вспомнить подобного запроса\n" +"пожалуйста извините нас и просто игнорируйте\n" +"это сообщение.\n" +"\n" +"С уважением,\n" +"Команда разработчиков.\n" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:3 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:3 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:3 +msgid "Oops, please check the form for errors." +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:5 +msgid "Email:" +msgstr "Эл. почта:" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:6 +msgid "Enable Your Account" +msgstr "Включите Вашу учетную запись" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:8 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:8 +msgid "" +"This is the last step, but just be sure to have the cookies enabled to log in afterwards." +msgstr "" +"Это последний шаг, но убедитесь, что включены cookies чтобы " +"войдите потом." + +#: IDF/gettexttemplates/idf/register/index.html.php:3 +#, fuzzy +msgid "" +"Read the terms and conditions – " +"basically \"Please be nice, we respect you\"." +msgstr "" +"Прочитайте условия – " +"основательно \"Будьте хорошими, мы Вас уважаем\"." + +#: IDF/gettexttemplates/idf/register/index.html.php:4 +#, fuzzy, php-format +msgid "" +"If you have just forgotten your login information, then there is no need to " +"create a new account. You can just recover your login " +"name and password." +msgstr "" +"Если Вы просто забыли данные для входа нет необходимости создавать новую " +"учетную запись. Просто перейдите сюда для " +"восстановления логина и пароля." + +#: IDF/gettexttemplates/idf/register/index.html.php:5 +#, php-format +msgid "" +"With your account, you will able to participate in the life of all the " +"projects hosted here. Participating in a software project must be fun, so if " +"you have troubles, you can let us know about your issues " +"at anytime!" +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:6 +msgid "Oops, please check the provided login and email address to register." +msgstr "" +"Ой, пожалуйста, проверьте логин и адрес электронной почты для регистрации." + +#: IDF/gettexttemplates/idf/register/index.html.php:7 IDF/Views.php:137 +msgid "Create Your Account" +msgstr "Создайте Вашу учетную запись" + +#: IDF/gettexttemplates/idf/register/index.html.php:9 +msgid "" +"Be sure to provide a valid email address, as we are sending a validation " +"link by email." +msgstr "" +"Не забудьте указать действительный адрес электронной почты, т.к. на него " +"будет оправлена ссылка для подтверждения регистрации." + +#: IDF/gettexttemplates/idf/register/index.html.php:10 +msgid "Did you know?" +msgstr "Знаете ли Вы?" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:3 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:3 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:3 +msgid "Oops, we found an error in the form." +msgstr "" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:4 +msgid "Confirm Your Account" +msgstr "Подтвердить Вашу учетную запись" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:7 +msgid "" +"Use your email software to read your emails and open your confirmation " +"email. Either click directly on the confirmation link or copy/paste the " +"confirmation key in the box and submit the form." +msgstr "" +"Используйте клиента электронной почты для открытия письма с подтверждением. " +"Либо щелкните на ссылку для подтверждения или скопируйте / вставьте ключ " +"подтверждения в форму." + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:8 +msgid "" +"Just after providing the confirmation key, you will be able to set your " +"password and start using this website fully." +msgstr "" +"Сразу после предоставления ключа подтверждения вы сможете установить пароль " +"и начать работу с этим сайтом в полном объеме." + +#: IDF/gettexttemplates/idf/review/base-full.html.php:3 +#: IDF/gettexttemplates/idf/review/base.html.php:3 +msgid "Open Reviews" +msgstr "Открытые рецензии" + +#: IDF/gettexttemplates/idf/review/base.html.php:4 +#: IDF/gettexttemplates/idf/review/create.html.php:11 +#: IDF/gettexttemplates/idf/review/index.html.php:3 IDF/Views/Review.php:83 +msgid "Start Code Review" +msgstr "Начать рецензирование кода" + +#: IDF/gettexttemplates/idf/review/create.html.php:3 +msgid "" +"

To start a code review, you need to provide:

\n" +"
    \n" +"
  • A commit or revision of the current code in the repository from which " +"you started your work.
  • \n" +"
  • A patch describing your changes with respect to the reference commit.\n" +"
  • Check your patch does not provide any password or confidential " +"information!
  • \n" +"
" +msgstr "" +"

Для начала аудита кода Вам необходимо указать:

\n" +"
    \n" +"
  • Комит или ревизию исходного кода в репозитории над котором вы работали.\n" +"
  • Патч описывающий Ваши изменения с учетом исходного комита.
  • \n" +"
  • Проверьте, что Вы не указали в патче какие-либо пароли или " +"другую конфиденциальную информацияю!
  • \n" +"
" + +#: IDF/gettexttemplates/idf/review/create.html.php:9 +msgid "" +"The form contains some errors. Please correct them to submit the code review." +msgstr "" +"Форма содержит ошибки. Пожалуйста исправьте их чтобы отправить вашу рецензию." + +#: IDF/gettexttemplates/idf/review/create.html.php:10 +msgid "" +"Select the commit against which you created your patch to be sure it applies " +"correctly." +msgstr "" +"Выберите комит для которого вы создали свой патч, чтобы убедиться, что он " +"применяется правильно." + +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:3 +msgid "The following review has been created:" +msgstr "Следующая рецензия была создана:" + +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:16 +msgid "Review:" +msgstr "Рецензия:" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:3 +msgid "The following review has been updated:" +msgstr "Следющая рецензия была обновлена:" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:5 +#, php-format +msgid "" +"By %%who%%, %%c.creation_dtime%%, on file:\n" +"%%c.cfile%%\n" +msgstr "" +"By %%who%%, %%c.creation_dtime%%, on file:\n" +"%%c.cfile%%\n" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:14 +msgid "General comments (last first):" +msgstr "Общие комментарии (последние в начале):" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:15 +msgid "Detailed file comments (last first):" +msgstr "Подробные комментарии файла (новые в начале):" + +#: IDF/gettexttemplates/idf/review/view.html.php:3 +msgid "" +"Code review is a process in which\n" +"after or before changes are commited into the code repository,\n" +"different people discuss the code changes. The goal is\n" +"to improve the quality of the code and the\n" +"contributions, as such, you must be pragmatic when writing\n" +"your review. Correctly mention the line numbers (in the old or in the\n" +"new file) and try to keep a good balance between seriousness and fun.\n" +msgstr "" +"Рецензирование кода - это процесс, при котором до или после комитов " +"отправленых в репозиторий, разные люди обсуждают изменения в коде. Целью " +"является улучшение качества кода и участия, таким образом, " +"вы должны быть прагматичными при написании обзора. Правильно отметить номера " +"строк (в старом или в новом файле) и попытаться сохранить хороший баланс " +"между серьезностью и шуткой.\n" + +#: IDF/gettexttemplates/idf/review/view.html.php:11 +msgid "" +"\n" +"Proposing code for review is intimidating, you know\n" +"you will receive critics, so please, as a reviewer, keep this\n" +"process fun, use it to help your contributor learn your\n" +"coding standards and the structure of the code and make them want\n" +"to propose more contributions.\n" +msgstr "" +"\n" +"Предложение кода для рецензирования пугает. Знайте, вы " +"будете получать критику, поэтому, пожалуйста, как рецензент, " +"воспринимать этот процесс с улыбкой, использовать его, " +"чтобы помочь вашей команде узнать ваши стандарты кодирования и структуры " +"кода и сделать так, что бы они продолжили участие в проекте .\n" + +#: IDF/gettexttemplates/idf/review/view.html.php:18 +#: IDF/gettexttemplates/idf/source/commit.html.php:3 +#: IDF/gettexttemplates/idf/source/commit.html~.php:3 +#, php-format +msgid "%%ndiff%% diff" +msgid_plural "%%ndiff%% diffs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: IDF/gettexttemplates/idf/review/view.html.php:19 +#, php-format +msgid "%%nc%% comment" +msgid_plural "%%nc%% comments" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: IDF/gettexttemplates/idf/review/view.html.php:20 +#, php-format +msgid "" +"Comment %%i%% by %%who%%, " +"%%c.creation_dtime%%" +msgstr "" +"Комментарий %%i%% %%who%%, %%c.creation_dtime%%" + +#: IDF/gettexttemplates/idf/review/view.html.php:21 +#, php-format +msgid "Your comments on the changes in file %%file%%:" +msgstr "Ваши комментарии на изменения в файле %%file%%:" + +#: IDF/gettexttemplates/idf/review/view.html.php:23 +#, php-format +msgid "Sign in to participate in the review." +msgstr "Войдите что бы учавствовать в рецензировании." + +#: IDF/gettexttemplates/idf/review/view.html.php:24 +msgid "" +"The form contains some errors. Please correct them to submit your review." +msgstr "" +"Форма содержит ошибки. Пожалуйста исправьте их чтобы отправить вашу рецензию." + +#: IDF/gettexttemplates/idf/review/view.html.php:25 +msgid "How to Participate in a Code Review" +msgstr "Как принять участие в рецензировании кода" + +#: IDF/gettexttemplates/idf/review/view.html.php:28 +#: IDF/gettexttemplates/idf/source/commit.html.php:5 +#: IDF/gettexttemplates/idf/source/commit.html~.php:5 +msgid "Author:" +msgstr "Автор:" + +#: IDF/gettexttemplates/idf/review/view.html.php:29 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/source/commit.html.php:7 +#: IDF/gettexttemplates/idf/source/commit.html~.php:7 +msgid "Commit:" +msgstr "Комит:" + +#: IDF/gettexttemplates/idf/review/view.html.php:30 +#: IDF/gettexttemplates/idf/source/commit.html.php:8 +#: IDF/gettexttemplates/idf/source/commit.html~.php:8 +msgid "View corresponding source tree" +msgstr "Просмотреть соответствующие дерево исходных текстов" + +#: IDF/gettexttemplates/idf/review/view.html.php:32 +msgid "Reviewers:" +msgstr "Рецензенты:" + +#: IDF/gettexttemplates/idf/review/view.html.php:33 +msgid "No reviewers at the moment." +msgstr "Нет рецензентов в данный момент." + +#: IDF/gettexttemplates/idf/review/view.html.php:34 +msgid "Files:" +msgstr "Файлов:" + +#: IDF/gettexttemplates/idf/review/view.html.php:36 +#: IDF/gettexttemplates/idf/source/commit.html.php:24 +#: IDF/gettexttemplates/idf/source/commit.html~.php:23 +msgid "Download the corresponding diff file" +msgstr "Скачать соответствующий diff файл." + +#: IDF/gettexttemplates/idf/review/view.html.php:37 +msgid "General Comments" +msgstr "Общие комментарии" + +#: IDF/gettexttemplates/idf/review/view.html.php:40 +msgid "Submit Code Review" +msgstr "Отправить рецензию на код" + +#: IDF/gettexttemplates/idf/source/base.html.php:3 +msgid "Source Tree" +msgstr "Исходный код" + +#: IDF/gettexttemplates/idf/source/base.html.php:4 +msgid "Change Log" +msgstr "История изменений" + +#: IDF/gettexttemplates/idf/source/base.html.php:6 +msgid "How To Get The Code" +msgstr "Как получить код" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:3 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:8 +#: IDF/Views/Project.php:190 +msgid "Age" +msgstr "Возраст" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:4 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:10 +msgid "Message" +msgstr "Сообщение" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:5 +msgid "Parent:" +msgstr "Родитель:" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:6 +#: IDF/gettexttemplates/idf/source/commit.html.php:10 +#: IDF/gettexttemplates/idf/source/commit.html~.php:10 +msgid "View corresponding commit" +msgstr "Открыть соответствующий коммит." + +#: IDF/gettexttemplates/idf/source/changelog.html.php:8 +msgid "by" +msgstr " " + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:3 +msgid "A new commit has been created:" +msgstr "Новые комит был создан:" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:8 +msgid "Created by:" +msgstr "Создатель:" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:8 +msgid "Created at:" +msgstr "Создан:" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:8 +msgid "Content:" +msgstr "Содежимое:" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:10 +msgid "Commit details:" +msgstr "Детали комита:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:4 +#: IDF/gettexttemplates/idf/source/commit.html~.php:4 +msgid "Date:" +msgstr "Дата:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:6 +#: IDF/gettexttemplates/idf/source/commit.html~.php:6 +msgid "Branch:" +msgstr "Ветка:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:9 +#: IDF/gettexttemplates/idf/source/commit.html~.php:9 +msgid "Parents:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:11 +#: IDF/gettexttemplates/idf/source/commit.html~.php:11 +msgid "Message:" +msgstr "Сообщение:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:12 +#: IDF/gettexttemplates/idf/source/commit.html~.php:12 +#: IDF/gettexttemplates/idf/wiki/feedfragment-page.xml.php:3 +#: IDF/gettexttemplates/idf/wiki/feedfragment-resource.xml.php:3 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:10 +msgid "Changes:" +msgstr "Изменения:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:13 +#: IDF/gettexttemplates/idf/source/commit.html~.php:13 +msgid "deleted" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:14 +#: IDF/gettexttemplates/idf/source/commit.html.php:18 +#: IDF/gettexttemplates/idf/source/commit.html~.php:14 +#: IDF/gettexttemplates/idf/source/commit.html~.php:17 +msgid "full" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:15 +#: IDF/gettexttemplates/idf/source/commit.html~.php:15 +msgid "renamed" +msgstr "переименовано" + +#: IDF/gettexttemplates/idf/source/commit.html.php:16 +msgid "copied" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:17 +#: IDF/gettexttemplates/idf/source/commit.html~.php:16 +msgid "added" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:19 +#: IDF/gettexttemplates/idf/source/commit.html~.php:18 +msgid "modified" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:20 +msgid "properties changed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:21 +#: IDF/gettexttemplates/idf/source/commit.html~.php:20 +msgid "removed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:22 +#: IDF/gettexttemplates/idf/source/commit.html~.php:21 +msgid "File differences" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html~.php:19 +msgid "properies changed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:3 +#, php-format +msgid "" +"The revision identifier %%commit%% is ambiguous and can be\n" +"expanded to multiple valid revisions - please choose one:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:5 +msgid "Title" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:6 +msgid "Author" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:7 +msgid "Date" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:8 +msgid "Branch" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:9 +msgid "Revision" +msgstr "" + +#: IDF/gettexttemplates/idf/source/feedfragment.xml.php:3 +#, php-format +msgid "%%cproject.name%%: Commit %%c.scm_id%%" +msgstr "%%cproject.name%%: Комит %%c.scm_id%%" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:3 +msgid "Branches" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:4 +msgid "filter branches" +msgstr "фильтровать бранчи" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:5 +msgid "Tags" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:6 +msgid "filter tags" +msgstr "фильтровать метки" + +#: IDF/gettexttemplates/idf/source/git/file.html.php:3 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:4 +#, php-format +msgid "" +"Source at commit %%commit%% created " +"%%cobject.date%%." +msgstr "" +"Исходный код в комите %%commit%% " +"создан %%cobject.date%%." + +#: IDF/gettexttemplates/idf/source/git/file.html.php:4 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:5 +#, php-format +msgid "By %%cobject.author%%, %%cobject.title%%" +msgstr "%%cobject.author%%, %%cobject.title%%" + +#: IDF/gettexttemplates/idf/source/git/file.html.php:5 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:6 +msgid "Root" +msgstr "Корень" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the git software to manage the source\n" +"code." +msgstr "" +"Команда проекта %%project%% использует\n" +"git для управления исходным кодом." + +#: IDF/gettexttemplates/idf/source/git/help.html.php:6 +#, php-format +msgid "" +"You may need to provide your SSH key. The " +"synchronization of your SSH key can take a couple of minutes. You can learn " +"more about SSH key authentication." +msgstr "" +"Возможно Вам потребуется указать ваш SSH ключ. " +"Синхронизация ключа может занять некоторое время. Вы можете найти больше " +"информации про авторизацию по SSH ключу." + +#: IDF/gettexttemplates/idf/source/git/help.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:6 +msgid "To make a first commit in the repository, perform the following steps:" +msgstr "" +"Чтобы сделать первый комит в репозиторий, выполните следующие действия:" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:8 +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:7 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:7 +#, php-format +msgid "Find here more details on how to access %%project%% source code." +msgstr "" +"Найти здесь более подробную информацию о том, как получить доступ к " +"исходному коду проекта %%project%%." + +#: IDF/gettexttemplates/idf/source/git/help.html.php:9 +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:8 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:8 +msgid "Command-Line Access" +msgstr "Доступ из командной строки" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:10 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:9 +msgid "First Commit" +msgstr "Первый комит" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:11 +#: IDF/Views/Download.php:66 IDF/Views/Download.php:348 +msgid "Size" +msgstr "Размер" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:12 +msgid ":" +msgstr ":" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:13 +msgid "Download this version" +msgstr "Скачать эту версию" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:13 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:13 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:14 +msgid "or" +msgstr "или" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:3 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:3 +#, php-format +msgid "" +"The branch or revision %%commit%% is not valid or does not exist\n" +"in this repository." +msgstr "" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:5 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:5 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:5 +msgid "The following list shows all available branches:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:6 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:6 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:6 +#, php-format +msgid "" +"If this is a new repository, the reason for this error\n" +"could be that you have not committed and / or pushed any change so far.\n" +"In this case please take a look at the Help page\n" +"how to access your repository." +msgstr "" + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the Mercurial software to manage the source\n" +"code." +msgstr "" +"Команда %%project%% использует Mercurial для управления " +"исходным кодом." + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:6 +#, php-format +msgid "" +"To get write access to the repository, you need to use your username and " +"your extra password." +msgstr "" +"Чтобы получить доступ на запись в репозиторий, вам необходимо использовать " +"свое имя пользователя и дополнительный пароль." + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:9 +msgid "Write Access Authentication" +msgstr "Аутентификация для возможности записи" + +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:3 +#, php-format +msgid "Property %%prop%% set to %%val%%" +msgstr "" + +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the monotone software to manage the source\n" +"code." +msgstr "" +"Команда прокета %%project%% использует\n" +"monotone для управления исходным\n" +"кодом." + +#: IDF/gettexttemplates/idf/source/svn/changelog.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/commit.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/commit.html~.php:3 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:14 +msgid "Revision:" +msgstr "Ревизия:" + +#: IDF/gettexttemplates/idf/source/svn/changelog.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/commit.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/commit.html~.php:4 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:10 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:15 +msgid "Switch" +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the subversion software to manage the source\n" +"code." +msgstr "" +"Команда проекта %%project%% использует\n" +"subversion для управления исходным кодом." + +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:3 +#, php-format +msgid "" +"The revision %%commit%% is not valid or does not exist\n" +"in this repository." +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:9 +msgid "Rev" +msgstr "Рев" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:16 +msgid "Branches:" +msgstr "Бранчи:" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:17 +msgid "Tags:" +msgstr "Теги:" + +#: IDF/gettexttemplates/idf/user/changeemail-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"To confirm that you want %%email%%\n" +"to be your new email address, just follow this link:\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following verification key:\n" +"\n" +"%%key%%\n" +"\n" +"If you do not want to change your email address, \n" +"just ignore this message.\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" +"Здравствуйте %%user%%.\n" +"\n" +"Чтобы подтвердить смену эл. адреса на %%email%% проследуйте по следующей " +"ссылке:\n" +"\n" +"%%url%%\n" +"\n" +"Или пройдите по этой ссылке:\n" +"\n" +"%%urlik%%\n" +"\n" +"и введите ключ подтверждения:\n" +"\n" +"%%key%%\n" +"\n" +"Если смена адреса вам не требуется, то просто проигнорируйте это письмо.\n" +"\n" +"С уважением,\n" +"Команда разработчиков.\n" + +#: IDF/gettexttemplates/idf/user/changeemail.html.php:4 +msgid "Confirm Your New Email Address" +msgstr "Подтвердите Ваш новый эл. адрес" + +#: IDF/gettexttemplates/idf/user/changeemail.html.php:7 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:7 +msgid "" +"Use your email software to read your emails and open your verification " +"email. Either click directly on the verification link or copy/paste the " +"verification key in the box and submit the form." +msgstr "" +"Запустите ваше ПО для чтения электронной почты и откройте письмо с " +"подтверждением. Либо нажмите непосредственно на ссылку подтверждения или " +"скопируйте и вставьте проверочный ключ в форму и нажмите Отправить." + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:3 +#, php-format +msgid "Update your account." +msgstr "Изменить Вашу учетную запись." + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:4 +#, php-format +msgid "See your public profile." +msgstr "Посмотреть Ваш публичный профиль." + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:5 +#, php-format +msgid "See your forge issue watch list." +msgstr "Смотреть ваш список слежения для хранилища." + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:6 +msgid "Key Management" +msgstr "Управление ключами" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:7 +msgid "Secondary Emails" +msgstr "Дополнительный e-mail" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:8 +msgid "Extra password" +msgstr "Дополнительный пароль" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:9 +msgid "" +"This password is used to access some of the external systems managed by our " +"infrastructure. It will be regenerated if you change your password." +msgstr "" +"Этот пароль служит для доступа с внешних систем, управляемых нашей " +"инфраструктурой. Он будет сгенерирован при смене Вашего пароля." + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:10 +msgid "API key" +msgstr "API ключ" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:11 +msgid "" +"Your API key will be regenerated automatically if you change your password." +msgstr "API ключ будет сгенерирован автоматически при смене Вашего пароль." + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:12 +msgid "Update Your Account" +msgstr "Обновить учетную запись" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:14 +msgid "Your Current Public Keys" +msgstr "Ваши текущие публичные ключи" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:15 +msgid "Delete this key" +msgstr "Удалить этот ключ" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:16 +msgid "Your additional email addresses" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:17 +msgid "Delete this address" +msgstr "Удалить этот адрес" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:18 +msgid "" +"If possible, use your real name. By using your real name, people will have " +"more trust in your comments and remarks." +msgstr "" +"Если возможно, используйте свое настоящее имя. При использовании свое " +"настоящего имени, люди будут больше доверять вашим комментариям и замечаниям." + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:19 +msgid "" +"The extra password is used to access some of the external systems and the " +"API key is used to interact with this website using a program." +msgstr "" +"Дополнительный пароль используется для доступа с некоторых внешних систем и " +"ключ API используется для взаимодействия с этим веб-сайтом из внешней " +"программы." + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:20 +msgid "Show API key and extra password" +msgstr "Показать ключ API и дополнительный пароль" + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:3 +msgid "" +"Oops, please check the provided login or email address to recover your " +"password." +msgstr "" +"Ой, пожалуйста, проверьте логин или адрес электронной почты для " +"восстановления пароля." + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:4 +msgid "Recover My Password" +msgstr "Восстановить мой пароль" + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:6 +msgid "" +"Provide either your login or email address, if a corresponding user is found " +"in the database, we will send you an email with the details on how to reset " +"your password." +msgstr "" +"Введите ваш Логин или адрес электронной почты. Если соответствующий " +"пользователь найден в базе данных, мы вышлем Вам письмо с информацией о том, " +"как сменить пароль." + +#: IDF/gettexttemplates/idf/user/passrecovery-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"You lost your password and wanted to recover it.\n" +"To provide a new password for your account, you\n" +"just have to follow the provided link. You will\n" +"get a simple form to provide a new password.\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following verification key:\n" +"\n" +"%%key%%\n" +"\n" +"If you are not the one who requested to reset\n" +"your password, simply ignore this email, your\n" +"password will not be changed.\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" +"Здравствуйте, %%user%%,\n" +"\n" +"Вы потеряли пароль и хотите восстановить его.\n" +"Для задания нового пароля Вам необходимо перейти по ссылке и заполнить " +"небольшую форму.\n" +"\n" +"%%url%%\n" +"\n" +"Так же вы можете перейти на следующую страницу:\n" +"\n" +"%%urlik%%\n" +"\n" +"А ввести следующий проверочный ключ:\n" +"\n" +"%%key%%\n" +"\n" +"Если вы не запрашивали смену пароля можете просто проигнорировать это " +"письмо.\n" +"\n" +"С уважением,\n" +"Команда разработчиков\n" + +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:4 +msgid "Recover Your Password" +msgstr "Восстановить пароль" + +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:8 +msgid "" +"Just after providing the confirmation key, you will be able to reset your " +"password and use this website fully." +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:6 +msgid "Reset Your Password" +msgstr "Сбросить пароль" + +#: IDF/gettexttemplates/idf/user/public.html.php:3 +#, php-format +msgid "You are looking at the public profile of %%member%%." +msgstr "Вы просматриваете публичный профиль %%member%%." + +#: IDF/gettexttemplates/idf/user/public.html.php:5 +msgid "Twitter:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:6 +msgid "Public Email:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:7 +msgid "Website:" +msgstr "Веб-сайт:" + +#: IDF/gettexttemplates/idf/user/public.html.php:8 +msgid "Last time seen:" +msgstr "Последний раз был здесь:" + +#: IDF/gettexttemplates/idf/user/public.html.php:9 +msgid "Member since:" +msgstr "Участник с:" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:3 +msgid "List Pages" +msgstr "Список страниц" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:4 +#, fuzzy +msgid "List Resources" +msgstr "Исходный код %s" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:5 +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:4 +#: IDF/gettexttemplates/idf/wiki/search.html.php:3 IDF/Views/Wiki.php:211 +msgid "New Page" +msgstr "Новая страница" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:6 +#: IDF/gettexttemplates/idf/wiki/listResources.html.php:3 +#: IDF/Views/Wiki.php:256 +#, fuzzy +msgid "New Resource" +msgstr "Новая проблема" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:7 +msgid "Update This Page" +msgstr "Обновить эту страницу" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:8 +#, fuzzy +msgid "Update This Resource" +msgstr "Обновить эту страницу" + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:3 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:3 +msgid "Preview of the Page" +msgstr "Предпросмотр страницы" + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:7 +msgid "The form contains some errors. Please correct them to create the page." +msgstr "Форма содержит ошибки. Пожалуйста исправтье их чтобы создать страницу." + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:6 +msgid "Create Page" +msgstr "Создать страницу" + +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:3 +msgid "" +"\n" +"Wiki resources are later addressed in wiki pages by their title, so ensure " +"that you\n" +"give your resource a unique and an easy to remember name.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:8 +#, fuzzy +msgid "Create Resource" +msgstr "Создать пользователя" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:3 +msgid "" +"If you delete this documentation page, it will be removed from the database " +"with all the associated revisions and you will not be able to " +"recover it." +msgstr "" +"Если вы удалите эту страницу документации, она будет удалена из базы данных " +"со всеми сопутствующими изменениями и вы не сможете ее восстановить." +"" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:6 +msgid "Delete Page" +msgstr "Удалить страницу" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:14 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:15 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:15 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:17 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:18 +msgid "Old Revisions" +msgstr "Старые ревизии" + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:3 +#, php-format +msgid "" +"You are looking at an old revision (%%oldrev.summary%%) of the " +"page \n" +"%%page.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" +"Вы открыли старую версию (%%oldrev.summary%%) страницы\n" +"%%page.title%%. Эта версия была создана\n" +"%%submitter%%." + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:5 +msgid "" +"If you delete this old revision, it will be removed from the database and " +"you will not be able to recover it." +msgstr "" +"Если вы удалите эту старую версию, она будет удалена из базы данных, и " +"вы не сможете ее восстановить." + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:8 +msgid "Delete Revision" +msgstr "Удалить ревизию" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:3 +#, fuzzy +msgid "" +"If you delete this documentation resource, it will be removed from the " +"database with all the associated revisions \n" +"and you will not be able to recover it. Any documentation " +"pages that reference this resource,\n" +"will no longer be able to render it, but won't be deleted." +msgstr "" +"Если вы удалите эту страницу документации, она будет удалена из базы данных " +"со всеми сопутствующими изменениями и вы не сможете ее восстановить." +"" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:8 +#, fuzzy +msgid "Delete Resource" +msgstr "Удалить ревизию" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:10 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:8 +#, fuzzy +msgid "File size" +msgstr "размер файла" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:9 +#: IDF/Views/Wiki.php:101 +#, fuzzy +msgid "MIME type" +msgstr "тип" + +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:3 +#, fuzzy, php-format +msgid "" +"You are looking at an old revision (%%oldrev.summary%%) of the " +"resource \n" +"%%resource.title%%. This revision was created by " +"%%submitter%%." +msgstr "" +"Вы открыли старую версию (%%oldrev.summary%%) страницы\n" +"%%page.title%%. Эта версия была создана\n" +"%%submitter%%." + +#: IDF/gettexttemplates/idf/wiki/edit-info.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

The content of the page can use the Markdown syntax with the Extra extension.

\n" +"

Website addresses are automatically linked and you can link to another " +"page in the documentation using double square brackets like that " +"[[AnotherPage]].

\n" +"

If you want to embed uploaded resources, use the [[!ResourceName]] syntax for that. This is described more in detail in the FAQ.

\n" +"

To directly include a file content from the repository, embrace its path " +"with triple square brackets: [[[my/file.txt]]].

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/feedfragment-resource.xml.php:4 +#, fuzzy +msgid "Initial creation" +msgstr "Создание первоначальной страницы" + +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:3 +#, php-format +msgid "See the deprecated pages." +msgstr "Смотреть устаревшие страницы." + +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:5 +msgid "Number of pages:" +msgstr "Количество страниц:" + +#: IDF/gettexttemplates/idf/wiki/listResources.html.php:4 +#, fuzzy +msgid "Number of resources:" +msgstr "Количество пользователей:" + +#: IDF/gettexttemplates/idf/wiki/search.html.php:4 +msgid "Pages found:" +msgstr "Страниц найдено:" + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:3 +msgid "The form contains some errors. Please correct them to update the page." +msgstr "Форма содержит ошибки. Пожалуйста исправте их чтобы обновить страницу." + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:6 +msgid "Update Page" +msgstr "Обновить страницу" + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:10 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:11 +msgid "Delete this page" +msgstr "Удалить эту страницу" + +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:4 +#, fuzzy +msgid "Update Resource" +msgstr "Обновить пользователя" + +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:8 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:9 +#, fuzzy +msgid "Delete this resource" +msgstr "Удалить эту ревизию" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:3 +msgid "" +"Attention! This page is marked as deprecated, \n" +"use it as reference only if you are sure you need these specific information." +msgstr "" +"Внимание! Эта страница помечена как устаревшая. Ссылайтесь " +"на нее, только если вы уверены, что нужна именно она." + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:5 +#, php-format +msgid "" +"You are looking at an old revision of the page \n" +"%%page.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" +"Вы смотрите на старую версию страницы \n" +"%%page.title%%. Эта версия была создана\n" +"%%submitter%%." + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:10 +msgid "Table of Content" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:13 +msgid "Delete this revision" +msgstr "Удалить эту ревизию" + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:3 +#, fuzzy, php-format +msgid "" +"You are looking at an old revision of the resource \n" +"%%resource.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" +"Вы смотрите на старую версию страницы \n" +"%%page.title%%. Эта версия была создана\n" +"%%submitter%%." + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:14 +#, fuzzy +msgid "Page Usage" +msgstr "ИмяСтраницы" + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:15 +msgid "This resource is not used on any pages yet." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:3 +msgid "A new documentation page has been created:" +msgstr "Новая страница документации была создана:" + +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:14 +msgid "Documentation page:" +msgstr "Страница документации:" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:3 +msgid "The following documentation page has been updated:" +msgstr "Следующая страница документации была обновлена:" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:7 +msgid "Updated by:" +msgstr "Обновлена:" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:13 +msgid "New content:" +msgstr "Новое содержимое:" + +#: IDF/Issue.php:76 +msgid "owner" +msgstr "владелец" + +#: IDF/Issue.php:84 IDF/Wiki/Page.php:86 +msgid "interested users" +msgstr "наблюдающие пользователи" + +#: IDF/Issue.php:85 +msgid "" +"Interested users will get an email notification when the issue is changed." +msgstr "" +"Наблюдающие пользователи получат сообщение, когда проблема будем изменена." + +#: IDF/Issue.php:92 IDF/Project.php:94 IDF/Review.php:95 IDF/Upload.php:99 +#: IDF/Wiki/Page.php:94 +msgid "labels" +msgstr "метки" + +#: IDF/Issue.php:111 IDF/IssueFile.php:102 IDF/Review.php:114 +#: IDF/Upload.php:118 IDF/Wiki/Page.php:106 IDF/Wiki/Resource.php:101 +msgid "modification date" +msgstr "дата модификации" + +#: IDF/Issue.php:212 IDF/IssueComment.php:143 +#, php-format +msgid "" +"Issue %3$d, %4$s" +msgstr "" +"Проблема %3$d, %4$s" + +#: IDF/Issue.php:214 +#, fuzzy, php-format +msgid "Creation of issue %3$d, by %4$s" +msgstr "Создание проблемы %d, %s" + +#: IDF/Issue.php:224 +#, fuzzy, php-format +msgid "%1$s: Issue %2$d created - %3$s" +msgstr "%s: Проблема %d создана - %s" + +#: IDF/Issue.php:307 +#, fuzzy, php-format +msgid "Issue %1$s - %2$s (%3$s)" +msgstr "Проблема %s - %s (%s)" + +#: IDF/Issue.php:311 +#, fuzzy, php-format +msgid "Updated Issue %1$s - %2$s (%3$s)" +msgstr "Обновить проблему %s - %s (%s)" + +#: IDF/IssueComment.php:51 IDF/IssueRelation.php:47 +msgid "issue" +msgstr "проблема" + +#: IDF/IssueComment.php:58 IDF/IssueFile.php:49 IDF/Review/Comment.php:62 +#: IDF/Review/FileComment.php:49 IDF/Review/FileComment.php:69 +msgid "comment" +msgstr "комментарий" + +#: IDF/IssueComment.php:72 IDF/Review/Comment.php:75 IDF/Upload.php:63 +#: IDF/Wiki/PageRevision.php:85 +msgid "changes" +msgstr "изменения" + +#: IDF/IssueComment.php:73 +msgid "Serialized array of the changes in the issue." +msgstr "Сериализованный массив изменений в этой проблеме." + +#: IDF/IssueComment.php:180 +#, fuzzy, php-format +msgid "Comment on issue %3$d, by %4$s" +msgstr "Комментарий на проблему %d, %s" + +#: IDF/IssueComment.php:191 +#, fuzzy, php-format +msgid "%1$s: Comment on issue %2$d - %3$s" +msgstr "%s: Комментарий на проблему %d - %s" + +#: IDF/IssueFile.php:64 +msgid "file name" +msgstr "имя файла" + +#: IDF/IssueFile.php:70 +msgid "the file" +msgstr "файл" + +#: IDF/IssueFile.php:76 +msgid "file size" +msgstr "размер файла" + +#: IDF/IssueFile.php:84 +msgid "type" +msgstr "тип" + +#: IDF/IssueFile.php:86 +msgid "Image" +msgstr "Изображение" + +#: IDF/IssueFile.php:87 +msgid "Other" +msgstr "Другой" + +#: IDF/IssueRelation.php:54 +msgid "verb" +msgstr "" + +#: IDF/IssueRelation.php:61 +msgid "other issue" +msgstr "другие проблемы" + +#: IDF/Key.php:55 +msgid "public key" +msgstr "Открытый ключ" + +#: IDF/Key.php:90 +msgid "Invalid or unknown key data detected." +msgstr "Обнаружены неверные или неизвестные данные ключа." + +#: IDF/Plugin/SyncMercurial.php:78 IDF/Plugin/SyncSvn.php:81 +#, php-format +msgid "The repository %s already exists." +msgstr "Репозиторий %s уже существует." + +#: IDF/Plugin/SyncMercurial.php:142 +#, php-format +msgid "%s does not exist or is not writable." +msgstr "%s не существует или нет прав на запись." + +#: IDF/Plugin/SyncMonotone.php:107 IDF/Plugin/SyncMonotone.php:492 +msgid "\"mtn_repositories\" must be defined in your configuration file" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:114 IDF/Plugin/SyncMonotone.php:482 +msgid "\"mtn_usher_conf\" does not exist or is not writable" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:121 +#, php-format +msgid "Could not find mtn-post-push script \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:155 +#, php-format +msgid "The configuration file \"%s\" is missing" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:164 +#, php-format +msgid "The project path \"%s\" already exists" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:170 +#, php-format +msgid "The project path \"%s\" could not be created" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:208 +#, php-format +msgid "The key directory \"%s\" could not be created" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:227 +#, php-format +msgid "Could not parse key information: %s" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:265 +#, php-format +msgid "Could not create configuration directory \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:275 +#, php-format +msgid "Could not create symlink for configuration file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:293 +#, php-format +msgid "Could not write configuration file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:309 IDF/Plugin/SyncMonotone.php:525 +#, php-format +msgid "Could not parse usher configuration in \"%1$s\": %2$s" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:320 +#, php-format +msgid "usher configuration already contains a server entry named \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:345 IDF/Plugin/SyncMonotone.php:546 +#, php-format +msgid "Could not write usher configuration file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:395 +#, php-format +msgid "Could not write write-permissions file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:420 +#, php-format +msgid "Could not write read-permissions file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:438 +#, php-format +msgid "Could not remove symlink \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:446 +#, php-format +msgid "Could not create symlink \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:500 +#, php-format +msgid "One or more paths underneath %s could not be deleted" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:512 +#, php-format +msgid "Could not delete client private key \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:599 IDF/Plugin/SyncMonotone.php:718 +#, php-format +msgid "Could not parse read-permissions for project \"%1$s\": %2$s" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:643 IDF/Plugin/SyncMonotone.php:741 +#, php-format +msgid "Could not write read-permissions for project \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:657 IDF/Plugin/SyncMonotone.php:760 +#, php-format +msgid "Could not write write-permissions file for project \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:813 +msgid "\"mtn_repositories\" must be defined in your configuration file." +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:820 +#, php-format +msgid "The project path %s does not exists." +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:838 +#, php-format +msgid "The command \"%s\" could not be executed." +msgstr "" + +#: IDF/Project.php:62 IDF/Tag.php:66 +msgid "name" +msgstr "имя" + +#: IDF/Project.php:69 +msgid "short name" +msgstr "краткое имя" + +#: IDF/Project.php:70 +#, fuzzy +msgid "" +"Used in the URL to access the project, must be short with only letters and " +"numbers." +msgstr "Используется в адресе для доступа к проекту. Только буквы и цифры." + +#: IDF/Project.php:78 +msgid "short description" +msgstr "краткое описание" + +#: IDF/Project.php:86 IDF/Review/Patch.php:74 +msgid "description" +msgstr "описание" + +#: IDF/Project.php:87 +#, fuzzy +msgid "The description can be extended using the Markdown syntax." +msgstr "Описание может быть расширенно с использованием markdown синтакса." + +#: IDF/Project.php:100 +msgid "private" +msgstr "частный" + +#: IDF/Project.php:108 +msgid "current project activity" +msgstr "" + +#: IDF/Project.php:159 +#, php-format +msgid "Project \"%s\" not found." +msgstr "Проект \"%s\" не найден." + +#: IDF/ProjectActivity.php:56 +#, fuzzy +msgid "date" +msgstr "Обновлено" + +#: IDF/Review/Comment.php:55 IDF/Review/Patch.php:80 +msgid "patch" +msgstr "патч" + +#: IDF/Review/Comment.php:83 +msgid "vote" +msgstr "голос" + +#: IDF/Review/Comment.php:139 IDF/Review/Patch.php:151 +#, php-format +msgid "" +"Review %3$d, %4$s" +msgstr "" +"Аудит %3$d, " +"%4$s" + +#: IDF/Review/Comment.php:141 +#, fuzzy, php-format +msgid "Update of review %3$d, by %4$s" +msgstr "Обновление рецензии %d, %s" + +#: IDF/Review/Comment.php:151 +#, fuzzy, php-format +msgid "%1$s: Updated review %2$d - %3$s" +msgstr "%s: Обновленная рецензия %d - %s" + +#: IDF/Review/Comment.php:222 +#, fuzzy, php-format +msgid "Updated Code Review %1$s - %2$s (%3$s)" +msgstr "Обновленная рецензия кода %s - %s (%s)" + +#: IDF/Review/Patch.php:52 +msgid "review" +msgstr "рецензия" + +#: IDF/Review/Patch.php:67 +msgid "commit" +msgstr "комит" + +#: IDF/Review/Patch.php:153 +#, fuzzy, php-format +msgid "Creation of review %3$d, by %4$s" +msgstr "Создание проблемы %d, %s" + +#: IDF/Review/Patch.php:163 +#, fuzzy, php-format +msgid "%1$s: Creation of Review %2$d - %3$s" +msgstr "%s: Создание рецензии %d - %s" + +#: IDF/Review/Patch.php:208 +#, fuzzy, php-format +msgid "New Code Review %1$s - %2$s (%3$s)" +msgstr "Новая рецензия кода %s - %s (%s)" + +#: IDF/Scm/Git.php:309 IDF/Scm/Mercurial.php:199 +#, php-format +msgid "Folder %1$s not found in commit %2$s." +msgstr "Директория %1$s не найдена в комите %2$s." + +#: IDF/Scm/Git.php:433 IDF/Scm/Mercurial.php:216 +#, php-format +msgid "Not a valid tree: %s." +msgstr "Не действительное дерево: %s." + +#: IDF/Scm/Monotone/Stdio.php:81 +msgid "Monotone client key name or hash not in project conf." +msgstr "Клиентский ключ monotone или хэш не в настройках проекта." + +#: IDF/Scm/Monotone/Stdio.php:89 +#, php-format +msgid "The key directory %s could not be created." +msgstr "" + +#: IDF/Scm/Monotone/Stdio.php:100 +#, php-format +msgid "Could not write client key \"%s\"" +msgstr "" + +#: IDF/Search/Occ.php:33 +#, fuzzy +msgid "occurrence" +msgstr "вхождение" + +#: IDF/Search/Occ.php:49 +msgid "word" +msgstr "слово" + +#: IDF/Search/Occ.php:75 +#, fuzzy +msgid "occurrences" +msgstr "вхождений" + +#: IDF/Search/Occ.php:81 +#, fuzzy +msgid "ponderated occurrence" +msgstr "ponderated вхождение" + +#: IDF/Tag.php:59 +msgid "tag class" +msgstr "пометить класс" + +#: IDF/Tag.php:60 +msgid "The class of the tag." +msgstr "Класс метки." + +#: IDF/Tag.php:73 +msgid "lcname" +msgstr "lcname" + +#: IDF/Tag.php:74 +msgid "Lower case version of the name for fast searching." +msgstr "Имя в нижнем регистре для быстрого поиска." + +#: IDF/Template/Markdown.php:84 +msgid "Create this documentation page" +msgstr "Создать эту страницу документации" + +#: IDF/Template/Markdown.php:97 +msgid "You are not allowed to access the wiki." +msgstr "" + +#: IDF/Template/Markdown.php:106 +#, fuzzy +msgid "The wiki resource has not been found." +msgstr "Проект был обновлен." + +#: IDF/Template/Markdown.php:113 +msgid "The wiki resource has not been found. Create it!" +msgstr "" + +#: IDF/Template/Markdown.php:146 +#, fuzzy +msgid "This revision of the resource is no longer available." +msgstr "Этот проект не доступен." + +#: IDF/Template/ShowUser.php:51 +msgid "Anonymous" +msgstr "Аноним" + +#: IDF/Template/ShowUser.php:54 +msgid "Me" +msgstr "Я" + +#: IDF/Timeline/Paginator.php:49 +msgid "Today" +msgstr "Сегодня" + +#: IDF/Upload.php:70 +msgid "file" +msgstr "файл" + +#: IDF/Upload.php:71 +msgid "The path is relative to the upload path." +msgstr "Путь относителен пути загрузки." + +#: IDF/Upload.php:78 IDF/Wiki/ResourceRevision.php:71 +msgid "file size in bytes" +msgstr "размер файла в байтах" + +#: IDF/Upload.php:84 +msgid "MD5" +msgstr "" + +#: IDF/Upload.php:106 +msgid "number of downloads" +msgstr "количество файлов" + +#: IDF/Upload.php:201 +#, php-format +msgid "Download %2$d, %3$s" +msgstr "Загрузка %2$d, %3$s" + +#: IDF/Upload.php:204 +#, fuzzy, php-format +msgid "Addition of download %2$d, by %3$s" +msgstr "Добавление загрузки %d, %s" + +#: IDF/Upload.php:214 +#, fuzzy, php-format +msgid "%1$s: Download %2$d added - %3$s" +msgstr "%s: Файл %d добавлен - %s" + +#: IDF/Upload.php:301 +#, fuzzy, php-format +msgid "New download - %1$s (%2$s)" +msgstr "Новый файл - %s (%s)" + +#: IDF/Upload.php:305 +#, fuzzy, php-format +msgid "Updated download - %1$s (%2$s)" +msgstr "Новый файл - %s (%s)" + +#: IDF/Views/Admin.php:47 +#, fuzzy +msgid "The forge configuration has been saved." +msgstr "Конфигурации загрузки сохранены." + +#: IDF/Views/Admin.php:80 +msgid "This table shows the projects in the forge." +msgstr "Таблица показывает проекты в хранилище." + +#: IDF/Views/Admin.php:85 +msgid "Short Name" +msgstr "Краткое имя" + +#: IDF/Views/Admin.php:87 +msgid "Repository Size" +msgstr "Размер репозитория" + +#: IDF/Views/Admin.php:93 +msgid "No projects were found." +msgstr "Проектов не найдено." + +#: IDF/Views/Admin.php:116 +#, fuzzy +msgid "The label configuration has been saved." +msgstr "Конфигурации загрузки сохранены." + +#: IDF/Views/Admin.php:147 IDF/Views/Admin.php:314 IDF/Views/Wiki.php:484 +#: IDF/Views/Wiki.php:536 +#, php-format +msgid "Update %s" +msgstr "Обновление %s" + +#: IDF/Views/Admin.php:155 IDF/Views/Project.php:304 +msgid "The project has been updated." +msgstr "Проект был обновлен." + +#: IDF/Views/Admin.php:192 +msgid "The project has been created." +msgstr "Проект был создан." + +#: IDF/Views/Admin.php:223 +#, php-format +msgid "Delete %s Project" +msgstr "Удалить проект %s" + +#: IDF/Views/Admin.php:230 +msgid "The project has been deleted." +msgstr "Проект удалён." + +#: IDF/Views/Admin.php:260 +msgid "Not Validated User List" +msgstr "Список не проверенных пользователей" + +#: IDF/Views/Admin.php:268 +msgid "This table shows the users in the forge." +msgstr "Таблица показывает пользователей хранилища." + +#: IDF/Views/Admin.php:272 +msgid "login" +msgstr "логин" + +#: IDF/Views/Admin.php:275 +msgid "Admin" +msgstr "Админ" + +#: IDF/Views/Admin.php:277 +msgid "Last Login" +msgstr "Последний вход" + +#: IDF/Views/Admin.php:284 +msgid "No users were found." +msgstr "Пользователей не найдено." + +#: IDF/Views/Admin.php:321 +msgid "You do not have the rights to update this user." +msgstr "У вас нет прав для обновления этого пользователя." + +#: IDF/Views/Admin.php:339 +msgid "The user has been updated." +msgstr "Пользователь был обновлен." + +#: IDF/Views/Admin.php:372 +#, php-format +msgid "The user %s has been created." +msgstr "Пользователь %s создан." + +#: IDF/Views/Admin.php:379 +msgid "Add User" +msgstr "Добавить пользователя." + +#: IDF/Views/Admin.php:395 +msgid "Usher management" +msgstr "" + +#: IDF/Views/Admin.php:432 +msgid "Usher configuration has been reloaded" +msgstr "" + +#: IDF/Views/Admin.php:436 +msgid "Usher has been shut down" +msgstr "" + +#: IDF/Views/Admin.php:441 +msgid "Usher has been started up" +msgstr "" + +#: IDF/Views/Admin.php:479 +#, php-format +msgid "The server \"%s\" has been started" +msgstr "" + +#: IDF/Views/Admin.php:483 +#, php-format +msgid "The server \"%s\" has been stopped" +msgstr "" + +#: IDF/Views/Admin.php:488 +#, php-format +msgid "The server \"%s\" has been killed" +msgstr "" + +#: IDF/Views/Admin.php:508 +#, php-format +msgid "Open connections for \"%s\"" +msgstr "" + +#: IDF/Views/Admin.php:513 +#, php-format +msgid "no connections for server \"%s\"" +msgstr "" + +#: IDF/Views/Admin.php:534 +msgid "Yes" +msgstr "Да" + +#: IDF/Views/Admin.php:534 +msgid "No" +msgstr "Нет" + +#: IDF/Views/Download.php:45 +#, php-format +msgid "%s Downloads" +msgstr "Файлы для %s" + +#: IDF/Views/Download.php:51 +msgid "This table shows the files to download." +msgstr "Таблица показывает файлы для скачивания." + +#: IDF/Views/Download.php:67 IDF/Views/Download.php:349 +msgid "Uploaded" +msgstr "Загружено" + +#: IDF/Views/Download.php:71 IDF/Views/Download.php:353 +msgid "No downloads were found." +msgstr "Файлов не найдено" + +#: IDF/Views/Download.php:94 +#, php-format +msgid "Download %s" +msgstr "Скачать %s" + +#: IDF/Views/Download.php:111 +#, php-format +msgid "The file %2$s has been updated." +msgstr "Файл %2$s обновлен." + +#: IDF/Views/Download.php:144 +#, php-format +msgid "Delete Download %s" +msgstr "Удалить файл %s" + +#: IDF/Views/Download.php:177 +msgid "The file has been deleted." +msgstr "Файл был удален." + +#: IDF/Views/Download.php:244 +#, php-format +msgid "The file has been uploaded." +msgstr "Файл загружен." + +#: IDF/Views/Download.php:271 +#, fuzzy +msgid "New Downloads from Archive" +msgstr "Добавить файл" + +#: IDF/Views/Download.php:278 +#, fuzzy +msgid "The archive has been uploaded and processed." +msgstr "Проект был обновлен." + +#: IDF/Views/Download.php:331 +#, php-format +msgid "%1$s Downloads with Label %2$s" +msgstr "%1$s загрузок с меткой %2$s" + +#: IDF/Views/Download.php:341 +#, php-format +msgid "This table shows the downloads with label %s." +msgstr "Таблица показывает файлы с меткой %s." + +#: IDF/Views/Issue.php:41 +#, php-format +msgid "%s Open Issues" +msgstr "Открытые проблемы для %s" + +#: IDF/Views/Issue.php:51 IDF/Views/Issue.php:382 IDF/Views/User.php:75 +msgid "This table shows the open issues." +msgstr "Таблица показывает открытые проблемы." + +#: IDF/Views/Issue.php:61 IDF/Views/Issue.php:220 IDF/Views/Issue.php:301 +#: IDF/Views/Issue.php:390 IDF/Views/Issue.php:542 IDF/Views/Issue.php:765 +#: IDF/Views/Issue.php:824 IDF/Views/Review.php:57 IDF/Views/User.php:81 +msgid "Id" +msgstr "Id" + +#: IDF/Views/Issue.php:64 IDF/Views/Issue.php:223 IDF/Views/Issue.php:305 +#: IDF/Views/Issue.php:393 IDF/Views/Issue.php:545 IDF/Views/Issue.php:768 +#: IDF/Views/Issue.php:827 IDF/Views/Review.php:60 IDF/Views/User.php:85 +msgid "Last Updated" +msgstr "Последнее обновление" + +#: IDF/Views/Issue.php:68 IDF/Views/Issue.php:227 IDF/Views/Issue.php:309 +#: IDF/Views/Issue.php:397 IDF/Views/Issue.php:549 IDF/Views/Issue.php:772 +#: IDF/Views/Issue.php:831 +msgid "No issues were found." +msgstr "Проблем на найдено." + +#: IDF/Views/Issue.php:113 +msgid "Not assigned" +msgstr "" + +#: IDF/Views/Issue.php:149 +#, php-format +msgid "Summary of tracked issues in %s." +msgstr "" + +#: IDF/Views/Issue.php:194 +#, php-format +msgid "Watch List: Closed Issues for %s" +msgstr "Лист слежения: закрытые проблемы для %s" + +#: IDF/Views/Issue.php:195 +#, php-format +msgid "This table shows the closed issues in your watch list for %s project." +msgstr "" +"Таблица показывает закрытые проблемы в вашем листе слежения для проекта %s." + +#: IDF/Views/Issue.php:200 +#, php-format +msgid "Watch List: Open Issues for %s" +msgstr "Лист слежения: открытые проблемы для %s" + +#: IDF/Views/Issue.php:201 +#, php-format +msgid "This table shows the open issues in your watch list for %s project." +msgstr "" +"Таблица показывает открытые проблемы в вашем листе слежения для проекта %s." + +#: IDF/Views/Issue.php:277 +msgid "Watch List: Closed Issues" +msgstr "Лист слежения: закрытые проблемы" + +#: IDF/Views/Issue.php:278 +msgid "This table shows the closed issues in your watch list." +msgstr "Таблица показывает закрытые проблемы в вашем листе слежения." + +#: IDF/Views/Issue.php:283 +msgid "Watch List: Open Issues" +msgstr "Лист слежения: открытые проблемы" + +#: IDF/Views/Issue.php:284 +msgid "This table shows the open issues in your watch list." +msgstr "Таблица показывает открытые проблемы в Вашем листе слежения." + +#: IDF/Views/Issue.php:303 IDF/Views/User.php:82 +msgid "Project" +msgstr "Проект" + +#: IDF/Views/Issue.php:344 +#, fuzzy, php-format +msgid "%1$s %2$s Submitted %3$s Issues" +msgstr "Отправленные проблемы:" + +#: IDF/Views/Issue.php:348 +#, php-format +msgid "%1$s %2$s Closed Submitted %3$s Issues" +msgstr "" + +#: IDF/Views/Issue.php:352 +#, fuzzy, php-format +msgid "%1$s %2$s Closed Working %3$s Issues" +msgstr "%s закрытых проблем" + +#: IDF/Views/Issue.php:356 +#, php-format +msgid "%1$s %2$s Working %3$s Issues" +msgstr "" + +#: IDF/Views/Issue.php:417 +msgid "Submit a new issue" +msgstr "Добавить проблему" + +#: IDF/Views/Issue.php:433 +#, fuzzy, php-format +msgid "Issue %2$d has been created." +msgstr "Проблема %d создана." + +#: IDF/Views/Issue.php:490 +#, php-format +msgid "Search issues - %s" +msgstr "Поиск проблем - %s" + +#: IDF/Views/Issue.php:492 +#, php-format +msgid "Search closed issues - %s" +msgstr "Поиск закрытых проблем - %s" + +#: IDF/Views/Issue.php:539 +msgid "This table shows the found issues." +msgstr "Таблица показывает найденные проблемы." + +#: IDF/Views/Issue.php:604 +#, fuzzy, php-format +msgid "Issue %2$d: %3$s" +msgstr "Проблема %d: %s" + +#: IDF/Views/Issue.php:628 +#, fuzzy, php-format +msgid "Issue %2$d has been updated." +msgstr "Проблема %d обновлена." + +#: IDF/Views/Issue.php:718 +#, php-format +msgid "View %s" +msgstr "Смотреть %s" + +#: IDF/Views/Issue.php:745 +#, php-format +msgid "%s Closed Issues" +msgstr "%s закрытых проблем" + +#: IDF/Views/Issue.php:755 +msgid "This table shows the closed issues." +msgstr "Таблица показывает закрытые проблемы." + +#: IDF/Views/Issue.php:798 +#, php-format +msgid "%1$s Issues with Label %2$s" +msgstr "%1$s проблем с меткой %2$s" + +#: IDF/Views/Issue.php:801 +#, php-format +msgid "%1$s Closed Issues with Label %2$s" +msgstr "%1$s закрытых проблем с меткой %2$s" + +#: IDF/Views/Issue.php:814 +#, php-format +msgid "This table shows the issues with label %s." +msgstr "Таблица показывает проблемы с меткой %s." + +#: IDF/Views/Issue.php:937 +msgid "The issue has been removed from your watch list." +msgstr "Проблема выла удалена и вашего листа слежения." + +#: IDF/Views/Issue.php:940 +msgid "The issue has been added to your watch list." +msgstr "Проблема была добавлена в Ваш лист слежения." + +#: IDF/Views/Issue.php:1037 +msgid "On your watch list." +msgstr "В Вашем списке наблюдения." + +#: IDF/Views/Project.php:95 +msgid "Issues and Comments" +msgstr "Проблемы и Комментарии" + +#: IDF/Views/Project.php:99 +msgid "Documents" +msgstr "Документы" + +#: IDF/Views/Project.php:101 +msgid "Reviews and Patches" +msgstr "Рецензии и патчи" + +#: IDF/Views/Project.php:180 +msgid "This table shows the project updates." +msgstr "Таблица показывает обновления проекта." + +#: IDF/Views/Project.php:191 +msgid "Change" +msgstr "Изменить" + +#: IDF/Views/Project.php:195 +msgid "No changes were found." +msgstr "Изменений не найдено." + +#: IDF/Views/Project.php:296 +#, php-format +msgid "%s Project Summary" +msgstr "Краткое описание %s" + +#: IDF/Views/Project.php:335 +#, php-format +msgid "%s Issue Tracking Configuration" +msgstr "Настройка слежения за проблемами %s" + +#: IDF/Views/Project.php:344 +msgid "The issue tracking configuration has been saved." +msgstr "Настройки слежения за проблемами сохранены." + +#: IDF/Views/Project.php:381 +#, php-format +msgid "%s Downloads Configuration" +msgstr "Настройка загрузок %s" + +#: IDF/Views/Project.php:393 +msgid "The downloads configuration has been saved." +msgstr "Конфигурации загрузки сохранены." + +#: IDF/Views/Project.php:428 +#, php-format +msgid "%s Documentation Configuration" +msgstr "Настройка документации %s" + +#: IDF/Views/Project.php:437 +msgid "The documentation configuration has been saved." +msgstr "Настройки документации сохранены." + +#: IDF/Views/Project.php:471 +#, php-format +msgid "%s Project Members" +msgstr "Участники проекта %s" + +#: IDF/Views/Project.php:480 +msgid "The project membership has been saved." +msgstr "Участие в проекте сохранено." + +#: IDF/Views/Project.php:503 +#, php-format +msgid "%s Tabs Access Rights" +msgstr "права доступа к вкладкам для %s" + +#: IDF/Views/Project.php:517 +#, fuzzy +msgid "" +"The project tabs access rights and notification settings have been saved." +msgstr "Права доступа к вкладкам для проекта сохранены." + +#: IDF/Views/Project.php:566 +#, php-format +msgid "%s Source" +msgstr "Исходный код %s" + +#: IDF/Views/Project.php:580 +msgid "The project source configuration has been saved." +msgstr "Настройки исходного кода проекта сохранены." + +#: IDF/Views/Review.php:41 +#, php-format +msgid "%s Code Reviews" +msgstr "Рецензии кода для %s" + +#: IDF/Views/Review.php:48 +msgid "This table shows the latest reviews." +msgstr "Таблица показывает последние аудиты." + +#: IDF/Views/Review.php:64 +msgid "No reviews were found." +msgstr "Рецензий не найдено." + +#: IDF/Views/Review.php:94 +#, fuzzy, php-format +msgid "The code review %2$d has been created." +msgstr "Аудит кода %d создан." + +#: IDF/Views/Review.php:140 +#, fuzzy, php-format +msgid "Review %2$d: %3$s" +msgstr "Обзор %d: %s" + +#: IDF/Views/Review.php:160 +#, fuzzy, php-format +msgid "Your code review %2$d has been published." +msgstr "Ваша рецензия %d была опубликована." + +#: IDF/Views/Source.php:40 +#, php-format +msgid "%s Source Help" +msgstr "Помощь по исходному коду для %s" + +#: IDF/Views/Source.php:58 +#, php-format +msgid "%s Invalid Revision" +msgstr "" + +#: IDF/Views/Source.php:82 +#, php-format +msgid "%s Ambiguous Revision" +msgstr "" + +#: IDF/Views/Source.php:107 +#, php-format +msgid "%1$s %2$s Change Log" +msgstr "история изменений %1$s %2$s" + +#: IDF/Views/Source.php:153 IDF/Views/Source.php:234 IDF/Views/Source.php:362 +#, php-format +msgid "%1$s %2$s Source Tree" +msgstr "%1$s %2$s дерево исходного кода" + +#: IDF/Views/Source.php:310 +#, php-format +msgid "%s Commit Details" +msgstr "Детали комита %s" + +#: IDF/Views/Source.php:311 +#, fuzzy, php-format +msgid "%1$s Commit Details - %2$s" +msgstr "Детали комита %s - %s" + +#: IDF/Views/User.php:59 +msgid "Your Dashboard - Working Issues" +msgstr "Сводная информация - Проблемы в работе" + +#: IDF/Views/User.php:62 +msgid "Your Dashboard - Submitted Issues" +msgstr "Сводная информация - Отправленные проблемы" + +#: IDF/Views/User.php:89 +msgid "No issues are assigned to you, yeah!" +msgstr "На Вас не назначена ни одна проблема, ура!" + +#: IDF/Views/User.php:89 +msgid "All the issues you submitted are fixed, yeah!" +msgstr "Все отправленные Вами проблемы решены, ура!" + +#: IDF/Views/User.php:121 +msgid "Your personal information has been updated." +msgstr "Информация о вас обновлена." + +#: IDF/Views/User.php:133 +msgid "Your Account" +msgstr "Ваша учетная запись" + +#: IDF/Views/User.php:157 +msgid "The public key has been deleted." +msgstr "" + +#: IDF/Views/User.php:177 +msgid "The address has been deleted." +msgstr "Адрес был удалён." + +#: IDF/Views/User.php:200 +msgid "Confirm The Email Change" +msgstr "Подтвердите изменения эл. адреса" + +#: IDF/Views/User.php:232 +#, php-format +msgid "Your new email address \"%s\" has been validated. Thank you!" +msgstr "Ваш новый электронный адрес \"%s\" подтвержден. Спасибо!" + +#: IDF/Views/Wiki.php:41 +#, php-format +msgid "%s Documentation" +msgstr "Документация для %s" + +#: IDF/Views/Wiki.php:48 +msgid "This table shows the documentation pages." +msgstr "Таблица показывает страницы документации." + +#: IDF/Views/Wiki.php:61 IDF/Views/Wiki.php:144 IDF/Views/Wiki.php:185 +msgid "Page Title" +msgstr "Заголовок страницы" + +#: IDF/Views/Wiki.php:63 IDF/Views/Wiki.php:103 IDF/Views/Wiki.php:146 +#: IDF/Views/Wiki.php:187 +msgid "Updated" +msgstr "Обновлено" + +#: IDF/Views/Wiki.php:67 IDF/Views/Wiki.php:191 +msgid "No documentation pages were found." +msgstr "Страниц документации не найдено." + +#: IDF/Views/Wiki.php:88 +#, fuzzy, php-format +msgid "%s Documentation Resources" +msgstr "Документация для %s" + +#: IDF/Views/Wiki.php:94 +#, fuzzy +msgid "This table shows the resources that can be used on documentation pages." +msgstr "Таблица показывает страницы документации." + +#: IDF/Views/Wiki.php:100 +#, fuzzy +msgid "Resource Title" +msgstr "Исходный код" + +#: IDF/Views/Wiki.php:107 +#, fuzzy +msgid "No resources were found." +msgstr "Проблем на найдено." + +#: IDF/Views/Wiki.php:128 +#, php-format +msgid "Documentation Search - %s" +msgstr "Поиск документации - %s" + +#: IDF/Views/Wiki.php:139 +msgid "This table shows the pages found." +msgstr "Таблица показывает найденные страницы." + +#: IDF/Views/Wiki.php:150 +msgid "No pages were found." +msgstr "Страниц не найдено." + +#: IDF/Views/Wiki.php:169 +#, php-format +msgid "%1$s Documentation Pages with Label %2$s" +msgstr "%1$s Страниц документации с меткой %2$s" + +#: IDF/Views/Wiki.php:179 +#, php-format +msgid "This table shows the documentation pages with label %s." +msgstr "Таблица показывает страницы документации с меткой %s." + +#: IDF/Views/Wiki.php:222 +#, fuzzy, php-format +msgid "The page %2$s has been created." +msgstr "Страница%s создана." + +#: IDF/Views/Wiki.php:265 +#, fuzzy, php-format +msgid "The resource %2$s has been created." +msgstr "Страница%s создана." + +#: IDF/Views/Wiki.php:409 IDF/Views/Wiki.php:448 +msgid "The old revision has been deleted." +msgstr "Старая версия удалена." + +#: IDF/Views/Wiki.php:415 IDF/Views/Wiki.php:454 +#, php-format +msgid "Delete Old Revision of %s" +msgstr "Удалить старую ревизию of %s" + +#: IDF/Views/Wiki.php:496 +#, fuzzy, php-format +msgid "The page %2$s has been updated." +msgstr "Страница %s обновлена." + +#: IDF/Views/Wiki.php:548 +#, fuzzy, php-format +msgid "The resource %2$s has been updated." +msgstr "Файл %2$s обновлен." + +#: IDF/Views/Wiki.php:583 +msgid "The documentation page has been deleted." +msgstr "Страница документации удалена." + +#: IDF/Views/Wiki.php:591 +#, php-format +msgid "Delete Page %s" +msgstr "Удалить страницу %s" + +#: IDF/Views/Wiki.php:623 +#, fuzzy +msgid "The documentation resource has been deleted." +msgstr "Страница документации удалена." + +#: IDF/Views/Wiki.php:631 +#, fuzzy, php-format +msgid "Delete Resource %s" +msgstr "Удалить страницу %s" + +#: IDF/Views.php:173 IDF/Views.php:199 +msgid "Confirm Your Account Creation" +msgstr "Подтвердите создание учетной записи" + +#: IDF/Views.php:219 +msgid "Welcome! You can now participate in the life of your project of choice." +msgstr "" +"Добро пожаловать! Теперь Вы можете учавствовать в жизни выбранного проекта." + +#: IDF/Views.php:245 IDF/Views.php:269 IDF/Views.php:310 +msgid "Password Recovery" +msgstr "Восстановление пароля" + +#: IDF/Views.php:289 +msgid "" +"Welcome back! Next time, you can use your broswer options to remember the " +"password." +msgstr "" +"Рады Вас снова видеть! Следующий раз Вы можете использовать функцию " +"сохранения пароля в Вашем браузере." + +#: IDF/Views.php:331 +msgid "Here to Help You!" +msgstr "Здесь чтобы помогать Вам!" + +#: IDF/Views.php:347 +msgid "InDefero Upload Archive Format" +msgstr "" + +#: IDF/Views.php:363 +msgid "InDefero API (Application Programming Interface)" +msgstr "InDefero API (Application Programming Interface)" + +#: IDF/Wiki/Page.php:62 IDF/Wiki/Resource.php:64 +msgid "title" +msgstr "заголовок" + +#: IDF/Wiki/Page.php:63 +msgid "" +"The title of the page must only contain letters, digits or the dash " +"character. For example: My-new-Wiki-Page." +msgstr "" +"Заголовок страницы должен содержать только буквы, цифры или дефис. Например: " +"Моя-новая-вики-страница." + +#: IDF/Wiki/Page.php:71 +msgid "A one line description of the page content." +msgstr "Описание содержимого страницы в одну строчку." + +#: IDF/Wiki/Page.php:196 IDF/Wiki/PageRevision.php:196 +#, php-format +msgid "%2$s, %3$s" +msgstr "%2$s, %3$s" + +#: IDF/Wiki/Page.php:198 +#, fuzzy, php-format +msgid "Creation of page %2$s, by %3$s" +msgstr "Создание страницы %s, %s" + +#: IDF/Wiki/Page.php:208 +#, fuzzy, php-format +msgid "%1$s: Documentation page %2$s added - %3$s" +msgstr "%s: Страницы документации %s добавлена - %s" + +#: IDF/Wiki/PageRevision.php:48 +msgid "page" +msgstr "страница" + +#: IDF/Wiki/PageRevision.php:66 IDF/Wiki/ResourceRevision.php:64 +msgid "A one line description of the changes." +msgstr "Описание изменений в одну строку." + +#: IDF/Wiki/PageRevision.php:72 +msgid "content" +msgstr "содержание" + +#: IDF/Wiki/PageRevision.php:218 IDF/Wiki/ResourceRevision.php:311 +#, fuzzy, php-format +msgid "Change of %2$s, by %3$s" +msgstr "Изменение %s, %s" + +#: IDF/Wiki/PageRevision.php:231 +#, fuzzy, php-format +msgid "%1$s: Documentation page %2$s updated - %3$s" +msgstr "%s: Страница документации %s обновлена - %s" + +#: IDF/Wiki/PageRevision.php:293 +#, fuzzy, php-format +msgid "New Documentation Page %1$s - %2$s (%3$s)" +msgstr "Новая страница документации %s - %s (%s)" + +#: IDF/Wiki/PageRevision.php:297 +#, fuzzy, php-format +msgid "Documentation Page Changed %1$s - %2$s (%3$s)" +msgstr "Страница документации изменена %s - %s (%s)" + +#: IDF/Wiki/Resource.php:65 +#, fuzzy +msgid "" +"The title of the resource must only contain letters, digits, dots or the " +"dash character. For example: my-resource.png." +msgstr "" +"Заголовок страницы должен содержать только буквы, цифры или дефис. Например: " +"Моя-новая-вики-страница." + +#: IDF/Wiki/Resource.php:72 +msgid "MIME media type" +msgstr "" + +#: IDF/Wiki/Resource.php:73 +msgid "The MIME media type of the resource." +msgstr "" + +#: IDF/Wiki/Resource.php:81 +#, fuzzy +msgid "A one line description of the resource." +msgstr "Краткое описание проекта." + +#: IDF/Wiki/Resource.php:176 IDF/Wiki/ResourceRevision.php:308 +#, fuzzy, php-format +msgid "%2$s, %3$s" +msgstr "%2$s, %3$s" + +#: IDF/Wiki/Resource.php:178 +#, fuzzy, php-format +msgid "Creation of resource %2$s, by %3$s" +msgstr "Создание страницы %s, %s" + +#: IDF/Wiki/Resource.php:188 +#, fuzzy, php-format +msgid "%1$s: Documentation resource %2$s added - %3$s" +msgstr "%s: Страницы документации %s добавлена - %s" + +#: IDF/Wiki/ResourceRevision.php:47 +#, fuzzy +msgid "resource" +msgstr "Исходный код" + +#: IDF/Wiki/ResourceRevision.php:78 +msgid "File extension" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:79 +msgid "The file extension of the uploaded resource." +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:94 +msgid "page usage" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:116 +#, php-format +msgid "id %d: %s" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:263 +#, fuzzy, php-format +msgid "Download (%s)" +msgstr "Скачать %s" + +#: IDF/Wiki/ResourceRevision.php:270 +msgid "View resource details" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:324 +#, fuzzy, php-format +msgid "%1$s: Documentation resource %2$s updated - %3$s" +msgstr "%s: Страница документации %s обновлена - %s" + +#~ msgid "" +#~ "The master branch is empty or contains illegal characters, please use " +#~ "only letters, digits, dashs and dots as separators." +#~ msgstr "" +#~ "Мастер бранч пустой или содержит недопустимые символы, пожалуйста, " +#~ "используйте только латинские буквы, цифры, дефисы и точки в качестве " +#~ "разделителей." + +#~ msgid "Learn more about the post-commit web hooks." +#~ msgstr "Прочитать больше про post-commit web hooks." + +#~ msgid "Your mail" +#~ msgstr "Ваша почта" + +#~ msgid "" +#~ "Notification emails will be sent from the %%from_email%% " +#~ "address, if you send the email to a mailing list, you may need to " +#~ "register this email address. Multiple email addresses must be separated " +#~ "through commas (','). If you do not want to send emails for a given type " +#~ "of changes, simply leave the corresponding field empty." +#~ msgstr "" +#~ "Уведомления по электронной почте будут отправлены с адреса %" +#~ "%from_email%%. Если Вы отправляете письма на адрес рассылки " +#~ "возможно Вам понадобиться зарегистрировать этот адрес. Несколько адресов " +#~ "должны разделяться запятой (','). Если Вы не хотите отправлять сообщения " +#~ "на выбранное действие просто оставьте соотвествующее поле пустым." + +#~ msgid "You have here access to the administration of the forge." +#~ msgstr "Вы здесь имеете доступ к администрированию хранилища." + +#~ msgid "Forge statistics" +#~ msgstr "Статистика хранилища" + +#~ msgid "Projects:" +#~ msgstr "Проектов:" diff --git a/indefero/src/IDF/locale/sl/idf.po b/indefero/src/IDF/locale/sl/idf.po new file mode 100644 index 0000000..ea113a4 --- /dev/null +++ b/indefero/src/IDF/locale/sl/idf.po @@ -0,0 +1,5436 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# William MARTIN , 2011. +msgid "" +msgstr "" +"Project-Id-Version: Indefero\n" +"Report-Msgid-Bugs-To: http://projects.ceondo.com/p/indefero/issues/\n" +"POT-Creation-Date: 2012-03-22 01:16+0100\n" +"PO-Revision-Date: 2011-10-31 00:19+0000\n" +"Last-Translator: tommyd \n" +"Language-Team: LANGUAGE \n" +"Language: sl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n" +"%100==4 ? 2 : 3)\n" + +#: IDF/Commit.php:55 IDF/Conf.php:54 IDF/Issue.php:52 +#: IDF/ProjectActivity.php:49 IDF/Review.php:65 IDF/Search/Occ.php:69 +#: IDF/Tag.php:52 IDF/Upload.php:49 IDF/Wiki/Page.php:54 +#: IDF/Wiki/Resource.php:56 +msgid "project" +msgstr "projekt" + +#: IDF/Commit.php:63 IDF/Issue.php:67 IDF/IssueComment.php:65 +#: IDF/IssueFile.php:57 IDF/IssueRelation.php:69 IDF/Review/Comment.php:69 +#: IDF/Review.php:80 IDF/Upload.php:91 IDF/Wiki/Page.php:78 +#: IDF/Wiki/PageRevision.php:79 IDF/Wiki/Resource.php:88 +#: IDF/Wiki/ResourceRevision.php:86 +msgid "submitter" +msgstr "pošiljatelj" + +#: IDF/Commit.php:87 IDF/Issue.php:60 IDF/Review/Patch.php:60 +#: IDF/Review.php:73 IDF/Upload.php:57 IDF/Wiki/Page.php:70 +#: IDF/Wiki/PageRevision.php:65 IDF/Wiki/Resource.php:80 +#: IDF/Wiki/ResourceRevision.php:63 +msgid "summary" +msgstr "povzetek" + +#: IDF/Commit.php:93 +msgid "changelog" +msgstr "dnevnik sprememb" + +#: IDF/Commit.php:100 IDF/Issue.php:105 IDF/IssueComment.php:79 +#: IDF/IssueFile.php:96 IDF/IssueRelation.php:75 IDF/Review/Comment.php:90 +#: IDF/Review/FileComment.php:75 IDF/Review/Patch.php:87 IDF/Review.php:108 +#: IDF/Upload.php:112 IDF/Wiki/Page.php:100 IDF/Wiki/PageRevision.php:92 +#: IDF/Wiki/Resource.php:95 IDF/Wiki/ResourceRevision.php:101 +msgid "creation date" +msgstr "datum nastanka" + +#: IDF/Commit.php:238 +#, php-format +msgid "Commit %1$s, by %2$s" +msgstr "" + +#: IDF/Commit.php:337 +#, php-format +msgid "New Commit %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Conf.php:61 IDF/Gconf.php:73 +msgid "key" +msgstr "ključ" + +#: IDF/Conf.php:67 IDF/Gconf.php:79 IDF/ProjectActivity.php:62 +msgid "value" +msgstr "vrednost" + +#: IDF/Diff.php:460 +msgid "Old" +msgstr "Staro " + +#: IDF/Diff.php:460 +msgid "New" +msgstr "Novo" + +#: IDF/EmailAddress.php:49 IDF/Key.php:49 +msgid "user" +msgstr "uporabnik" + +#: IDF/EmailAddress.php:55 +msgid "email" +msgstr "" + +#: IDF/Form/Admin/ForgeConf.php:34 +msgid "Custom forge page enabled" +msgstr "" + +#: IDF/Form/Admin/ForgeConf.php:39 IDF/Form/WikiPageCreate.php:80 +#: IDF/Form/WikiPageUpdate.php:72 +msgid "Content" +msgstr "Vsebina" + +#: IDF/Form/Admin/LabelConf.php:40 +#, fuzzy +msgid "Predefined project labels" +msgstr "Zaseben projekt" + +#: IDF/Form/Admin/LabelConf.php:55 +#, php-format +msgid "" +"The label \"%s\" is invalid: A label must only consist of alphanumeric " +"characters and dashes, and can optionally contain a \":\" with a group " +"prefix." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:38 IDF/Views/Project.php:600 +msgid "git" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:39 IDF/Views/Project.php:601 +msgid "Subversion" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:40 IDF/Views/Project.php:602 +msgid "mercurial" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:41 IDF/Views/Project.php:603 +msgid "monotone" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:49 IDF/Form/Admin/ProjectUpdate.php:44 +#: IDF/Form/ProjectConf.php:39 IDF/Views/Admin.php:86 IDF/Views/Admin.php:273 +msgid "Name" +msgstr "Ime" + +#: IDF/Form/Admin/ProjectCreate.php:55 IDF/Form/TabsConf.php:101 +#: IDF/gettexttemplates/idf/base-full.html.php:5 +#: IDF/gettexttemplates/idf/base-full.html~.php:5 +#: IDF/gettexttemplates/idf/base.html.php:5 +#: IDF/gettexttemplates/idf/base.html~.php:5 +#: IDF/gettexttemplates/idf/main-menu.html.php:9 +#: IDF/gettexttemplates/idf/project-list.html.php:5 +#: IDF/gettexttemplates/idf/project-list.html.php:7 +msgid "Private project" +msgstr "Zaseben projekt" + +#: IDF/Form/Admin/ProjectCreate.php:62 +msgid "Shortname" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:64 +msgid "" +"It must be unique for each project and composed only of letters, digits and " +"dash (-) like \"my-project\"." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:69 IDF/Form/Admin/ProjectUpdate.php:50 +msgid "Short description" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:70 IDF/Form/Admin/ProjectUpdate.php:51 +#: IDF/Project.php:79 +msgid "A one line description of the project." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:77 IDF/Form/Admin/ProjectUpdate.php:58 +#: IDF/Form/ProjectConf.php:56 +msgid "External URL" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:84 +msgid "Repository type" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:92 +msgid "Remote Subversion repository" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:99 IDF/Form/SourceConf.php:40 +msgid "Repository username" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:106 IDF/Form/SourceConf.php:47 +msgid "Repository password" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:113 IDF/Form/Admin/ProjectUpdate.php:66 +msgid "Master branch" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:116 IDF/Form/Admin/ProjectUpdate.php:69 +msgid "" +"This should be a world-wide unique identifier for your project. A reverse " +"DNS notation like \"com.my-domain.my-project\" is a good idea." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:121 IDF/Form/Admin/ProjectUpdate.php:95 +#: IDF/Form/MembersConf.php:46 IDF/Form/TabsConf.php:53 +#: IDF/Form/TabsConf.php:72 +msgid "Project owners" +msgstr "Lastniki projekta" + +#: IDF/Form/Admin/ProjectCreate.php:130 IDF/Form/Admin/ProjectUpdate.php:103 +#: IDF/Form/MembersConf.php:54 IDF/Form/TabsConf.php:52 +#: IDF/Form/TabsConf.php:78 +msgid "Project members" +msgstr "Člani projekta" + +#: IDF/Form/Admin/ProjectCreate.php:140 IDF/Form/Admin/ProjectUpdate.php:85 +#: IDF/Form/IssueCreate.php:168 IDF/Form/IssueUpdate.php:164 +#: IDF/Form/ProjectConf.php:73 IDF/Form/UpdateUpload.php:71 +#: IDF/Form/Upload.php:70 IDF/Form/WikiPageCreate.php:93 +#: IDF/Form/WikiPageUpdate.php:104 +msgid "Labels" +msgstr "Oznake" + +#: IDF/Form/Admin/ProjectCreate.php:155 +msgid "Project template" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:157 +msgid "" +"Use the given project to initialize the new project. Access rights and " +"general configuration will be taken from the template project." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:204 +msgid "" +"Only a remote repository available through HTTP or HTTPS is allowed. For " +"example \"http://somewhere.com/svn/trunk\"." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:220 IDF/Form/Admin/ProjectUpdate.php:117 +msgid "" +"The master branch is empty or contains illegal characters, please use only " +"letters, digits, dashes and dots as separators." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:230 IDF/Form/Admin/ProjectUpdate.php:128 +msgid "This master branch is already used. Please select another one." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:241 +msgid "" +"This shortname contains illegal characters, please use only letters, digits " +"and dash (-)." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:244 +msgid "The shortname cannot start with the dash (-) character." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:247 +msgid "The shortname cannot end with the dash (-) character." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:252 +msgid "This shortname is already used. Please select another one." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:303 IDF/Form/Admin/ProjectDelete.php:78 +#: IDF/Form/Admin/ProjectUpdate.php:153 IDF/Form/Admin/UserCreate.php:106 +#: IDF/Form/Admin/UserUpdate.php:191 IDF/Form/IssueCreate.php:338 +#: IDF/Form/IssueUpdate.php:329 IDF/Form/MembersConf.php:64 +#: IDF/Form/Password.php:76 IDF/Form/Register.php:112 +#: IDF/Form/ReviewCreate.php:187 IDF/Form/ReviewFileComment.php:143 +#: IDF/Form/TabsConf.php:122 IDF/Form/UpdateUpload.php:126 +#: IDF/Form/Upload.php:149 IDF/Form/UploadArchive.php:137 +#: IDF/Form/UserAccount.php:216 IDF/Form/UserChangeEmail.php:80 +#: IDF/Form/WikiPageCreate.php:167 IDF/Form/WikiPageDelete.php:59 +#: IDF/Form/WikiPageUpdate.php:178 IDF/Form/WikiResourceCreate.php:123 +#: IDF/Form/WikiResourceDelete.php:59 IDF/Form/WikiResourceUpdate.php:124 +msgid "Cannot save the model from an invalid form." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:341 +msgid "" +"Click on the Project Management tab to set the description of your project." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:426 +msgid "This project is not available." +msgstr "" + +#: IDF/Form/Admin/ProjectDelete.php:41 +msgid "Confirmation code" +msgstr "" + +#: IDF/Form/Admin/ProjectDelete.php:46 +msgid "I have made a backup of all the important data of this project." +msgstr "" + +#: IDF/Form/Admin/ProjectDelete.php:55 +msgid "" +"The confirmation code does not match. Please provide a valid confirmation " +"code to delete the project." +msgstr "" + +#: IDF/Form/Admin/ProjectDelete.php:63 +msgid "Sorry, you really need to backup your data before deletion." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:37 IDF/Form/Admin/UserUpdate.php:38 +#: IDF/Form/RegisterConfirmation.php:50 IDF/Form/UserAccount.php:40 +msgid "First name" +msgstr "Ime" + +#: IDF/Form/Admin/UserCreate.php:46 IDF/Form/Admin/UserUpdate.php:47 +#: IDF/Form/RegisterConfirmation.php:59 IDF/Form/UserAccount.php:49 +msgid "Last name" +msgstr "Priimek" + +#: IDF/Form/Admin/UserCreate.php:56 +msgid "Login" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:60 +msgid "" +"The login must be between 3 and 15 characters long and contains only letters " +"and digits." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:69 IDF/Form/Admin/UserUpdate.php:57 +msgid "Email" +msgstr "E-naslov" + +#: IDF/Form/Admin/UserCreate.php:71 +msgid "" +"Double check the email address as the password is sent directly to the user." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:76 IDF/Form/Admin/UserUpdate.php:67 +#: IDF/Form/UserAccount.php:66 +msgid "Language" +msgstr "Jezik" + +#: IDF/Form/Admin/UserCreate.php:87 IDF/Form/UserAccount.php:161 +msgid "Add a public key" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:92 +msgid "" +"Paste a SSH or monotone public key. Be careful to not provide your private " +"key here!" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:157 +msgid "Your details to access your forge." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:189 IDF/Form/UserAccount.php:429 +#: IDF/Form/UserAccount.php:438 +#, php-format +msgid "The email \"%s\" is already used." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:198 IDF/Form/Register.php:72 +#, php-format +msgid "The login \"%s\" can only contain letters and digits." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:203 IDF/Form/Register.php:77 +#, php-format +msgid "The login \"%s\" is already used, please find another one." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:78 +msgid "Password" +msgstr "Geslo" + +#: IDF/Form/Admin/UserUpdate.php:81 +msgid "Leave blank if you do not want to change the password." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:81 +msgid "" +"The password must be hard for other people to guess, but easy for the user " +"to remember." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:89 +msgid "Confirm password" +msgstr "Potrditev gesla" + +#: IDF/Form/Admin/UserUpdate.php:100 IDF/Form/IssueCreate.php:66 +#: IDF/Form/ProjectConf.php:48 IDF/Form/ReviewCreate.php:54 +#: IDF/Form/UpdateUpload.php:51 IDF/Form/Upload.php:49 +#: IDF/Form/UserAccount.php:101 IDF/Form/WikiPageCreate.php:70 +#: IDF/Form/WikiPageUpdate.php:60 IDF/Form/WikiResourceCreate.php:54 +#: IDF/Form/WikiResourceUpdate.php:46 IDF/Views/Wiki.php:102 +msgid "Description" +msgstr "Opis" + +#: IDF/Form/Admin/UserUpdate.php:109 IDF/Form/UserAccount.php:110 +msgid "Twitter username" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:119 IDF/Form/UserAccount.php:120 +msgid "Public email address" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:129 IDF/Form/UserAccount.php:130 +msgid "Website URL" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:139 IDF/Form/UserAccount.php:140 +msgid "Upload custom avatar" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:146 IDF/Form/UserAccount.php:147 +msgid "" +"An image file with a width and height not larger than 60 pixels (bigger " +"images are scaled down)." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:151 IDF/Form/UserAccount.php:152 +msgid "Remove custom avatar" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:155 IDF/Form/UserAccount.php:156 +msgid "Tick this to delete the custom avatar." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:161 IDF/Views/Admin.php:274 +msgid "Staff" +msgstr "Osebje" + +#: IDF/Form/Admin/UserUpdate.php:164 +msgid "If you give staff rights to a user, you really need to trust him." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:172 IDF/Views/Admin.php:276 +msgid "Active" +msgstr "Aktiven" + +#: IDF/Form/Admin/UserUpdate.php:176 +msgid "" +"If the user is not getting the confirmation email or is abusing the system, " +"you can directly enable or disable their account here." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:274 +msgid "--- is not a valid first name." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:290 +msgid "" +"A user with this email already exists, please provide another email address." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:301 IDF/Form/UserAccount.php:398 +msgid "For security reason, you cannot upload a file with this extension." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:316 IDF/Form/UserAccount.php:461 +msgid "The passwords do not match. Please give them again." +msgstr "" + +#: IDF/Form/Field/EmailList.php:45 +msgid "Please enter one or more valid email addresses." +msgstr "" + +#: IDF/Form/IssueCreate.php:57 IDF/Form/IssueUpdate.php:46 +#: IDF/Form/ReviewCreate.php:45 IDF/Form/ReviewFileComment.php:73 +#: IDF/Form/UpdateUpload.php:42 IDF/Form/Upload.php:40 +#: IDF/gettexttemplates/idf/issues/base.html.php:3 IDF/Views/Download.php:65 +#: IDF/Views/Download.php:347 IDF/Views/Issue.php:62 IDF/Views/Issue.php:221 +#: IDF/Views/Issue.php:302 IDF/Views/Issue.php:391 IDF/Views/Issue.php:543 +#: IDF/Views/Issue.php:766 IDF/Views/Issue.php:825 IDF/Views/Review.php:58 +#: IDF/Views/User.php:83 IDF/Views/Wiki.php:62 IDF/Views/Wiki.php:145 +#: IDF/Views/Wiki.php:186 +msgid "Summary" +msgstr "Povzetek" + +#: IDF/Form/IssueCreate.php:76 IDF/Form/IssueUpdate.php:66 +#: IDF/Form/ReviewCreate.php:83 +msgid "The \"upload_issue_path\" configuration variable was not set." +msgstr "" + +#: IDF/Form/IssueCreate.php:86 IDF/Form/IssueUpdate.php:76 +msgid "Attach a file" +msgstr "Izberi datoteko" + +#: IDF/Form/IssueCreate.php:99 IDF/Form/IssueUpdate.php:89 +#: IDF/Form/ReviewCreate.php:103 IDF/Form/ReviewFileComment.php:83 +#: IDF/Views/Issue.php:63 IDF/Views/Issue.php:222 IDF/Views/Issue.php:304 +#: IDF/Views/Issue.php:392 IDF/Views/Issue.php:544 IDF/Views/Issue.php:767 +#: IDF/Views/Issue.php:826 IDF/Views/Review.php:59 IDF/Views/User.php:84 +msgid "Status" +msgstr "Stanje" + +#: IDF/Form/IssueCreate.php:108 IDF/Form/IssueUpdate.php:99 +msgid "Owner" +msgstr "Lastnik" + +#: IDF/Form/IssueCreate.php:118 IDF/Form/IssueUpdate.php:112 +#: IDF/Form/IssueUpdate.php:129 +msgid "This issue" +msgstr "" + +#: IDF/Form/IssueCreate.php:210 +msgid "You cannot add a label with the \"Status\" prefix to an issue." +msgstr "" + +#: IDF/Form/IssueCreate.php:211 IDF/Form/IssueCreate.php:218 +#: IDF/Form/UpdateUpload.php:110 IDF/Form/Upload.php:121 +#: IDF/Form/WikiPageCreate.php:151 IDF/Form/WikiPageUpdate.php:162 +msgid "You provided an invalid label." +msgstr "" + +#: IDF/Form/IssueCreate.php:217 IDF/Form/UpdateUpload.php:109 +#, php-format +msgid "You cannot provide more than one label from the %s class to an issue." +msgstr "" + +#: IDF/Form/IssueCreate.php:228 IDF/Form/IssueUpdate.php:194 +msgid "You need to provide a description of the issue." +msgstr "" + +#: IDF/Form/IssueCreate.php:251 IDF/Form/ReviewCreate.php:159 +msgid "You provided an invalid status." +msgstr "" + +#: IDF/Form/IssueCreate.php:272 +msgid "You provided an invalid relation type." +msgstr "" + +#: IDF/Form/IssueCreate.php:294 +#, php-format +msgid "The value \"%s\" is not a valid issue id." +msgstr "" + +#: IDF/Form/IssueCreate.php:300 +#, php-format +msgid "The issue \"%s\" does not exist." +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:86 +msgid "is related to" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:87 +msgid "blocks" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:88 +msgid "is blocked by" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:89 +msgid "duplicates" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:90 +msgid "is duplicated by" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:97 +msgid "" +"Define an issue template to hint the reporter to provide certain information" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:106 +msgid "Open issue status values" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:114 +msgid "Closed issue status values" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:123 +msgid "Predefined issue labels" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:125 +msgid "" +"The first \"Type:\" and \"Priority:\" entries found in this list are " +"automatically chosen as defaults for new issues." +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:133 +msgid "Each issue may have at most one label with each of these classes." +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:140 +msgid "Issue relations" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:142 +msgid "" +"You can define bidirectional relations like \"is related to\" or \"blocks, " +"is blocked by\". For standard relations pre-configured translations exist, " +"new relations should however be defined in a language that is understood by " +"all project members." +msgstr "" + +#: IDF/Form/IssueUpdate.php:56 IDF/Form/ReviewFileComment.php:45 +#: IDF/Form/WikiPageUpdate.php:82 IDF/Form/WikiResourceUpdate.php:66 +msgid "Comment" +msgstr "Komentar" + +#: IDF/Form/IssueUpdate.php:316 +msgid "No changes were entered." +msgstr "" + +#: IDF/Form/MembersConf.php:104 +#, php-format +msgid "The following login is invalid: %s." +msgid_plural "The following logins are invalid: %s." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: IDF/Form/Password.php:34 +msgid "Your login or email" +msgstr "" + +#: IDF/Form/Password.php:35 +msgid "Provide either your login or your email to recover your password." +msgstr "" + +#: IDF/Form/Password.php:49 IDF/Form/Password.php:64 +msgid "" +"Sorry, we cannot find a user with this email address or login. Feel free to " +"try again." +msgstr "" + +#: IDF/Form/Password.php:100 +msgid "Password Recovery - InDefero" +msgstr "" + +#: IDF/Form/PasswordInputKey.php:36 IDF/Form/PasswordReset.php:39 +#: IDF/Form/UserChangeEmail.php:36 +msgid "Your verification key" +msgstr "" + +#: IDF/Form/PasswordInputKey.php:50 IDF/Form/PasswordReset.php:89 +msgid "" +"We are sorry but this validation key is not valid. Maybe you should directly " +"copy/paste it from your validation email." +msgstr "" + +#: IDF/Form/PasswordInputKey.php:61 IDF/Form/PasswordReset.php:100 +msgid "" +"Sorry, but this verification key has expired, please restart the password " +"recovery sequence. For security reasons, the verification key is only valid " +"24h." +msgstr "" + +#: IDF/Form/PasswordInputKey.php:76 IDF/Form/PasswordReset.php:108 +#: IDF/Form/RegisterConfirmation.php:137 IDF/Form/RegisterInputKey.php:72 +msgid "Cannot save an invalid form." +msgstr "" + +#: IDF/Form/PasswordReset.php:45 IDF/Form/RegisterConfirmation.php:69 +#: IDF/Form/UserAccount.php:77 +msgid "Your password" +msgstr "Vaše geslo" + +#: IDF/Form/PasswordReset.php:48 IDF/Form/UserAccount.php:80 +msgid "" +"Your password must be hard for other people to find it, but easy for you to " +"remember." +msgstr "" + +#: IDF/Form/PasswordReset.php:56 IDF/Form/RegisterConfirmation.php:80 +#: IDF/Form/UserAccount.php:89 +msgid "Confirm your password" +msgstr "" + +#: IDF/Form/PasswordReset.php:74 IDF/Form/RegisterConfirmation.php:122 +msgid "The two passwords must be the same." +msgstr "" + +#: IDF/Form/PasswordReset.php:77 +msgid "" +"This account is not active. Please contact the forge administrator to " +"activate it." +msgstr "" + +#: IDF/Form/ProjectConf.php:43 +msgid "Short Description" +msgstr "" + +#: IDF/Form/ProjectConf.php:85 +msgid "The \"upload_path\" configuration variable was not set." +msgstr "" + +#: IDF/Form/ProjectConf.php:90 +msgid "Update the logo" +msgstr "" + +#: IDF/Form/ProjectConf.php:92 +msgid "The logo must be a picture with a size of 32 by 32." +msgstr "" + +#: IDF/Form/ProjectConf.php:103 +msgid "Remove the current logo" +msgstr "" + +#: IDF/Form/ProjectConf.php:139 +msgid "Could not determine the size of the uploaded picture." +msgstr "" + +#: IDF/Form/ProjectConf.php:143 +msgid "The picture must have a size of 32 by 32." +msgstr "" + +#: IDF/Form/ProjectConf.php:164 +msgid "The entered URL is invalid. Only http and https URLs are allowed." +msgstr "" + +#: IDF/Form/Register.php:41 +msgid "Your login" +msgstr "" + +#: IDF/Form/Register.php:45 +msgid "" +"The login must be between 3 and 15 characters long and contain only letters " +"and digits." +msgstr "" + +#: IDF/Form/Register.php:53 IDF/Form/UserAccount.php:59 +msgid "Your email" +msgstr "E-naslov" + +#: IDF/Form/Register.php:55 +msgid "We will never send you any unsolicited emails. We hate spam too!" +msgstr "" + +#: IDF/Form/Register.php:60 +msgid "I agree to the terms and conditions." +msgstr "" + +#: IDF/Form/Register.php:88 +msgid "" +"We know, this is boring, but you need to agree with the terms and conditions." +msgstr "" + +#: IDF/Form/Register.php:97 +#, php-format +msgid "" +"The email \"%1$s\" is already used. If you need to, you can recover your password." +msgstr "" + +#: IDF/Form/Register.php:148 +msgid "Confirm the creation of your account." +msgstr "" + +#: IDF/Form/RegisterConfirmation.php:40 IDF/Form/RegisterInputKey.php:36 +msgid "Your confirmation key" +msgstr "" + +#: IDF/Form/RegisterConfirmation.php:72 +msgid "" +"Your password must be hard for other people to guess, but easy for you to " +"remember." +msgstr "" + +#: IDF/Form/RegisterConfirmation.php:99 IDF/Form/RegisterInputKey.php:50 +msgid "" +"We are sorry but this confirmation key is not valid. Maybe you should " +"directly copy/paste it from your confirmation email." +msgstr "" + +#: IDF/Form/RegisterConfirmation.php:110 +#, php-format +msgid "" +"This account has already been confirmed. Maybe should you try to recover your password." +msgstr "" + +#: IDF/Form/ReviewCreate.php:74 +#: IDF/gettexttemplates/idf/source/base.html.php:5 +#: IDF/gettexttemplates/idf/source/changelog.html.php:7 +msgid "Commit" +msgstr "" + +#: IDF/Form/ReviewCreate.php:92 +msgid "Patch" +msgstr "" + +#: IDF/Form/ReviewCreate.php:119 +msgid "We were not able to parse your patch. Please provide a valid patch." +msgstr "" + +#: IDF/Form/ReviewCreate.php:128 +msgid "You provided an invalid commit." +msgstr "" + +#: IDF/Form/ReviewCreate.php:202 +msgid "Initial patch to be reviewed." +msgstr "" + +#: IDF/Form/ReviewFileComment.php:56 +msgid "General comment" +msgstr "" + +#: IDF/Form/ReviewFileComment.php:113 +msgid "" +"You need to provide your general comment about the proposal, or comments on " +"at least one file." +msgstr "" + +#: IDF/Form/ReviewFileComment.php:124 +msgid "The status have been updated." +msgstr "" + +#: IDF/Form/ReviewFileComment.php:130 +msgid "This field is required." +msgstr "" + +#: IDF/Form/SourceConf.php:54 IDF/Form/UploadConf.php:70 +msgid "Webhook URL" +msgstr "" + +#: IDF/Form/TabsConf.php:38 IDF/gettexttemplates/idf/admin/base.html.php:4 +#: IDF/gettexttemplates/idf/base-full.html.php:8 +#: IDF/gettexttemplates/idf/base-full.html~.php:7 +#: IDF/gettexttemplates/idf/base.html.php:8 +#: IDF/gettexttemplates/idf/base.html~.php:7 +#: IDF/gettexttemplates/idf/downloads/base.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:14 +#: IDF/Views/Project.php:97 +msgid "Downloads" +msgstr "Prenosi" + +#: IDF/Form/TabsConf.php:39 IDF/gettexttemplates/idf/base-full.html.php:12 +#: IDF/gettexttemplates/idf/base-full.html~.php:11 +#: IDF/gettexttemplates/idf/base.html.php:12 +#: IDF/gettexttemplates/idf/base.html~.php:11 +msgid "Code Review" +msgstr "Revizije Izvorne kode" + +#: IDF/Form/TabsConf.php:40 IDF/gettexttemplates/idf/admin/base.html.php:5 +#: IDF/gettexttemplates/idf/base-full.html.php:9 +#: IDF/gettexttemplates/idf/base-full.html~.php:8 +#: IDF/gettexttemplates/idf/base.html.php:9 +#: IDF/gettexttemplates/idf/base.html~.php:8 +msgid "Documentation" +msgstr "Dokumentacija" + +#: IDF/Form/TabsConf.php:41 IDF/gettexttemplates/idf/admin/base.html.php:7 +#: IDF/gettexttemplates/idf/base-full.html.php:11 +#: IDF/gettexttemplates/idf/base-full.html~.php:10 +#: IDF/gettexttemplates/idf/base.html.php:11 +#: IDF/gettexttemplates/idf/base.html~.php:10 +msgid "Source" +msgstr "Izvorna koda" + +#: IDF/Form/TabsConf.php:42 IDF/gettexttemplates/idf/base-full.html.php:10 +#: IDF/gettexttemplates/idf/base-full.html~.php:9 +#: IDF/gettexttemplates/idf/base.html.php:10 +#: IDF/gettexttemplates/idf/base.html~.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:17 +msgid "Issues" +msgstr "Napake/Predlogi" + +#: IDF/Form/TabsConf.php:50 +msgid "Open to all" +msgstr "Odprto za vse" + +#: IDF/Form/TabsConf.php:51 +msgid "Signed in users" +msgstr "Prijavljeni uporabniki" + +#: IDF/Form/TabsConf.php:54 +msgid "Closed" +msgstr "Zaprta" + +#: IDF/Form/TabsConf.php:84 +#, fuzzy +msgid "Others" +msgstr "Ostalo" + +#: IDF/Form/TabsConf.php:107 +msgid "Extra authorized users" +msgstr "Ostali odobreni uporabniki" + +#: IDF/Form/Upload.php:59 IDF/Form/WikiResourceCreate.php:65 +#: IDF/Form/WikiResourceUpdate.php:56 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:7 +#: IDF/Views/Download.php:64 IDF/Views/Download.php:346 +msgid "File" +msgstr "Datoteka" + +#: IDF/Form/Upload.php:87 IDF/Form/WikiResourceCreate.php:96 +#: IDF/Form/WikiResourceUpdate.php:83 +msgid "For security reasons, you cannot upload a file with this extension." +msgstr "" + +#: IDF/Form/Upload.php:120 +#, php-format +msgid "You cannot provide more than one label from the %s class to a download." +msgstr "" + +#: IDF/Form/UploadArchive.php:41 +#, fuzzy +msgid "Archive file" +msgstr "Arhiv" + +#: IDF/Form/UploadArchive.php:67 +#, php-format +msgid "" +"For security reasons, you cannot upload a file (%s) with this extension." +msgstr "" + +#: IDF/Form/UploadArchive.php:98 +#, php-format +msgid "" +"You cannot provide more than label from the %1$s class to a download (%2$s)." +msgstr "" + +#: IDF/Form/UploadArchive.php:109 +#, php-format +msgid "" +"A file with the name \"%s\" has already been uploaded and is not marked to " +"be replaced." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:41 +msgid "The archive does not exist." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:48 +#, php-format +msgid "The archive could not be read (code %d)." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:53 +msgid "The archive does not contain a manifest.xml." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:61 +#, php-format +msgid "The archive's manifest is invalid: %s" +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:77 +#, php-format +msgid "The entry %d in the manifest is missing a file name." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:82 +#, php-format +msgid "The entry %d in the manifest is missing a summary." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:86 +msgid "The manifest must not reference itself." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:91 +#, php-format +msgid "The entry %s in the manifest does not exist in the archive." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:96 +#, php-format +msgid "The entry %s in the manifest is referenced more than once." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:108 +#, php-format +msgid "The entry %s in the manifest has more than the six allowed labels set." +msgstr "" + +#: IDF/Form/UploadConf.php:53 +msgid "Predefined download labels" +msgstr "" + +#: IDF/Form/UploadConf.php:62 +msgid "Each download may have at most one label with each of these classes" +msgstr "" + +#: IDF/Form/UserAccount.php:61 +msgid "" +"If you change your email address, an email will be sent to the new address " +"to confirm it." +msgstr "" + +#: IDF/Form/UserAccount.php:80 +msgid "Leave blank if you do not want to change your password." +msgstr "" + +#: IDF/Form/UserAccount.php:166 +msgid "" +"Paste an SSH or monotone public key. Be careful to not provide your private " +"key here!" +msgstr "" + +#: IDF/Form/UserAccount.php:171 +msgid "Add a secondary email address" +msgstr "" + +#: IDF/Form/UserAccount.php:173 +msgid "You will get an email to confirm that you own the address you specify." +msgstr "" + +#: IDF/Form/UserAccount.php:200 +msgid "Confirm your new email address." +msgstr "" + +#: IDF/Form/UserAccount.php:203 +#, php-format +msgid "" +"A validation email has been sent to \"%s\" to validate the email address " +"change." +msgstr "" + +#: IDF/Form/UserAccount.php:341 +msgid "" +"Please check the key as it does not appear to be a valid SSH public key." +msgstr "" + +#: IDF/Form/UserAccount.php:363 +msgid "" +"Please check the key as it does not appear to be a valid monotone public key." +msgstr "" + +#: IDF/Form/UserAccount.php:371 +msgid "Public key looks like neither an SSH nor monotone public key." +msgstr "" + +#: IDF/Form/UserAccount.php:383 +msgid "You already have uploaded this key." +msgstr "" + +#: IDF/Form/UserChangeEmail.php:63 +msgid "" +"The validation key is not valid. Please copy/paste it from your confirmation " +"email." +msgstr "" + +#: IDF/Form/WikiConf.php:49 +msgid "Predefined documentation page labels" +msgstr "" + +#: IDF/Form/WikiConf.php:58 +msgid "" +"Each documentation page may have at most one label with each of these classes" +msgstr "" + +#: IDF/Form/WikiPageCreate.php:38 +msgid "" +"# Introduction\n" +"\n" +"Add your content here.\n" +"\n" +"\n" +"# Details\n" +"\n" +"Add your content here. Format your content with:\n" +"\n" +"* Text in **bold** or *italic*.\n" +"* Headings, paragraphs, and lists.\n" +"* Links to other [[WikiPage]].\n" +msgstr "" + +#: IDF/Form/WikiPageCreate.php:57 +msgid "PageName" +msgstr "" + +#: IDF/Form/WikiPageCreate.php:60 IDF/Form/WikiPageUpdate.php:50 +msgid "Page title" +msgstr "Naslov strani" + +#: IDF/Form/WikiPageCreate.php:66 IDF/Form/WikiPageUpdate.php:56 +msgid "" +"The page name must contains only letters, digits and the dash (-) character." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:71 IDF/Form/WikiPageUpdate.php:61 +msgid "This one line description is displayed in the list of pages." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:108 IDF/Form/WikiPageUpdate.php:119 +#: IDF/Form/WikiResourceCreate.php:78 +msgid "The title contains invalid characters." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:114 IDF/Form/WikiPageUpdate.php:125 +msgid "A page with this title already exists." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:150 IDF/Form/WikiPageUpdate.php:161 +#, php-format +msgid "You cannot provide more than one label from the %s class to a page." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:200 +msgid "Initial page creation" +msgstr "" + +#: IDF/Form/WikiPageDelete.php:39 +msgid "Yes, I understand that the page and all its revisions will be deleted." +msgstr "" + +#: IDF/Form/WikiPageDelete.php:50 IDF/Form/WikiResourceDelete.php:50 +msgid "You need to confirm the deletion." +msgstr "" + +#: IDF/Form/WikiPageUpdate.php:83 IDF/Form/WikiResourceUpdate.php:67 +msgid "One line to describe the changes you made." +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:40 +msgid "ResourceName" +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:44 +msgid "Resource title" +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:50 +msgid "" +"The resource name must contains only letters, digits and the dash (-) " +"character." +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:55 IDF/Form/WikiResourceUpdate.php:47 +msgid "This one line description is displayed in the list of resources." +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:84 +msgid "A resource with this title already exists." +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:142 +msgid "Initial resource creation" +msgstr "" + +#: IDF/Form/WikiResourceDelete.php:39 +msgid "" +"Yes, I understand that the resource and all its revisions will be deleted." +msgstr "" + +#: IDF/Form/WikiResourceUpdate.php:89 +#, php-format +msgid "" +"The mime type of the uploaded file \"%1$s\" does not match the mime type of " +"this resource \"%2$s\"" +msgstr "" + +#: IDF/Form/WikiResourceUpdate.php:97 +msgid "The current version of the resource and the uploaded file are equal." +msgstr "" + +#: IDF/Gconf.php:60 IDF/Search/Occ.php:56 +msgid "model class" +msgstr "" + +#: IDF/Gconf.php:66 IDF/Search/Occ.php:62 +msgid "model id" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/base.html.php:3 +msgid "Project Summary" +msgstr "Splošno o projektu" + +#: IDF/gettexttemplates/idf/admin/base.html.php:6 +msgid "Issue Tracking" +msgstr "Sledenje zadevam" + +#: IDF/gettexttemplates/idf/admin/base.html.php:8 +msgid "Project Members" +msgstr "Osebje Projekta" + +#: IDF/gettexttemplates/idf/admin/base.html.php:9 +msgid "Tabs Access and Notifications" +msgstr "Dostop in obvestila" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:3 +#: IDF/gettexttemplates/idf/admin/issue-tracking.html.php:3 +#: IDF/gettexttemplates/idf/admin/wiki.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/labels.html.php:3 +msgid "" +"\n" +"

Instructions:

\n" +"

List one status value per line in desired sort-order.

\n" +"

Optionally, use an equals-sign to document the meaning of each status " +"value.

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:8 +msgid "" +"

The webhook URL setting specifies an URL to which a HTTP PUT\n" +"request is sent after a new download has been added or to which a HTTP " +"POST\n" +"request is sent after an existing download has been updated.\n" +"If this field is empty, notifications are disabled.

\n" +"\n" +"

Only properly-escaped HTTP URLs are supported, for " +"example:

\n" +"\n" +"
    \n" +"
  • http://domain.com/upload
  • \n" +"
  • http://domain.com/upload?my%20param
  • \n" +"
\n" +"\n" +"

In addition, the URL may contain the following \"%\" notation, which\n" +"will be replaced with specific project values for each download:

\n" +"\n" +"
    \n" +"
  • %p - project name
  • \n" +"
  • %d - download id
  • \n" +"
\n" +"\n" +"

For example, updating download 123 of project 'my-project' with\n" +"web hook URL http://mydomain.com/%p/%d would send a POST " +"request to\n" +"http://mydomain.com/my-project/123.

" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:31 +#: IDF/gettexttemplates/idf/admin/source.html.php:30 +msgid "Web-Hook authentication key:" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:32 +#: IDF/gettexttemplates/idf/admin/issue-tracking.html.php:8 +#: IDF/gettexttemplates/idf/admin/members.html.php:13 +#: IDF/gettexttemplates/idf/admin/source.html.php:31 +#: IDF/gettexttemplates/idf/admin/summary.html.php:11 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:12 +#: IDF/gettexttemplates/idf/admin/wiki.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/forge/index.html.php:13 +#: IDF/gettexttemplates/idf/gadmin/projects/labels.html.php:8 +msgid "Save Changes" +msgstr "Shrani spremembe" + +#: IDF/gettexttemplates/idf/admin/members.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:3 +msgid "" +"\n" +"

Instructions:

\n" +"

Specify each person by its login. Each person must have already " +"registered with the given login.

\n" +"

Separate the logins with commas and/or new lines.

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/members.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:8 +msgid "" +"\n" +"

Notes:

\n" +"

A project owner may make any change to this project, including removing " +"other project owners. You need to be carefull when you give owner rights.\n" +"

A project member will not have access to the administration area but will " +"have more options available in the use of the project.

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:3 +msgid "You can find here the current repository configuration of your project." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:4 +msgid "" +"

The webhook URL setting specifies an URL to which a HTTP \n" +"%%hook_request_method%% request is sent after each " +"repository\n" +"commit. If this field is empty, notifications are disabled.

\n" +"\n" +"

Only properly-escaped HTTP URLs are supported, for " +"example:

\n" +"\n" +"
    \n" +"
  • http://domain.com/commit
  • \n" +"
  • http://domain.com/commit?my%20param
  • \n" +"
\n" +"\n" +"

In addition, the URL may contain the following \"%\" notation, which\n" +"will be replaced with specific project values for each commit:

\n" +"\n" +"
    \n" +"
  • %p - project name
  • \n" +"
  • %r - revision number
  • \n" +"
\n" +"\n" +"

For example, committing revision 123 to project 'my-project' with\n" +"post-commit URL http://mydomain.com/%p/%r would send a request " +"to\n" +"http://mydomain.com/my-project/123.

" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:26 +msgid "" +"The form contains some errors. Please correct them to update the source " +"configuration." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:27 +msgid "Repository type:" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:28 +msgid "Repository access:" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:29 +msgid "Repository size:" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

The description of the project can be improved using the Markdown syntax.

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:7 +msgid "" +"The form contains some errors. Please correct them to update the summary." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:8 +msgid "Current logo" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:9 +#: IDF/gettexttemplates/idf/base-full.html.php:4 +#: IDF/gettexttemplates/idf/base-full.html~.php:4 +#: IDF/gettexttemplates/idf/base.html.php:4 +#: IDF/gettexttemplates/idf/base.html~.php:4 +#: IDF/gettexttemplates/idf/main-menu.html.php:8 +#: IDF/gettexttemplates/idf/project-list.html.php:4 +msgid "Project logo" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:10 +msgid "Your project does not have a logo configured yet." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:3 +msgid "" +"This section allows you to configure project tabs access rights and " +"notifications." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:4 +msgid "" +"Tab access controls whether a single user can navigate into a particular " +"section of your project via the main menu or automatically generated object " +"links." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:5 +msgid "" +"If you mark a project as private, only the project members and " +"administrators, together with the extra authorized users you provide will " +"have access to the project as a whole. You will still be able to define " +"further access rights for the different tabs but the \"Open to all\" and " +"\"Signed in users\" will default to authorized users only." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:6 +msgid "" +"For the extra authorized user list, specify each person by its login. Each " +"person must have already registered with the given login. Separate the " +"logins with commas and/or new lines." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:7 +msgid "" +"Only project members and admins have write access to the source. If you " +"restrict the access to the source, anonymous access is not provided and the " +"users must authenticate themselves with their password or SSH key." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:8 +#, php-format +msgid "" +"Here you can configure who should be notified about changes in a particular " +"section. You can also configure additional addresses, like the one of a " +"mailing list, that should be notified. (Keep in mind that you might have to " +"register the sender address %%from_email%% to let the " +"mailing list actually accept notification emails.) Multiple email addresses " +"must be separated through commas (',')." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:9 +msgid "" +"The form contains some errors. Please correct them to update the access " +"rights." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:10 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:13 +msgid "Access Rights" +msgstr "Pravice dostopa" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:11 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:14 +#, fuzzy +msgid "Notifications" +msgstr "Potrditvena e-pošta" + +#: IDF/gettexttemplates/idf/base-full.html.php:3 +#: IDF/gettexttemplates/idf/base-full.html~.php:3 +#: IDF/gettexttemplates/idf/base.html.php:3 +#: IDF/gettexttemplates/idf/base.html~.php:3 +#, php-format +msgid "" +"Sign in or create your account to create issues or " +"add comments" +msgstr "" + +#: IDF/gettexttemplates/idf/base-full.html.php:6 +#: IDF/gettexttemplates/idf/base.html.php:6 +#: IDF/gettexttemplates/idf/project-list.html.php:6 +msgid "External link to project" +msgstr "" + +#: IDF/gettexttemplates/idf/base-full.html.php:7 +#: IDF/gettexttemplates/idf/base-full.html~.php:6 +#: IDF/gettexttemplates/idf/base.html.php:7 +#: IDF/gettexttemplates/idf/base.html~.php:6 +msgid "Project Home" +msgstr "Projekt" + +#: IDF/gettexttemplates/idf/base-full.html.php:13 +#: IDF/gettexttemplates/idf/base-full.html~.php:12 +#: IDF/gettexttemplates/idf/base.html.php:13 +#: IDF/gettexttemplates/idf/base.html~.php:12 +msgid "Project Management" +msgstr "Upravljanje Projekta" + +#: IDF/gettexttemplates/idf/downloads/base.html.php:4 +#: IDF/gettexttemplates/idf/downloads/index.html.php:4 +#: IDF/Views/Download.php:235 +msgid "New Download" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/base.html.php:5 +#, fuzzy +msgid "Upload Archive" +msgstr "Arhiv" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:3 +msgid "" +"Each file must have a distinct name and file contents\n" +"cannot be changed, so be sure to include release numbers in each file\n" +"name." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:6 +#, php-format +msgid "" +"You can use the Markdown syntax for the description." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:7 +msgid "The form contains some errors. Please correct them to submit the file." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:8 +msgid "Submit File" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:9 +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:8 +#: IDF/gettexttemplates/idf/downloads/delete.html.php:7 +#: IDF/gettexttemplates/idf/downloads/view.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:21 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:14 +#: IDF/gettexttemplates/idf/issues/create.html.php:14 +#: IDF/gettexttemplates/idf/issues/view.html.php:27 +#: IDF/gettexttemplates/idf/register/confirmation.html.php:7 +#: IDF/gettexttemplates/idf/register/index.html.php:8 +#: IDF/gettexttemplates/idf/register/inputkey.html.php:5 +#: IDF/gettexttemplates/idf/review/create.html.php:12 +#: IDF/gettexttemplates/idf/review/view.html.php:41 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:5 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:13 +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:7 +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:9 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:5 +msgid "Cancel" +msgstr "Prekliči" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:10 +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:9 +#: IDF/gettexttemplates/idf/register/inputkey.html.php:6 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:6 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:6 +msgid "Instructions" +msgstr "Navodila" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:3 +msgid "" +"The archive must include a manifest.xml file with meta " +"information about the\n" +"files to process inside the archive. All processed files must be unique or " +"replace existing files explicitely." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:5 +#, php-format +msgid "" +"You can learn more about the archive format here." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:6 +msgid "" +"The form contains some errors. Please correct them to submit the archive." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:7 +#, fuzzy +msgid "Submit Archive" +msgstr "Arhiv" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:3 +msgid "" +"Attention! If you want to delete a specific version of your " +"software, maybe, someone is depending on this specific version to run his " +"systems. Are you sure, you will not affect anybody when removing this file?" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:4 +#, php-format +msgid "" +"Instead of deleting the file, you could mark it as " +"deprecated." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:5 +#: IDF/gettexttemplates/idf/downloads/view.html.php:4 +#: IDF/gettexttemplates/idf/issues/attachment.html.php:4 +#: IDF/gettexttemplates/idf/issues/view.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:5 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:7 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:7 +#, php-format +msgid "by %%submitter%%" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:6 +msgid "Delete File" +msgstr "Izbriši datoteko" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:8 +#: IDF/gettexttemplates/idf/downloads/view.html.php:14 +msgid "Uploaded:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:9 +#: IDF/gettexttemplates/idf/downloads/view.html.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:29 +#: IDF/gettexttemplates/idf/review/view.html.php:27 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:12 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:14 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:14 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:15 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:17 +msgid "Updated:" +msgstr "Zadnjič osveženo:" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:10 +#: IDF/gettexttemplates/idf/downloads/view.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:6 +#: IDF/gettexttemplates/idf/listProjects.html.php:17 +msgid "Downloads:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:11 +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:7 +#: IDF/gettexttemplates/idf/downloads/view.html.php:17 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:6 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:6 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:11 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:16 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:10 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:21 +#: IDF/gettexttemplates/idf/issues/view.html.php:33 +#: IDF/gettexttemplates/idf/project-list.html.php:8 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:6 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:13 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:16 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:12 +#: IDF/IssueComment.php:157 IDF/Wiki/PageRevision.php:204 +msgid "Labels:" +msgstr "Oznake:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:3 +msgid "A new file is available for download:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:4 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:6 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:5 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:8 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:4 +msgid "Hello," +msgstr "Živjo," + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:6 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:5 +msgid "Project:" +msgstr "Projekt:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:6 +msgid "Submitted by:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:8 +msgid "Download:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/view.html.php:31 +#: IDF/gettexttemplates/idf/user/public.html.php:4 +msgid "Description:" +msgstr "Opis:" + +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:3 +msgid "A file download was updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/feedfragment.xml.php:3 +msgid "Details" +msgstr "Podrobnosti" + +#: IDF/gettexttemplates/idf/downloads/index.html.php:3 +#, php-format +msgid "See the deprecated files." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/index.html.php:5 +msgid "Number of files:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:3 +msgid "" +"Attention! This file is marked as deprecated, download it " +"only if you are sure you need this specific version." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:5 +msgid "md5:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:6 +msgid "Changes" +msgstr "Spremembe" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:7 +msgid "The form contains some errors. Please correct them to update the file." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:8 +msgid "Update File" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:10 +#: IDF/gettexttemplates/idf/downloads/view.html.php:12 +msgid "Remove this file" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:11 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:18 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:7 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:12 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:12 +msgid "Trash" +msgstr "Smeti" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:13 +msgid "Delete this file" +msgstr "" + +#: IDF/gettexttemplates/idf/faq-api.html.php:3 +#: IDF/gettexttemplates/idf/faq-archive-format.html.php:3 +#: IDF/gettexttemplates/idf/faq.html.php:65 +msgid "Here we are, just to help you." +msgstr "" + +#: IDF/gettexttemplates/idf/faq-api.html.php:4 +#: IDF/gettexttemplates/idf/faq-archive-format.html.php:4 +#: IDF/gettexttemplates/idf/faq.html.php:66 +#: IDF/gettexttemplates/idf/gadmin/base.html.php:4 +#: IDF/gettexttemplates/idf/index.html.php:4 IDF/Views/Admin.php:77 +#: IDF/Views.php:91 +msgid "Projects" +msgstr "Projekti" + +#: IDF/gettexttemplates/idf/faq.html.php:3 +msgid "" +"

This is simple:

\n" +"
    \n" +"
  1. Write in the comments \"This is a duplicate of issue 123\" or - if you " +"are a member of the crew -\n" +"directly add the \"duplicates\" relation with the value \"123\" below the " +"comment field. Change \"123\"\n" +"with the corresponding issue number.
  2. \n" +"
  3. Change the status of the current issue to Duplicate.
  4. \n" +"
  5. Submit the changes.
  6. \n" +"
" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:11 +msgid "" +"You need to create an account on Gravatar, this takes about 5 minutes and is free." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:12 +msgid "" +"\n" +"

To embed any previously uploaded resource into your wiki page, you can " +"use the [[!ResourceName]] syntax.

\n" +"\n" +"

The rendering of the resource can then be further fine-tuned:\n" +"

    \n" +"
  • [[!ImageResource, align=right, width=200]] renders " +"\"ImageResource\" right-aligned and scale its width to 200
  • \n" +"
  • [[!TextResource, align=center, width=300, height=300]] " +"renders \"TextResource\" in a centered, 300 by 300 px iframe
  • \n" +"
  • [[!AnyResource, preview=no]] does not render a preview of " +"the resource, but only provides a download link (default for binary " +"resources)
  • \n" +"
  • [[!BinaryResource, title=Download]] renders the download " +"link of \"BinaryResource\" with an alternative title
  • \n" +"
\n" +"

\n" +"\n" +"Resources are versioned, just like wiki pages. If you update a resource, old " +"wiki pages still show the state of the resource\n" +"at the time when the wiki page was edited. If you specifically want to " +"update a resource on a page, you therefor need to update\n" +"the resource at first and then also the page where it is referenced, " +"otherwise the change won't be visible until the next regular edit. \n" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:28 +msgid "" +"

If you have to publish many files at once for a new release, it is a very " +"tedious task\n" +"to upload them one after another and enter meta information like a summary, " +"a description or additional\n" +"labels for each of them.

\n" +"

InDefero therefore supports a special archive format that is basically a " +"standard zip file which comes with\n" +"some meta information. These meta information are kept in a special manifest " +"file, which is distinctly kept from\n" +"the rest of the files in the archive that should be published.

\n" +"

Once this archive has been uploaded, InDefero reads in the meta " +"information, unpacks the other files from\n" +"the archive and creates new individual downloads for each of them.

" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:36 +#, php-format +msgid "Learn more about the archive format." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:37 +msgid "" +"The API (Application Programming Interface) is used to interact with " +"InDefero with another program. For example, this can be used to create a " +"desktop program to submit new tickets easily." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:38 +#, php-format +msgid "Learn more about the API." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:39 +#: IDF/gettexttemplates/idf/faq.html.php:45 +msgid "What are the keyboard shortcuts?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:40 +#: IDF/gettexttemplates/idf/faq.html.php:60 +msgid "How to mark an issue as duplicate?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:41 +#: IDF/gettexttemplates/idf/faq.html.php:61 +msgid "How can I display my head next to my comments?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:42 +#: IDF/gettexttemplates/idf/faq.html.php:62 +msgid "How can I embed images and other resources in my documentation pages?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:43 +#: IDF/gettexttemplates/idf/faq.html.php:63 +msgid "What is this \"Upload Archive\" functionality about?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:44 +#: IDF/gettexttemplates/idf/faq.html.php:64 +msgid "What is the API and how is it used?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:46 +msgid "Shift+h: This help page." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:47 +msgid "If you are in a project, you have the following shortcuts:" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:48 +msgid "Shift+u: Project updates." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:49 +msgid "Shift+d: Downloads." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:50 +msgid "Shift+o: Documentation." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:51 +msgid "Shift+a: Create a new issue." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:52 +msgid "Shift+i: List of open issues." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:53 +msgid "Shift+m: The issues you submitted." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:54 +msgid "Shift+w: The issues assigned to you." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:55 +msgid "Shift+s: Source." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:56 +msgid "You also have the standard access keys:" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:57 +msgid "Alt+1: Home." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:58 +msgid "Alt+2: Skip the menus." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:59 +msgid "Alt+4: Search (when available)." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:3 +msgid "Forge" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:5 +msgid "People" +msgstr "Ljudje" + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:6 +msgid "Usher" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/forge/base.html.php:3 +#, fuzzy +msgid "Frontpage" +msgstr "stran" + +#: IDF/gettexttemplates/idf/gadmin/forge/index.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

You can set up a custom forge page that is used as entry page for the " +"forge instead of the plain project listing. This page is then also " +"accessible via the 'Home' link in main menu bar.

\n" +"

The content of the page can use the Markdown syntax with the Extra extension.

\n" +"

Additionally, the following macros are available:
\n" +"

    \n" +"
  • {projectlist, label=..., order=(name|activity), limit=...} - Renders a project list that can optionally be filtered by label, " +"ordered by 'name' or 'activity' and / or limited to a specific number of " +"projects.
  • \n" +"
\n" +"

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:3 +#: IDF/gettexttemplates/idf/main-menu.html.php:7 +msgid "Project List" +msgstr "Seznam projektov" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:4 +#: IDF/Views/Admin.php:110 +#, fuzzy +msgid "Project Labels" +msgstr "Seznam projektov" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:16 +#: IDF/gettexttemplates/idf/listProjects.html.php:6 IDF/Views/Admin.php:186 +msgid "Create Project" +msgstr "Ustvari nov projekt" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:6 +msgid "Change Project Details" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:3 +msgid "" +"You can select the type of repository you want. In the case of subversion, " +"you can use optionally a remote repository instead of the local one." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:4 +msgid "" +"Once you have defined the repository type, you cannot change it." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:5 +msgid "" +"\n" +"

Specify each person by its login. Each person must have already " +"registered with the given login.

\n" +"

Separate the logins with commas and/or new lines.

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:14 +msgid "" +"The form contains some errors. Please correct them to create the project." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:15 +msgid "Provide at least one owner for the project or use a template." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:15 +msgid "Instructions:" +msgstr "Navodila:" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:3 +#, php-format +msgid "" +"Confirmation code to confirm the deletion of the project: \n" +"%%code%%." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:5 +msgid "" +"\n" +"Attention! Deleting a project is a one second operation\n" +"with the consequences that all the data related to the \n" +"project will be deleted.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:10 +msgid "" +"The form contains some errors. Please correct them to delete the project." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:11 +msgid "Project Statistics" +msgstr "Statistika Projekta" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:12 +msgid "Tab" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:13 +msgid "Number" +msgstr "Številka" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:15 +msgid "Code reviews" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:16 +#: IDF/Views/Project.php:93 +msgid "Commits" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:18 +msgid "Documentation pages" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:19 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:20 +msgid "Delete Project" +msgstr "Izbriši projekt" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:22 +msgid "" +"For large projects, the suppression can take a while, please be patient." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:3 +msgid "Space Usage Statistics" +msgstr "Statistika porabe prostora" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:4 +msgid "Repositories:" +msgstr "Repozitoriji:" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:5 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:11 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:18 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:16 +msgid "Attachments:" +msgstr "Priponke:" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:7 +msgid "Database:" +msgstr "Zbirka podatkov:" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:8 +msgid "Total Forge:" +msgstr "Skupaj razvoj:" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:13 +msgid "" +"The form contains some errors. Please correct them to update the project." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:14 +msgid "Provide at least one owner for the project." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:15 +msgid "Update Project" +msgstr "Uredi projekt" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:19 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:20 +msgid "Delete this project" +msgstr "Izbriši ta projekt" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:21 +msgid "You will be asked to confirm." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:3 +#: IDF/Views/Admin.php:264 +msgid "User List" +msgstr "Seznam uporabnikov" + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:13 +msgid "Update User" +msgstr "Osveži uporabnika" + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:4 +msgid "Create User" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:3 +msgid "The form contains some errors. Please correct them to create the user." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:6 +msgid "The user password will be sent by email to the user." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/createuser-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"An account on the forge has been created for you by\n" +"the administrator %%admin%%.\n" +"\n" +"Please find here your details to access the forge:\n" +"\n" +" Address: %%url%%\n" +" Login: %%user.login%%\n" +" Password: %%password%%\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:3 +#, php-format +msgid "See not validated users." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:4 +msgid "

You have here an overview of the users registered in the forge.

" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:5 +msgid "Number of users:" +msgstr "Število uporabnikov:" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:3 +msgid "" +"If you are changing the email address of the user, you\n" +"need to ensure that you are providing a valid email\n" +"address" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:6 +msgid "" +"If you give the user staff rights, the user will be\n" +"able to create new projects and update other non staff users.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:9 +msgid "The form contains some errors. Please correct them to update the user." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:10 +#: IDF/gettexttemplates/idf/register/confirmation.html.php:4 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:4 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:4 +msgid "Login:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:11 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:5 +msgid "Public Profile" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:12 +msgid "Administrative" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/base.html.php:3 +msgid "Configured servers" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/base.html.php:4 +#: IDF/Views/Admin.php:421 +msgid "Usher control" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html~.php:3 +msgid "address" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html~.php:4 +msgid "port" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:5 +msgid "No connections found." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:3 +msgid "current server status:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:4 +msgid "startup" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:5 +msgid "shutdown" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:6 +msgid "reload server configuration:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:7 +msgid "reload" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:11 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:11 +msgid "Status explanation" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:9 +msgid "active with n total open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:10 +msgid "waiting for new connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:11 +msgid "usher is being shut down, not accepting connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:12 +msgid "" +"usher is shut down, all local servers are stopped and not accepting " +"connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:3 +msgid "server name" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:4 IDF/Issue.php:99 +#: IDF/Review.php:102 +msgid "status" +msgstr "stanje" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:5 +msgid "action" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:6 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:6 +msgid "No monotone servers configured." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:7 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:7 +msgid "stop" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:8 +msgid "start" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:9 +msgid "kill" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:10 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:10 +msgid "active connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:12 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:12 +msgid "remote server without open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:13 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:13 +msgid "server with n open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:14 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:14 +msgid "local server running, without open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:15 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:15 +msgid "local server not running, waiting for connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:16 +msgid "local server is about to stop, n connections still open" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:17 +msgid "local server not running, not accepting connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:18 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:18 +msgid "usher is shut down, not running and not accepting connections" +msgstr "" + +#: IDF/gettexttemplates/idf/index.atom.php:3 +#, php-format +msgid "Personal project feed for %%user%%." +msgstr "" + +#: IDF/gettexttemplates/idf/index.html.php:3 +#: IDF/gettexttemplates/idf/main-menu.html.php:6 +msgid "Home" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:3 +#, php-format +msgid "Attachment to issue %%issue.id%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:5 +#: IDF/gettexttemplates/idf/review/view.html.php:35 +#: IDF/gettexttemplates/idf/source/commit.html.php:23 +#: IDF/gettexttemplates/idf/source/commit.html~.php:22 +#: IDF/gettexttemplates/idf/source/git/file.html.php:6 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:7 +msgid "Archive" +msgstr "Arhiv" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:6 +#: IDF/gettexttemplates/idf/source/git/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:12 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:12 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:10 +msgid "Download this file" +msgstr "Prenesi to datoteko" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:7 +#: IDF/gettexttemplates/idf/issues/view.html.php:28 +#: IDF/gettexttemplates/idf/review/view.html.php:26 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:13 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:14 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:16 +msgid "Created:" +msgstr "Ustvarjeno:" + +#: IDF/gettexttemplates/idf/issues/base.html.php:4 +msgid "All Issues" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/base.html.php:5 +msgid "My Issues" +msgstr "Moje zadeve" + +#: IDF/gettexttemplates/idf/issues/base.html.php:6 +msgid "My watch list" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/base.html.php:7 +#: IDF/gettexttemplates/idf/issues/by-label.html.php:6 +#: IDF/gettexttemplates/idf/issues/index.html.php:5 +#: IDF/gettexttemplates/idf/issues/project-watchlist.html.php:5 +#: IDF/gettexttemplates/idf/issues/search.html.php:8 +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:5 +msgid "New Issue" +msgstr "Nova zadeva" + +#: IDF/gettexttemplates/idf/issues/base.html.php:8 +#: IDF/gettexttemplates/idf/wiki/base.html.php:9 +msgid "Search" +msgstr "Iskanje" + +#: IDF/gettexttemplates/idf/issues/base.html.php:9 +msgid "Back to the issue" +msgstr "Nazaj na zadevo" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:3 +#, php-format +msgid "" +"

Open issues: %%open%%

\n" +"

Closed issues: %%closed%%

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:7 +msgid "Label:" +msgstr "Oznaka:" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:8 +msgid "Completion:" +msgstr "Ocena končanosti:" + +#: IDF/gettexttemplates/idf/issues/create.html.php:3 +msgid "" +"

When you submit the issue do not forget to provide the following " +"information:

\n" +"
    \n" +"
  • The steps to reproduce the problem.
  • \n" +"
  • The version of the software and your operating system.
  • \n" +"
  • Any information that can help the developers to solve the issue.
  • \n" +"
  • Do not provide any password or confidential information!
  • \n" +"
" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/create.html.php:10 +msgid "The form contains some errors. Please correct them to submit the issue." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/create.html.php:11 +#: IDF/gettexttemplates/idf/issues/create.html.php:13 +#: IDF/gettexttemplates/idf/issues/view.html.php:24 +#: IDF/gettexttemplates/idf/issues/view.html.php:26 +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:5 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:5 +msgid "Preview" +msgstr "Predogled" + +#: IDF/gettexttemplates/idf/issues/create.html.php:12 +msgid "Submit Issue" +msgstr "Objavi zadevo" + +#: IDF/gettexttemplates/idf/issues/create.html.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:34 +msgid "Attach file" +msgstr "Dodaj datoteko ..." + +#: IDF/gettexttemplates/idf/issues/create.html.php:16 +#: IDF/gettexttemplates/idf/issues/create.html.php:17 +#: IDF/gettexttemplates/idf/issues/view.html.php:35 +#: IDF/gettexttemplates/idf/issues/view.html.php:36 +msgid "Attach another file" +msgstr "Naloži novo datoteke" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:3 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:3 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:13 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:12 +#: IDF/gettexttemplates/idf/issues/view.html.php:18 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:3 +#: IDF/gettexttemplates/idf/review/view.html.php:38 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:11 +#: IDF/IssueComment.php:151 +msgid "Summary:" +msgstr "Povzetek:" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:4 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:4 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:8 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:14 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:13 +#: IDF/gettexttemplates/idf/issues/view.html.php:19 +#: IDF/gettexttemplates/idf/issues/view.html.php:30 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:4 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/view.html.php:39 IDF/IssueComment.php:153 +msgid "Status:" +msgstr "Stanje:" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:5 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:15 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:14 +#: IDF/gettexttemplates/idf/issues/view.html.php:20 +#: IDF/gettexttemplates/idf/issues/view.html.php:31 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:5 +#: IDF/IssueComment.php:155 +msgid "Owner:" +msgstr "Lastnik:" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:17 +#: IDF/gettexttemplates/idf/issues/view.html.php:22 IDF/IssueComment.php:159 +msgid "Relations:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/forge-watchlist.html.php:3 +#: IDF/gettexttemplates/idf/issues/index.html.php:3 +#: IDF/gettexttemplates/idf/issues/project-watchlist.html.php:3 +#, php-format +msgid "" +"

Open issues: %%open%%

\n" +"

Closed issues: %%closed%%

" +msgstr "" +"

Odprtih zadev: %%open%%\n" +"

Zaprtih zadev: %%closed%%

" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:3 +msgid "A new issue has been created and assigned to you:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:4 +msgid "A new issue has been created:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:8 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:11 +msgid "Reported by:" +msgstr "Sporočil:" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:12 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:19 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:17 +msgid "Issue:" +msgstr "Zadeve:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:3 +msgid "The following issue you are owning has been updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:4 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:3 +msgid "The following issue has been updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:4 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:4 +#, php-format +msgid "By %%who%%, %%c.creation_dtime%%:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:10 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:9 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:12 +msgid "URL:" +msgstr "URL:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:12 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:11 +msgid "Comments (last first):" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/search.html.php:3 +#, php-format +msgid "" +"\n" +"

Found open issues: %%open%%

\n" +"

Found closed issues: %%closed" +"%%

" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/search.html.php:6 +#, php-format +msgid "" +"

Label:\n" +"%%tag.class%%:" +"%%tag.name%%

" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:3 +msgid "View all open issues." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:4 +#, fuzzy +msgid "Create an issue." +msgstr "Nova stran" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:5 +#, php-format +msgid "" +"The issue tracker is empty.
Create your " +"first issue." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:6 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:4 +#, php-format +msgid "Unresolved: By %%key%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:7 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:5 +msgid "Status Summary" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:8 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:6 +msgid "Unresolved: By Assignee" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html~.php:3 +#, php-format +msgid "" +"The issue tracker is empty.
You can create your first issue here." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:3 +#, php-format +msgid "" +"See the %%nb_submit_closed%% closed." +msgid_plural "" +"See the %%nb_submit_closed%% closed." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:4 +#, php-format +msgid "" +"See the %%nb_owner_closed%% closed." +msgid_plural "" +"See the %%nb_owner_closed%% closed." +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:6 +#: IDF/gettexttemplates/idf/user/dashboard.html.php:7 +msgid "Submitted issues:" +msgstr "Poslanih zadev:" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:7 +#: IDF/gettexttemplates/idf/user/dashboard.html.php:6 +msgid "Working issues:" +msgstr "Zadeve v nastajanju:" + +#: IDF/gettexttemplates/idf/issues/view.html.php:3 +#, php-format +msgid "Reported by %%submitter%%, %%c.creation_dtime%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:4 +#: IDF/gettexttemplates/idf/review/view.html.php:22 +#, php-format +msgid "" +"Comment %%i%% by %%submitter%%, %%c.creation_dtime%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:5 +#, php-format +msgid "Sign in to reply to this comment." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:6 +msgid "" +"This issue is marked as closed, add a comment only if you think this issue " +"is still valid and more work is needed to fully fix it." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:8 +#, php-format +msgid "%%interested%% person" +msgid_plural "%%interested%% persons" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:9 +#, php-format +msgid "This issue %%verb%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:10 +msgid "Remove this issue from your watch list" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:11 +msgid "Add this issue to your watch list" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:12 +msgid "View the previous closed issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:13 +msgid "View the previous open issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:14 +msgid "View the next closed issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:15 +msgid "View the next open issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:16 +msgid "download" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:17 +msgid "view" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:23 +msgid "The form contains some errors. Please correct them to change the issue." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:25 +msgid "Submit Changes" +msgstr "Shrani spremembe" + +#: IDF/gettexttemplates/idf/issues/view.html.php:32 +msgid "Followed by:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:3 +#, fuzzy, php-format +msgid "1 project" +msgid_plural "%%label.project_count%% projects" +msgstr[0] "projekt" +msgstr[1] "projekt" +msgstr[2] "projekt" +msgstr[3] "projekt" + +#: IDF/gettexttemplates/idf/listProjects.html.php:4 +#, php-format +msgid "Remove filter for %%tag%%" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:5 +msgid "No projects managed with InDefero were found." +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:7 +msgid "Filter projects by label" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:8 +#, fuzzy +msgid "No projects with labels found." +msgstr "Nisem našel strani." + +#: IDF/gettexttemplates/idf/listProjects.html.php:9 +msgid "Order" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:10 +#, fuzzy +msgid "By name" +msgstr "ime" + +#: IDF/gettexttemplates/idf/listProjects.html.php:11 +msgid "By activity" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:12 +msgid "Filtered project stats" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:13 +msgid "Members:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:14 +msgid "Issues:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:15 +msgid "Commits:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:16 +msgid "Documentations:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:18 +msgid "Code reviews:" +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:3 +#, php-format +msgid "" +"You can create an account if you don't have one yet." +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:4 +msgid "What is your account information?" +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:5 +msgid "My login is" +msgstr "Sem uporabnik" + +#: IDF/gettexttemplates/idf/login_form.html.php:6 +msgid "My password is" +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:7 +msgid "Sign in" +msgstr "Prijavi se" + +#: IDF/gettexttemplates/idf/login_form.html.php:8 +msgid "I lost my password!" +msgstr "Pozabil sem geslo!" + +#: IDF/gettexttemplates/idf/login_form.html.php:9 +msgid "Welcome." +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:10 +msgid "It takes less than a minute to create your account." +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:3 +#, php-format +msgid "" +"Welcome, %%user%%." +msgstr "" +"Dobrodošel, %%user%%." + +#: IDF/gettexttemplates/idf/main-menu.html.php:4 +msgid "Sign Out" +msgstr "Odjava" + +#: IDF/gettexttemplates/idf/main-menu.html.php:5 +msgid "Sign in or create your account" +msgstr "Prijavi se ali pa ustvari uporabniški račun" + +#: IDF/gettexttemplates/idf/main-menu.html.php:10 IDF/Views/Admin.php:40 +msgid "Forge Management" +msgstr "Nastavitve spletišča" + +#: IDF/gettexttemplates/idf/main-menu.html.php:11 +msgid "Help and accessibility features" +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:12 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:14 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:14 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:15 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:13 +msgid "Help" +msgstr "Pomoč" + +#: IDF/gettexttemplates/idf/project/home.html.php:3 +#: IDF/gettexttemplates/idf/project/timeline.html.php:4 IDF/Views.php:46 +msgid "Welcome" +msgstr "Dobrodošel" + +#: IDF/gettexttemplates/idf/project/home.html.php:4 +#: IDF/gettexttemplates/idf/project/timeline.html.php:5 +msgid "Latest Updates" +msgstr "Zadnje spremembe" + +#: IDF/gettexttemplates/idf/project/home.html.php:5 +msgid "Featured Downloads" +msgstr "Pomembni prenosi" + +#: IDF/gettexttemplates/idf/project/home.html.php:6 +#, fuzzy +msgid "Show more featured downloads" +msgstr "Pomembni prenosi" + +#: IDF/gettexttemplates/idf/project/home.html.php:7 +#: IDF/gettexttemplates/idf/project/home.html.php:10 +msgid "show more..." +msgstr "Prikaži ostalo.." + +#: IDF/gettexttemplates/idf/project/home.html.php:8 +msgid "Featured Documentation" +msgstr "Pomembna Dokumnetacija" + +#: IDF/gettexttemplates/idf/project/home.html.php:9 +#, fuzzy +msgid "Show more featured documentation" +msgstr "Pomembna Dokumnetacija" + +#: IDF/gettexttemplates/idf/project/home.html.php:11 +msgid "Development Team" +msgstr "Razvojna skupina" + +#: IDF/gettexttemplates/idf/project/home.html.php:12 +msgid "Admins" +msgstr "Administratorji" + +#: IDF/gettexttemplates/idf/project/home.html.php:13 +msgid "Happy Crew" +msgstr "Ostali člani" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:3 +msgid "Latest updates" +msgstr "Zadnje spremembe" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:6 +#: IDF/Views/Project.php:90 +msgid "All Updates" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:7 +msgid "Filter by type" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:8 +msgid "Subscribe to this timeline" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:9 +msgid "RSS" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:10 +msgid "Atom feed" +msgstr "" + +#: IDF/gettexttemplates/idf/project-list.html.php:3 +msgid "Project activity: %%activity%%%" +msgstr "" + +#: IDF/gettexttemplates/idf/project-list.html.php:9 +msgid "n/a" +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation-email.txt.php:3 +#, php-format +msgid "" +"Hello,\n" +"\n" +"You have requested the creation of an account to\n" +"participate in the life of a software project.\n" +"\n" +"To confirm the account please follow this link:\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following confirmation key:\n" +"\n" +"%%key%%\n" +"\n" +"If you are not interested any longer in taking\n" +"part in the life of the software project or if\n" +"you can't remember having requested the creation\n" +"of an account, please excuse us and simply ignore\n" +"this email. \n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:3 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:3 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:3 +msgid "Oops, please check the form for errors." +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:5 +msgid "Email:" +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:6 +msgid "Enable Your Account" +msgstr "Omogoči Račun" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:8 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:8 +msgid "" +"This is the last step, but just be sure to have the cookies enabled to log in afterwards." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:3 +msgid "" +"Read the terms and conditions – " +"basically \"Please be nice, we respect you\"." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:4 +#, php-format +msgid "" +"If you have just forgotten your login information, then there is no need to " +"create a new account. You can just recover your login " +"name and password." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:5 +#, php-format +msgid "" +"With your account, you will able to participate in the life of all the " +"projects hosted here. Participating in a software project must be fun, so if " +"you have troubles, you can let us know about your issues " +"at anytime!" +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:6 +msgid "Oops, please check the provided login and email address to register." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:7 IDF/Views.php:137 +msgid "Create Your Account" +msgstr "Ustvari Uporabniški Račun" + +#: IDF/gettexttemplates/idf/register/index.html.php:9 +msgid "" +"Be sure to provide a valid email address, as we are sending a validation " +"link by email." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:10 +msgid "Did you know?" +msgstr "Ali ste vedeli, da ..." + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:3 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:3 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:3 +msgid "Oops, we found an error in the form." +msgstr "" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:4 +msgid "Confirm Your Account" +msgstr "Potrdi Račun" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:7 +msgid "" +"Use your email software to read your emails and open your confirmation " +"email. Either click directly on the confirmation link or copy/paste the " +"confirmation key in the box and submit the form." +msgstr "" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:8 +msgid "" +"Just after providing the confirmation key, you will be able to set your " +"password and start using this website fully." +msgstr "" + +#: IDF/gettexttemplates/idf/review/base-full.html.php:3 +#: IDF/gettexttemplates/idf/review/base.html.php:3 +msgid "Open Reviews" +msgstr "" + +#: IDF/gettexttemplates/idf/review/base.html.php:4 +#: IDF/gettexttemplates/idf/review/create.html.php:11 +#: IDF/gettexttemplates/idf/review/index.html.php:3 IDF/Views/Review.php:83 +msgid "Start Code Review" +msgstr "" + +#: IDF/gettexttemplates/idf/review/create.html.php:3 +msgid "" +"

To start a code review, you need to provide:

\n" +"
    \n" +"
  • A commit or revision of the current code in the repository from which " +"you started your work.
  • \n" +"
  • A patch describing your changes with respect to the reference commit.\n" +"
  • Check your patch does not provide any password or confidential " +"information!
  • \n" +"
" +msgstr "" + +#: IDF/gettexttemplates/idf/review/create.html.php:9 +msgid "" +"The form contains some errors. Please correct them to submit the code review." +msgstr "" + +#: IDF/gettexttemplates/idf/review/create.html.php:10 +msgid "" +"Select the commit against which you created your patch to be sure it applies " +"correctly." +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:3 +msgid "The following review has been created:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:16 +msgid "Review:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:3 +msgid "The following review has been updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:5 +#, php-format +msgid "" +"By %%who%%, %%c.creation_dtime%%, on file:\n" +"%%c.cfile%%\n" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:14 +msgid "General comments (last first):" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:15 +msgid "Detailed file comments (last first):" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:3 +msgid "" +"Code review is a process in which\n" +"after or before changes are commited into the code repository,\n" +"different people discuss the code changes. The goal is\n" +"to improve the quality of the code and the\n" +"contributions, as such, you must be pragmatic when writing\n" +"your review. Correctly mention the line numbers (in the old or in the\n" +"new file) and try to keep a good balance between seriousness and fun.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:11 +msgid "" +"\n" +"Proposing code for review is intimidating, you know\n" +"you will receive critics, so please, as a reviewer, keep this\n" +"process fun, use it to help your contributor learn your\n" +"coding standards and the structure of the code and make them want\n" +"to propose more contributions.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:18 +#: IDF/gettexttemplates/idf/source/commit.html.php:3 +#: IDF/gettexttemplates/idf/source/commit.html~.php:3 +#, php-format +msgid "%%ndiff%% diff" +msgid_plural "%%ndiff%% diffs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: IDF/gettexttemplates/idf/review/view.html.php:19 +#, php-format +msgid "%%nc%% comment" +msgid_plural "%%nc%% comments" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: IDF/gettexttemplates/idf/review/view.html.php:20 +#, php-format +msgid "" +"Comment %%i%% by %%who%%, " +"%%c.creation_dtime%%" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:21 +#, php-format +msgid "Your comments on the changes in file %%file%%:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:23 +#, php-format +msgid "Sign in to participate in the review." +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:24 +msgid "" +"The form contains some errors. Please correct them to submit your review." +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:25 +msgid "How to Participate in a Code Review" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:28 +#: IDF/gettexttemplates/idf/source/commit.html.php:5 +#: IDF/gettexttemplates/idf/source/commit.html~.php:5 +msgid "Author:" +msgstr "Avtor:" + +#: IDF/gettexttemplates/idf/review/view.html.php:29 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/source/commit.html.php:7 +#: IDF/gettexttemplates/idf/source/commit.html~.php:7 +msgid "Commit:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:30 +#: IDF/gettexttemplates/idf/source/commit.html.php:8 +#: IDF/gettexttemplates/idf/source/commit.html~.php:8 +msgid "View corresponding source tree" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:32 +msgid "Reviewers:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:33 +msgid "No reviewers at the moment." +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:34 +msgid "Files:" +msgstr "Datoteke:" + +#: IDF/gettexttemplates/idf/review/view.html.php:36 +#: IDF/gettexttemplates/idf/source/commit.html.php:24 +#: IDF/gettexttemplates/idf/source/commit.html~.php:23 +msgid "Download the corresponding diff file" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:37 +msgid "General Comments" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:40 +msgid "Submit Code Review" +msgstr "" + +#: IDF/gettexttemplates/idf/source/base.html.php:3 +msgid "Source Tree" +msgstr "Drevo izvorne kode" + +#: IDF/gettexttemplates/idf/source/base.html.php:4 +msgid "Change Log" +msgstr "Dnevnik sprememb" + +#: IDF/gettexttemplates/idf/source/base.html.php:6 +msgid "How To Get The Code" +msgstr "Navodila za dostop" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:3 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:8 +#: IDF/Views/Project.php:190 +msgid "Age" +msgstr "Starost" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:4 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:10 +msgid "Message" +msgstr "Sporočilo" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:5 +msgid "Parent:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:6 +#: IDF/gettexttemplates/idf/source/commit.html.php:10 +#: IDF/gettexttemplates/idf/source/commit.html~.php:10 +msgid "View corresponding commit" +msgstr "" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:8 +msgid "by" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:3 +msgid "A new commit has been created:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:8 +msgid "Created by:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:8 +msgid "Created at:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:8 +msgid "Content:" +msgstr "Vsebina:" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:10 +msgid "Commit details:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:4 +#: IDF/gettexttemplates/idf/source/commit.html~.php:4 +msgid "Date:" +msgstr "Datum:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:6 +#: IDF/gettexttemplates/idf/source/commit.html~.php:6 +msgid "Branch:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:9 +#: IDF/gettexttemplates/idf/source/commit.html~.php:9 +msgid "Parents:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:11 +#: IDF/gettexttemplates/idf/source/commit.html~.php:11 +msgid "Message:" +msgstr "Sporočilo:" + +#: IDF/gettexttemplates/idf/source/commit.html.php:12 +#: IDF/gettexttemplates/idf/source/commit.html~.php:12 +#: IDF/gettexttemplates/idf/wiki/feedfragment-page.xml.php:3 +#: IDF/gettexttemplates/idf/wiki/feedfragment-resource.xml.php:3 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:10 +msgid "Changes:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:13 +#: IDF/gettexttemplates/idf/source/commit.html~.php:13 +msgid "deleted" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:14 +#: IDF/gettexttemplates/idf/source/commit.html.php:18 +#: IDF/gettexttemplates/idf/source/commit.html~.php:14 +#: IDF/gettexttemplates/idf/source/commit.html~.php:17 +msgid "full" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:15 +#: IDF/gettexttemplates/idf/source/commit.html~.php:15 +msgid "renamed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:16 +msgid "copied" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:17 +#: IDF/gettexttemplates/idf/source/commit.html~.php:16 +msgid "added" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:19 +#: IDF/gettexttemplates/idf/source/commit.html~.php:18 +msgid "modified" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:20 +msgid "properties changed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:21 +#: IDF/gettexttemplates/idf/source/commit.html~.php:20 +msgid "removed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:22 +#: IDF/gettexttemplates/idf/source/commit.html~.php:21 +msgid "File differences" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html~.php:19 +msgid "properies changed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:3 +#, php-format +msgid "" +"The revision identifier %%commit%% is ambiguous and can be\n" +"expanded to multiple valid revisions - please choose one:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:5 +msgid "Title" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:6 +msgid "Author" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:7 +msgid "Date" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:8 +msgid "Branch" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:9 +msgid "Revision" +msgstr "" + +#: IDF/gettexttemplates/idf/source/feedfragment.xml.php:3 +#, php-format +msgid "%%cproject.name%%: Commit %%c.scm_id%%" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:3 +msgid "Branches" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:4 +msgid "filter branches" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:5 +msgid "Tags" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:6 +msgid "filter tags" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/file.html.php:3 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:4 +#, php-format +msgid "" +"Source at commit %%commit%% created " +"%%cobject.date%%." +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/file.html.php:4 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:5 +#, php-format +msgid "By %%cobject.author%%, %%cobject.title%%" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/file.html.php:5 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:6 +msgid "Root" +msgstr "Root" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the git software to manage the source\n" +"code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:6 +#, php-format +msgid "" +"You may need to provide your SSH key. The " +"synchronization of your SSH key can take a couple of minutes. You can learn " +"more about SSH key authentication." +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:6 +msgid "To make a first commit in the repository, perform the following steps:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:8 +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:7 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:7 +#, php-format +msgid "Find here more details on how to access %%project%% source code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:9 +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:8 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:8 +msgid "Command-Line Access" +msgstr "Možnosti ukazne vrstice" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:10 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:9 +msgid "First Commit" +msgstr "Prvi vnos" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:11 +#: IDF/Views/Download.php:66 IDF/Views/Download.php:348 +msgid "Size" +msgstr "Velikost" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:12 +msgid ":" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:13 +msgid "Download this version" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:13 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:13 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:14 +msgid "or" +msgstr "" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:3 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:3 +#, php-format +msgid "" +"The branch or revision %%commit%% is not valid or does not exist\n" +"in this repository." +msgstr "" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:5 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:5 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:5 +msgid "The following list shows all available branches:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:6 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:6 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:6 +#, php-format +msgid "" +"If this is a new repository, the reason for this error\n" +"could be that you have not committed and / or pushed any change so far.\n" +"In this case please take a look at the Help page\n" +"how to access your repository." +msgstr "" + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the Mercurial software to manage the source\n" +"code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:6 +#, php-format +msgid "" +"To get write access to the repository, you need to use your username and " +"your extra password." +msgstr "" + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:9 +msgid "Write Access Authentication" +msgstr "" + +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:3 +#, php-format +msgid "Property %%prop%% set to %%val%%" +msgstr "" + +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the monotone software to manage the source\n" +"code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/changelog.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/commit.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/commit.html~.php:3 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:14 +msgid "Revision:" +msgstr "Revizija:" + +#: IDF/gettexttemplates/idf/source/svn/changelog.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/commit.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/commit.html~.php:4 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:10 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:15 +msgid "Switch" +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the subversion software to manage the source\n" +"code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:3 +#, php-format +msgid "" +"The revision %%commit%% is not valid or does not exist\n" +"in this repository." +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:9 +msgid "Rev" +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:16 +msgid "Branches:" +msgstr "Branža:" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:17 +msgid "Tags:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/changeemail-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"To confirm that you want %%email%%\n" +"to be your new email address, just follow this link:\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following verification key:\n" +"\n" +"%%key%%\n" +"\n" +"If you do not want to change your email address, \n" +"just ignore this message.\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/user/changeemail.html.php:4 +msgid "Confirm Your New Email Address" +msgstr "" + +#: IDF/gettexttemplates/idf/user/changeemail.html.php:7 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:7 +msgid "" +"Use your email software to read your emails and open your verification " +"email. Either click directly on the verification link or copy/paste the " +"verification key in the box and submit the form." +msgstr "" + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:3 +#, php-format +msgid "Update your account." +msgstr "" + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:4 +#, php-format +msgid "See your public profile." +msgstr "" + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:5 +#, php-format +msgid "See your forge issue watch list." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:6 +msgid "Key Management" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:7 +msgid "Secondary Emails" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:8 +msgid "Extra password" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:9 +msgid "" +"This password is used to access some of the external systems managed by our " +"infrastructure. It will be regenerated if you change your password." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:10 +msgid "API key" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:11 +msgid "" +"Your API key will be regenerated automatically if you change your password." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:12 +msgid "Update Your Account" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:14 +msgid "Your Current Public Keys" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:15 +msgid "Delete this key" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:16 +msgid "Your additional email addresses" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:17 +msgid "Delete this address" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:18 +msgid "" +"If possible, use your real name. By using your real name, people will have " +"more trust in your comments and remarks." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:19 +msgid "" +"The extra password is used to access some of the external systems and the " +"API key is used to interact with this website using a program." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:20 +msgid "Show API key and extra password" +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:3 +msgid "" +"Oops, please check the provided login or email address to recover your " +"password." +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:4 +msgid "Recover My Password" +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:6 +msgid "" +"Provide either your login or email address, if a corresponding user is found " +"in the database, we will send you an email with the details on how to reset " +"your password." +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"You lost your password and wanted to recover it.\n" +"To provide a new password for your account, you\n" +"just have to follow the provided link. You will\n" +"get a simple form to provide a new password.\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following verification key:\n" +"\n" +"%%key%%\n" +"\n" +"If you are not the one who requested to reset\n" +"your password, simply ignore this email, your\n" +"password will not be changed.\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:4 +msgid "Recover Your Password" +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:8 +msgid "" +"Just after providing the confirmation key, you will be able to reset your " +"password and use this website fully." +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:6 +msgid "Reset Your Password" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:3 +#, php-format +msgid "You are looking at the public profile of %%member%%." +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:5 +msgid "Twitter:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:6 +msgid "Public Email:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:7 +msgid "Website:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:8 +msgid "Last time seen:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:9 +msgid "Member since:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:3 +msgid "List Pages" +msgstr "Vse strani" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:4 +msgid "List Resources" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:5 +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:4 +#: IDF/gettexttemplates/idf/wiki/search.html.php:3 IDF/Views/Wiki.php:211 +msgid "New Page" +msgstr "Nova stran" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:6 +#: IDF/gettexttemplates/idf/wiki/listResources.html.php:3 +#: IDF/Views/Wiki.php:256 +#, fuzzy +msgid "New Resource" +msgstr "Nova zadeva" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:7 +msgid "Update This Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:8 +#, fuzzy +msgid "Update This Resource" +msgstr "Osveži uporabnika" + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:3 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:3 +msgid "Preview of the Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:7 +msgid "The form contains some errors. Please correct them to create the page." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:6 +msgid "Create Page" +msgstr "Nova stran" + +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:3 +msgid "" +"\n" +"Wiki resources are later addressed in wiki pages by their title, so ensure " +"that you\n" +"give your resource a unique and an easy to remember name.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:8 +#, fuzzy +msgid "Create Resource" +msgstr "Ustvari Uporabniški Račun" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:3 +msgid "" +"If you delete this documentation page, it will be removed from the database " +"with all the associated revisions and you will not be able to " +"recover it." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:6 +msgid "Delete Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:14 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:15 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:15 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:17 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:18 +msgid "Old Revisions" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:3 +#, php-format +msgid "" +"You are looking at an old revision (%%oldrev.summary%%) of the " +"page \n" +"%%page.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:5 +msgid "" +"If you delete this old revision, it will be removed from the database and " +"you will not be able to recover it." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:8 +msgid "Delete Revision" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:3 +msgid "" +"If you delete this documentation resource, it will be removed from the " +"database with all the associated revisions \n" +"and you will not be able to recover it. Any documentation " +"pages that reference this resource,\n" +"will no longer be able to render it, but won't be deleted." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:8 +#, fuzzy +msgid "Delete Resource" +msgstr "Izbriši projekt" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:10 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:8 +#, fuzzy +msgid "File size" +msgstr "velikost datoteke" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:9 +#: IDF/Views/Wiki.php:101 +#, fuzzy +msgid "MIME type" +msgstr "tip" + +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:3 +#, php-format +msgid "" +"You are looking at an old revision (%%oldrev.summary%%) of the " +"resource \n" +"%%resource.title%%. This revision was created by " +"%%submitter%%." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/edit-info.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

The content of the page can use the Markdown syntax with the Extra extension.

\n" +"

Website addresses are automatically linked and you can link to another " +"page in the documentation using double square brackets like that " +"[[AnotherPage]].

\n" +"

If you want to embed uploaded resources, use the [[!ResourceName]] syntax for that. This is described more in detail in the FAQ.

\n" +"

To directly include a file content from the repository, embrace its path " +"with triple square brackets: [[[my/file.txt]]].

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/feedfragment-resource.xml.php:4 +msgid "Initial creation" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:3 +#, php-format +msgid "See the deprecated pages." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:5 +msgid "Number of pages:" +msgstr "Število strani:" + +#: IDF/gettexttemplates/idf/wiki/listResources.html.php:4 +#, fuzzy +msgid "Number of resources:" +msgstr "Število uporabnikov:" + +#: IDF/gettexttemplates/idf/wiki/search.html.php:4 +msgid "Pages found:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:3 +msgid "The form contains some errors. Please correct them to update the page." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:6 +msgid "Update Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:10 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:11 +msgid "Delete this page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:4 +#, fuzzy +msgid "Update Resource" +msgstr "Osveži uporabnika" + +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:8 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:9 +#, fuzzy +msgid "Delete this resource" +msgstr "Izbriši ta projekt" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:3 +msgid "" +"Attention! This page is marked as deprecated, \n" +"use it as reference only if you are sure you need these specific information." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:5 +#, php-format +msgid "" +"You are looking at an old revision of the page \n" +"%%page.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:10 +msgid "Table of Content" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:13 +msgid "Delete this revision" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:3 +#, php-format +msgid "" +"You are looking at an old revision of the resource \n" +"%%resource.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:14 +#, fuzzy +msgid "Page Usage" +msgstr "Naslov strani" + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:15 +msgid "This resource is not used on any pages yet." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:3 +msgid "A new documentation page has been created:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:14 +msgid "Documentation page:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:3 +msgid "The following documentation page has been updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:7 +msgid "Updated by:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:13 +msgid "New content:" +msgstr "" + +#: IDF/Issue.php:76 +msgid "owner" +msgstr "lastnik" + +#: IDF/Issue.php:84 IDF/Wiki/Page.php:86 +msgid "interested users" +msgstr "" + +#: IDF/Issue.php:85 +msgid "" +"Interested users will get an email notification when the issue is changed." +msgstr "" + +#: IDF/Issue.php:92 IDF/Project.php:94 IDF/Review.php:95 IDF/Upload.php:99 +#: IDF/Wiki/Page.php:94 +msgid "labels" +msgstr "oznake" + +#: IDF/Issue.php:111 IDF/IssueFile.php:102 IDF/Review.php:114 +#: IDF/Upload.php:118 IDF/Wiki/Page.php:106 IDF/Wiki/Resource.php:101 +msgid "modification date" +msgstr "datum spremembe" + +#: IDF/Issue.php:212 IDF/IssueComment.php:143 +#, php-format +msgid "" +"Issue %3$d, %4$s" +msgstr "" + +#: IDF/Issue.php:214 +#, php-format +msgid "Creation of issue %3$d, by %4$s" +msgstr "" + +#: IDF/Issue.php:224 +#, php-format +msgid "%1$s: Issue %2$d created - %3$s" +msgstr "" + +#: IDF/Issue.php:307 +#, php-format +msgid "Issue %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Issue.php:311 +#, php-format +msgid "Updated Issue %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/IssueComment.php:51 IDF/IssueRelation.php:47 +msgid "issue" +msgstr "zadeva" + +#: IDF/IssueComment.php:58 IDF/IssueFile.php:49 IDF/Review/Comment.php:62 +#: IDF/Review/FileComment.php:49 IDF/Review/FileComment.php:69 +msgid "comment" +msgstr "komentar" + +#: IDF/IssueComment.php:72 IDF/Review/Comment.php:75 IDF/Upload.php:63 +#: IDF/Wiki/PageRevision.php:85 +msgid "changes" +msgstr "spremembe" + +#: IDF/IssueComment.php:73 +msgid "Serialized array of the changes in the issue." +msgstr "" + +#: IDF/IssueComment.php:180 +#, php-format +msgid "Comment on issue %3$d, by %4$s" +msgstr "" + +#: IDF/IssueComment.php:191 +#, php-format +msgid "%1$s: Comment on issue %2$d - %3$s" +msgstr "" + +#: IDF/IssueFile.php:64 +msgid "file name" +msgstr "ime datoteke" + +#: IDF/IssueFile.php:70 +msgid "the file" +msgstr "Datoteka " + +#: IDF/IssueFile.php:76 +msgid "file size" +msgstr "velikost datoteke" + +#: IDF/IssueFile.php:84 +msgid "type" +msgstr "tip" + +#: IDF/IssueFile.php:86 +msgid "Image" +msgstr "Slika" + +#: IDF/IssueFile.php:87 +msgid "Other" +msgstr "Ostalo" + +#: IDF/IssueRelation.php:54 +msgid "verb" +msgstr "" + +#: IDF/IssueRelation.php:61 +msgid "other issue" +msgstr "" + +#: IDF/Key.php:55 +msgid "public key" +msgstr "" + +#: IDF/Key.php:90 +msgid "Invalid or unknown key data detected." +msgstr "" + +#: IDF/Plugin/SyncMercurial.php:78 IDF/Plugin/SyncSvn.php:81 +#, php-format +msgid "The repository %s already exists." +msgstr "" + +#: IDF/Plugin/SyncMercurial.php:142 +#, php-format +msgid "%s does not exist or is not writable." +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:107 IDF/Plugin/SyncMonotone.php:492 +msgid "\"mtn_repositories\" must be defined in your configuration file" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:114 IDF/Plugin/SyncMonotone.php:482 +msgid "\"mtn_usher_conf\" does not exist or is not writable" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:121 +#, php-format +msgid "Could not find mtn-post-push script \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:155 +#, php-format +msgid "The configuration file \"%s\" is missing" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:164 +#, php-format +msgid "The project path \"%s\" already exists" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:170 +#, php-format +msgid "The project path \"%s\" could not be created" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:208 +#, php-format +msgid "The key directory \"%s\" could not be created" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:227 +#, php-format +msgid "Could not parse key information: %s" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:265 +#, php-format +msgid "Could not create configuration directory \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:275 +#, php-format +msgid "Could not create symlink for configuration file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:293 +#, php-format +msgid "Could not write configuration file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:309 IDF/Plugin/SyncMonotone.php:525 +#, php-format +msgid "Could not parse usher configuration in \"%1$s\": %2$s" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:320 +#, php-format +msgid "usher configuration already contains a server entry named \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:345 IDF/Plugin/SyncMonotone.php:546 +#, php-format +msgid "Could not write usher configuration file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:395 +#, php-format +msgid "Could not write write-permissions file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:420 +#, php-format +msgid "Could not write read-permissions file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:438 +#, php-format +msgid "Could not remove symlink \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:446 +#, php-format +msgid "Could not create symlink \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:500 +#, php-format +msgid "One or more paths underneath %s could not be deleted" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:512 +#, php-format +msgid "Could not delete client private key \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:599 IDF/Plugin/SyncMonotone.php:718 +#, php-format +msgid "Could not parse read-permissions for project \"%1$s\": %2$s" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:643 IDF/Plugin/SyncMonotone.php:741 +#, php-format +msgid "Could not write read-permissions for project \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:657 IDF/Plugin/SyncMonotone.php:760 +#, php-format +msgid "Could not write write-permissions file for project \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:813 +msgid "\"mtn_repositories\" must be defined in your configuration file." +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:820 +#, php-format +msgid "The project path %s does not exists." +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:838 +#, php-format +msgid "The command \"%s\" could not be executed." +msgstr "" + +#: IDF/Project.php:62 IDF/Tag.php:66 +msgid "name" +msgstr "ime" + +#: IDF/Project.php:69 +msgid "short name" +msgstr "kratko ime" + +#: IDF/Project.php:70 +msgid "" +"Used in the URL to access the project, must be short with only letters and " +"numbers." +msgstr "" + +#: IDF/Project.php:78 +msgid "short description" +msgstr "Dostopen opis" + +#: IDF/Project.php:86 IDF/Review/Patch.php:74 +msgid "description" +msgstr "opis" + +#: IDF/Project.php:87 +msgid "The description can be extended using the Markdown syntax." +msgstr "" + +#: IDF/Project.php:100 +msgid "private" +msgstr "zasebno" + +#: IDF/Project.php:108 +msgid "current project activity" +msgstr "" + +#: IDF/Project.php:159 +#, php-format +msgid "Project \"%s\" not found." +msgstr "" + +#: IDF/ProjectActivity.php:56 +#, fuzzy +msgid "date" +msgstr "Zadnjič posodobljeno" + +#: IDF/Review/Comment.php:55 IDF/Review/Patch.php:80 +msgid "patch" +msgstr "" + +#: IDF/Review/Comment.php:83 +msgid "vote" +msgstr "" + +#: IDF/Review/Comment.php:139 IDF/Review/Patch.php:151 +#, php-format +msgid "" +"Review %3$d, %4$s" +msgstr "" + +#: IDF/Review/Comment.php:141 +#, php-format +msgid "Update of review %3$d, by %4$s" +msgstr "" + +#: IDF/Review/Comment.php:151 +#, php-format +msgid "%1$s: Updated review %2$d - %3$s" +msgstr "" + +#: IDF/Review/Comment.php:222 +#, php-format +msgid "Updated Code Review %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Review/Patch.php:52 +msgid "review" +msgstr "" + +#: IDF/Review/Patch.php:67 +msgid "commit" +msgstr "" + +#: IDF/Review/Patch.php:153 +#, php-format +msgid "Creation of review %3$d, by %4$s" +msgstr "" + +#: IDF/Review/Patch.php:163 +#, php-format +msgid "%1$s: Creation of Review %2$d - %3$s" +msgstr "" + +#: IDF/Review/Patch.php:208 +#, php-format +msgid "New Code Review %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Scm/Git.php:309 IDF/Scm/Mercurial.php:199 +#, php-format +msgid "Folder %1$s not found in commit %2$s." +msgstr "" + +#: IDF/Scm/Git.php:433 IDF/Scm/Mercurial.php:216 +#, php-format +msgid "Not a valid tree: %s." +msgstr "" + +#: IDF/Scm/Monotone/Stdio.php:81 +msgid "Monotone client key name or hash not in project conf." +msgstr "" + +#: IDF/Scm/Monotone/Stdio.php:89 +#, php-format +msgid "The key directory %s could not be created." +msgstr "" + +#: IDF/Scm/Monotone/Stdio.php:100 +#, php-format +msgid "Could not write client key \"%s\"" +msgstr "" + +#: IDF/Search/Occ.php:33 +msgid "occurrence" +msgstr "" + +#: IDF/Search/Occ.php:49 +msgid "word" +msgstr "" + +#: IDF/Search/Occ.php:75 +msgid "occurrences" +msgstr "" + +#: IDF/Search/Occ.php:81 +msgid "ponderated occurrence" +msgstr "" + +#: IDF/Tag.php:59 +msgid "tag class" +msgstr "" + +#: IDF/Tag.php:60 +msgid "The class of the tag." +msgstr "" + +#: IDF/Tag.php:73 +msgid "lcname" +msgstr "" + +#: IDF/Tag.php:74 +msgid "Lower case version of the name for fast searching." +msgstr "" + +#: IDF/Template/Markdown.php:84 +msgid "Create this documentation page" +msgstr "" + +#: IDF/Template/Markdown.php:97 +msgid "You are not allowed to access the wiki." +msgstr "" + +#: IDF/Template/Markdown.php:106 +msgid "The wiki resource has not been found." +msgstr "" + +#: IDF/Template/Markdown.php:113 +msgid "The wiki resource has not been found. Create it!" +msgstr "" + +#: IDF/Template/Markdown.php:146 +msgid "This revision of the resource is no longer available." +msgstr "" + +#: IDF/Template/ShowUser.php:51 +msgid "Anonymous" +msgstr "" + +#: IDF/Template/ShowUser.php:54 +msgid "Me" +msgstr "Jaz" + +#: IDF/Timeline/Paginator.php:49 +msgid "Today" +msgstr "Danes" + +#: IDF/Upload.php:70 +msgid "file" +msgstr "datoteka" + +#: IDF/Upload.php:71 +msgid "The path is relative to the upload path." +msgstr "" + +#: IDF/Upload.php:78 IDF/Wiki/ResourceRevision.php:71 +msgid "file size in bytes" +msgstr "Velikost v bajtih" + +#: IDF/Upload.php:84 +msgid "MD5" +msgstr "" + +#: IDF/Upload.php:106 +msgid "number of downloads" +msgstr "število prenosov" + +#: IDF/Upload.php:201 +#, php-format +msgid "Download %2$d, %3$s" +msgstr "" + +#: IDF/Upload.php:204 +#, php-format +msgid "Addition of download %2$d, by %3$s" +msgstr "" + +#: IDF/Upload.php:214 +#, php-format +msgid "%1$s: Download %2$d added - %3$s" +msgstr "" + +#: IDF/Upload.php:301 +#, php-format +msgid "New download - %1$s (%2$s)" +msgstr "" + +#: IDF/Upload.php:305 +#, php-format +msgid "Updated download - %1$s (%2$s)" +msgstr "" + +#: IDF/Views/Admin.php:47 +msgid "The forge configuration has been saved." +msgstr "" + +#: IDF/Views/Admin.php:80 +msgid "This table shows the projects in the forge." +msgstr "" + +#: IDF/Views/Admin.php:85 +msgid "Short Name" +msgstr "Kratko ime" + +#: IDF/Views/Admin.php:87 +msgid "Repository Size" +msgstr "Velikost repozitorija" + +#: IDF/Views/Admin.php:93 +msgid "No projects were found." +msgstr "" + +#: IDF/Views/Admin.php:116 +msgid "The label configuration has been saved." +msgstr "" + +#: IDF/Views/Admin.php:147 IDF/Views/Admin.php:314 IDF/Views/Wiki.php:484 +#: IDF/Views/Wiki.php:536 +#, php-format +msgid "Update %s" +msgstr "" + +#: IDF/Views/Admin.php:155 IDF/Views/Project.php:304 +msgid "The project has been updated." +msgstr "" + +#: IDF/Views/Admin.php:192 +msgid "The project has been created." +msgstr "" + +#: IDF/Views/Admin.php:223 +#, php-format +msgid "Delete %s Project" +msgstr "" + +#: IDF/Views/Admin.php:230 +msgid "The project has been deleted." +msgstr "" + +#: IDF/Views/Admin.php:260 +msgid "Not Validated User List" +msgstr "" + +#: IDF/Views/Admin.php:268 +msgid "This table shows the users in the forge." +msgstr "" + +#: IDF/Views/Admin.php:272 +msgid "login" +msgstr "" + +#: IDF/Views/Admin.php:275 +msgid "Admin" +msgstr "Administrator" + +#: IDF/Views/Admin.php:277 +msgid "Last Login" +msgstr "Zadnja prijava" + +#: IDF/Views/Admin.php:284 +msgid "No users were found." +msgstr "Nisem našel uporabnikov!" + +#: IDF/Views/Admin.php:321 +msgid "You do not have the rights to update this user." +msgstr "" + +#: IDF/Views/Admin.php:339 +msgid "The user has been updated." +msgstr "" + +#: IDF/Views/Admin.php:372 +#, php-format +msgid "The user %s has been created." +msgstr "" + +#: IDF/Views/Admin.php:379 +msgid "Add User" +msgstr "" + +#: IDF/Views/Admin.php:395 +msgid "Usher management" +msgstr "" + +#: IDF/Views/Admin.php:432 +msgid "Usher configuration has been reloaded" +msgstr "" + +#: IDF/Views/Admin.php:436 +msgid "Usher has been shut down" +msgstr "" + +#: IDF/Views/Admin.php:441 +msgid "Usher has been started up" +msgstr "" + +#: IDF/Views/Admin.php:479 +#, php-format +msgid "The server \"%s\" has been started" +msgstr "" + +#: IDF/Views/Admin.php:483 +#, php-format +msgid "The server \"%s\" has been stopped" +msgstr "" + +#: IDF/Views/Admin.php:488 +#, php-format +msgid "The server \"%s\" has been killed" +msgstr "" + +#: IDF/Views/Admin.php:508 +#, php-format +msgid "Open connections for \"%s\"" +msgstr "" + +#: IDF/Views/Admin.php:513 +#, php-format +msgid "no connections for server \"%s\"" +msgstr "" + +#: IDF/Views/Admin.php:534 +msgid "Yes" +msgstr "Da" + +#: IDF/Views/Admin.php:534 +msgid "No" +msgstr "Ne" + +#: IDF/Views/Download.php:45 +#, php-format +msgid "%s Downloads" +msgstr "" + +#: IDF/Views/Download.php:51 +msgid "This table shows the files to download." +msgstr "" + +#: IDF/Views/Download.php:67 IDF/Views/Download.php:349 +msgid "Uploaded" +msgstr "" + +#: IDF/Views/Download.php:71 IDF/Views/Download.php:353 +msgid "No downloads were found." +msgstr "" + +#: IDF/Views/Download.php:94 +#, php-format +msgid "Download %s" +msgstr "" + +#: IDF/Views/Download.php:111 +#, php-format +msgid "The file %2$s has been updated." +msgstr "" + +#: IDF/Views/Download.php:144 +#, php-format +msgid "Delete Download %s" +msgstr "" + +#: IDF/Views/Download.php:177 +msgid "The file has been deleted." +msgstr "" + +#: IDF/Views/Download.php:244 +#, php-format +msgid "The file has been uploaded." +msgstr "" + +#: IDF/Views/Download.php:271 +msgid "New Downloads from Archive" +msgstr "" + +#: IDF/Views/Download.php:278 +msgid "The archive has been uploaded and processed." +msgstr "" + +#: IDF/Views/Download.php:331 +#, php-format +msgid "%1$s Downloads with Label %2$s" +msgstr "" + +#: IDF/Views/Download.php:341 +#, php-format +msgid "This table shows the downloads with label %s." +msgstr "" + +#: IDF/Views/Issue.php:41 +#, php-format +msgid "%s Open Issues" +msgstr "" + +#: IDF/Views/Issue.php:51 IDF/Views/Issue.php:382 IDF/Views/User.php:75 +msgid "This table shows the open issues." +msgstr "" + +#: IDF/Views/Issue.php:61 IDF/Views/Issue.php:220 IDF/Views/Issue.php:301 +#: IDF/Views/Issue.php:390 IDF/Views/Issue.php:542 IDF/Views/Issue.php:765 +#: IDF/Views/Issue.php:824 IDF/Views/Review.php:57 IDF/Views/User.php:81 +msgid "Id" +msgstr "Id" + +#: IDF/Views/Issue.php:64 IDF/Views/Issue.php:223 IDF/Views/Issue.php:305 +#: IDF/Views/Issue.php:393 IDF/Views/Issue.php:545 IDF/Views/Issue.php:768 +#: IDF/Views/Issue.php:827 IDF/Views/Review.php:60 IDF/Views/User.php:85 +msgid "Last Updated" +msgstr "" + +#: IDF/Views/Issue.php:68 IDF/Views/Issue.php:227 IDF/Views/Issue.php:309 +#: IDF/Views/Issue.php:397 IDF/Views/Issue.php:549 IDF/Views/Issue.php:772 +#: IDF/Views/Issue.php:831 +msgid "No issues were found." +msgstr "" + +#: IDF/Views/Issue.php:113 +msgid "Not assigned" +msgstr "" + +#: IDF/Views/Issue.php:149 +#, php-format +msgid "Summary of tracked issues in %s." +msgstr "" + +#: IDF/Views/Issue.php:194 +#, php-format +msgid "Watch List: Closed Issues for %s" +msgstr "" + +#: IDF/Views/Issue.php:195 +#, php-format +msgid "This table shows the closed issues in your watch list for %s project." +msgstr "" + +#: IDF/Views/Issue.php:200 +#, php-format +msgid "Watch List: Open Issues for %s" +msgstr "" + +#: IDF/Views/Issue.php:201 +#, php-format +msgid "This table shows the open issues in your watch list for %s project." +msgstr "" + +#: IDF/Views/Issue.php:277 +msgid "Watch List: Closed Issues" +msgstr "" + +#: IDF/Views/Issue.php:278 +msgid "This table shows the closed issues in your watch list." +msgstr "" + +#: IDF/Views/Issue.php:283 +msgid "Watch List: Open Issues" +msgstr "" + +#: IDF/Views/Issue.php:284 +msgid "This table shows the open issues in your watch list." +msgstr "" + +#: IDF/Views/Issue.php:303 IDF/Views/User.php:82 +msgid "Project" +msgstr "Projekt" + +#: IDF/Views/Issue.php:344 +#, fuzzy, php-format +msgid "%1$s %2$s Submitted %3$s Issues" +msgstr "Poslanih zadev:" + +#: IDF/Views/Issue.php:348 +#, php-format +msgid "%1$s %2$s Closed Submitted %3$s Issues" +msgstr "" + +#: IDF/Views/Issue.php:352 +#, php-format +msgid "%1$s %2$s Closed Working %3$s Issues" +msgstr "" + +#: IDF/Views/Issue.php:356 +#, php-format +msgid "%1$s %2$s Working %3$s Issues" +msgstr "" + +#: IDF/Views/Issue.php:417 +msgid "Submit a new issue" +msgstr "Pošiljanje nove zadeve" + +#: IDF/Views/Issue.php:433 +#, php-format +msgid "Issue %2$d has been created." +msgstr "" + +#: IDF/Views/Issue.php:490 +#, php-format +msgid "Search issues - %s" +msgstr "" + +#: IDF/Views/Issue.php:492 +#, php-format +msgid "Search closed issues - %s" +msgstr "" + +#: IDF/Views/Issue.php:539 +msgid "This table shows the found issues." +msgstr "" + +#: IDF/Views/Issue.php:604 +#, php-format +msgid "Issue %2$d: %3$s" +msgstr "" + +#: IDF/Views/Issue.php:628 +#, php-format +msgid "Issue %2$d has been updated." +msgstr "" + +#: IDF/Views/Issue.php:718 +#, php-format +msgid "View %s" +msgstr "Poglej %s" + +#: IDF/Views/Issue.php:745 +#, php-format +msgid "%s Closed Issues" +msgstr "" + +#: IDF/Views/Issue.php:755 +msgid "This table shows the closed issues." +msgstr "" + +#: IDF/Views/Issue.php:798 +#, php-format +msgid "%1$s Issues with Label %2$s" +msgstr "" + +#: IDF/Views/Issue.php:801 +#, php-format +msgid "%1$s Closed Issues with Label %2$s" +msgstr "" + +#: IDF/Views/Issue.php:814 +#, php-format +msgid "This table shows the issues with label %s." +msgstr "" + +#: IDF/Views/Issue.php:937 +msgid "The issue has been removed from your watch list." +msgstr "" + +#: IDF/Views/Issue.php:940 +msgid "The issue has been added to your watch list." +msgstr "" + +#: IDF/Views/Issue.php:1037 +msgid "On your watch list." +msgstr "" + +#: IDF/Views/Project.php:95 +msgid "Issues and Comments" +msgstr "" + +#: IDF/Views/Project.php:99 +msgid "Documents" +msgstr "" + +#: IDF/Views/Project.php:101 +msgid "Reviews and Patches" +msgstr "" + +#: IDF/Views/Project.php:180 +msgid "This table shows the project updates." +msgstr "" + +#: IDF/Views/Project.php:191 +msgid "Change" +msgstr "Spremeni" + +#: IDF/Views/Project.php:195 +msgid "No changes were found." +msgstr "" + +#: IDF/Views/Project.php:296 +#, php-format +msgid "%s Project Summary" +msgstr "" + +#: IDF/Views/Project.php:335 +#, php-format +msgid "%s Issue Tracking Configuration" +msgstr "" + +#: IDF/Views/Project.php:344 +msgid "The issue tracking configuration has been saved." +msgstr "" + +#: IDF/Views/Project.php:381 +#, php-format +msgid "%s Downloads Configuration" +msgstr "" + +#: IDF/Views/Project.php:393 +msgid "The downloads configuration has been saved." +msgstr "" + +#: IDF/Views/Project.php:428 +#, php-format +msgid "%s Documentation Configuration" +msgstr "" + +#: IDF/Views/Project.php:437 +msgid "The documentation configuration has been saved." +msgstr "" + +#: IDF/Views/Project.php:471 +#, php-format +msgid "%s Project Members" +msgstr "" + +#: IDF/Views/Project.php:480 +msgid "The project membership has been saved." +msgstr "" + +#: IDF/Views/Project.php:503 +#, php-format +msgid "%s Tabs Access Rights" +msgstr "" + +#: IDF/Views/Project.php:517 +msgid "" +"The project tabs access rights and notification settings have been saved." +msgstr "" + +#: IDF/Views/Project.php:566 +#, php-format +msgid "%s Source" +msgstr "" + +#: IDF/Views/Project.php:580 +msgid "The project source configuration has been saved." +msgstr "" + +#: IDF/Views/Review.php:41 +#, php-format +msgid "%s Code Reviews" +msgstr "" + +#: IDF/Views/Review.php:48 +msgid "This table shows the latest reviews." +msgstr "" + +#: IDF/Views/Review.php:64 +msgid "No reviews were found." +msgstr "" + +#: IDF/Views/Review.php:94 +#, php-format +msgid "The code review %2$d has been created." +msgstr "" + +#: IDF/Views/Review.php:140 +#, php-format +msgid "Review %2$d: %3$s" +msgstr "" + +#: IDF/Views/Review.php:160 +#, php-format +msgid "Your code review %2$d has been published." +msgstr "" + +#: IDF/Views/Source.php:40 +#, php-format +msgid "%s Source Help" +msgstr "" + +#: IDF/Views/Source.php:58 +#, php-format +msgid "%s Invalid Revision" +msgstr "" + +#: IDF/Views/Source.php:82 +#, php-format +msgid "%s Ambiguous Revision" +msgstr "" + +#: IDF/Views/Source.php:107 +#, php-format +msgid "%1$s %2$s Change Log" +msgstr "" + +#: IDF/Views/Source.php:153 IDF/Views/Source.php:234 IDF/Views/Source.php:362 +#, php-format +msgid "%1$s %2$s Source Tree" +msgstr "" + +#: IDF/Views/Source.php:310 +#, php-format +msgid "%s Commit Details" +msgstr "" + +#: IDF/Views/Source.php:311 +#, php-format +msgid "%1$s Commit Details - %2$s" +msgstr "" + +#: IDF/Views/User.php:59 +msgid "Your Dashboard - Working Issues" +msgstr "" + +#: IDF/Views/User.php:62 +msgid "Your Dashboard - Submitted Issues" +msgstr "" + +#: IDF/Views/User.php:89 +msgid "No issues are assigned to you, yeah!" +msgstr "" + +#: IDF/Views/User.php:89 +msgid "All the issues you submitted are fixed, yeah!" +msgstr "" + +#: IDF/Views/User.php:121 +msgid "Your personal information has been updated." +msgstr "" + +#: IDF/Views/User.php:133 +msgid "Your Account" +msgstr "Vaš račun" + +#: IDF/Views/User.php:157 +msgid "The public key has been deleted." +msgstr "" + +#: IDF/Views/User.php:177 +msgid "The address has been deleted." +msgstr "" + +#: IDF/Views/User.php:200 +msgid "Confirm The Email Change" +msgstr "" + +#: IDF/Views/User.php:232 +#, php-format +msgid "Your new email address \"%s\" has been validated. Thank you!" +msgstr "" + +#: IDF/Views/Wiki.php:41 +#, php-format +msgid "%s Documentation" +msgstr "" + +#: IDF/Views/Wiki.php:48 +msgid "This table shows the documentation pages." +msgstr "" + +#: IDF/Views/Wiki.php:61 IDF/Views/Wiki.php:144 IDF/Views/Wiki.php:185 +msgid "Page Title" +msgstr "Naslov strani" + +#: IDF/Views/Wiki.php:63 IDF/Views/Wiki.php:103 IDF/Views/Wiki.php:146 +#: IDF/Views/Wiki.php:187 +msgid "Updated" +msgstr "Zadnjič posodobljeno" + +#: IDF/Views/Wiki.php:67 IDF/Views/Wiki.php:191 +msgid "No documentation pages were found." +msgstr "" + +#: IDF/Views/Wiki.php:88 +#, fuzzy, php-format +msgid "%s Documentation Resources" +msgstr "Dokumentacija" + +#: IDF/Views/Wiki.php:94 +msgid "This table shows the resources that can be used on documentation pages." +msgstr "" + +#: IDF/Views/Wiki.php:100 +#, fuzzy +msgid "Resource Title" +msgstr "Drevo izvorne kode" + +#: IDF/Views/Wiki.php:107 +#, fuzzy +msgid "No resources were found." +msgstr "Nisem našel uporabnikov!" + +#: IDF/Views/Wiki.php:128 +#, php-format +msgid "Documentation Search - %s" +msgstr "" + +#: IDF/Views/Wiki.php:139 +msgid "This table shows the pages found." +msgstr "" + +#: IDF/Views/Wiki.php:150 +msgid "No pages were found." +msgstr "Nisem našel strani." + +#: IDF/Views/Wiki.php:169 +#, php-format +msgid "%1$s Documentation Pages with Label %2$s" +msgstr "" + +#: IDF/Views/Wiki.php:179 +#, php-format +msgid "This table shows the documentation pages with label %s." +msgstr "" + +#: IDF/Views/Wiki.php:222 +#, php-format +msgid "The page %2$s has been created." +msgstr "" + +#: IDF/Views/Wiki.php:265 +#, php-format +msgid "The resource %2$s has been created." +msgstr "" + +#: IDF/Views/Wiki.php:409 IDF/Views/Wiki.php:448 +msgid "The old revision has been deleted." +msgstr "" + +#: IDF/Views/Wiki.php:415 IDF/Views/Wiki.php:454 +#, php-format +msgid "Delete Old Revision of %s" +msgstr "" + +#: IDF/Views/Wiki.php:496 +#, php-format +msgid "The page %2$s has been updated." +msgstr "" + +#: IDF/Views/Wiki.php:548 +#, php-format +msgid "The resource %2$s has been updated." +msgstr "" + +#: IDF/Views/Wiki.php:583 +msgid "The documentation page has been deleted." +msgstr "" + +#: IDF/Views/Wiki.php:591 +#, php-format +msgid "Delete Page %s" +msgstr "" + +#: IDF/Views/Wiki.php:623 +msgid "The documentation resource has been deleted." +msgstr "" + +#: IDF/Views/Wiki.php:631 +#, php-format +msgid "Delete Resource %s" +msgstr "" + +#: IDF/Views.php:173 IDF/Views.php:199 +msgid "Confirm Your Account Creation" +msgstr "" + +#: IDF/Views.php:219 +msgid "Welcome! You can now participate in the life of your project of choice." +msgstr "" + +#: IDF/Views.php:245 IDF/Views.php:269 IDF/Views.php:310 +msgid "Password Recovery" +msgstr "Ponastavitev gesla" + +#: IDF/Views.php:289 +msgid "" +"Welcome back! Next time, you can use your broswer options to remember the " +"password." +msgstr "" + +#: IDF/Views.php:331 +msgid "Here to Help You!" +msgstr "Tukaj da pomagamo!" + +#: IDF/Views.php:347 +msgid "InDefero Upload Archive Format" +msgstr "" + +#: IDF/Views.php:363 +msgid "InDefero API (Application Programming Interface)" +msgstr "" + +#: IDF/Wiki/Page.php:62 IDF/Wiki/Resource.php:64 +msgid "title" +msgstr "naslov" + +#: IDF/Wiki/Page.php:63 +msgid "" +"The title of the page must only contain letters, digits or the dash " +"character. For example: My-new-Wiki-Page." +msgstr "" + +#: IDF/Wiki/Page.php:71 +msgid "A one line description of the page content." +msgstr "" + +#: IDF/Wiki/Page.php:196 IDF/Wiki/PageRevision.php:196 +#, php-format +msgid "%2$s, %3$s" +msgstr "" + +#: IDF/Wiki/Page.php:198 +#, php-format +msgid "Creation of page %2$s, by %3$s" +msgstr "" + +#: IDF/Wiki/Page.php:208 +#, php-format +msgid "%1$s: Documentation page %2$s added - %3$s" +msgstr "" + +#: IDF/Wiki/PageRevision.php:48 +msgid "page" +msgstr "stran" + +#: IDF/Wiki/PageRevision.php:66 IDF/Wiki/ResourceRevision.php:64 +msgid "A one line description of the changes." +msgstr "" + +#: IDF/Wiki/PageRevision.php:72 +msgid "content" +msgstr "vsebina" + +#: IDF/Wiki/PageRevision.php:218 IDF/Wiki/ResourceRevision.php:311 +#, php-format +msgid "Change of %2$s, by %3$s" +msgstr "" + +#: IDF/Wiki/PageRevision.php:231 +#, php-format +msgid "%1$s: Documentation page %2$s updated - %3$s" +msgstr "" + +#: IDF/Wiki/PageRevision.php:293 +#, php-format +msgid "New Documentation Page %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Wiki/PageRevision.php:297 +#, php-format +msgid "Documentation Page Changed %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Wiki/Resource.php:65 +msgid "" +"The title of the resource must only contain letters, digits, dots or the " +"dash character. For example: my-resource.png." +msgstr "" + +#: IDF/Wiki/Resource.php:72 +msgid "MIME media type" +msgstr "" + +#: IDF/Wiki/Resource.php:73 +msgid "The MIME media type of the resource." +msgstr "" + +#: IDF/Wiki/Resource.php:81 +msgid "A one line description of the resource." +msgstr "" + +#: IDF/Wiki/Resource.php:176 IDF/Wiki/ResourceRevision.php:308 +#, php-format +msgid "%2$s, %3$s" +msgstr "" + +#: IDF/Wiki/Resource.php:178 +#, php-format +msgid "Creation of resource %2$s, by %3$s" +msgstr "" + +#: IDF/Wiki/Resource.php:188 +#, php-format +msgid "%1$s: Documentation resource %2$s added - %3$s" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:47 +#, fuzzy +msgid "resource" +msgstr "Izvorna koda" + +#: IDF/Wiki/ResourceRevision.php:78 +msgid "File extension" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:79 +msgid "The file extension of the uploaded resource." +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:94 +msgid "page usage" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:116 +#, php-format +msgid "id %d: %s" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:263 +#, fuzzy, php-format +msgid "Download (%s)" +msgstr "Prenosi" + +#: IDF/Wiki/ResourceRevision.php:270 +msgid "View resource details" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:324 +#, php-format +msgid "%1$s: Documentation resource %2$s updated - %3$s" +msgstr "" + +#~ msgid "Your mail" +#~ msgstr "Vaš e-naslov" diff --git a/indefero/src/IDF/locale/tr/idf.po b/indefero/src/IDF/locale/tr/idf.po new file mode 100644 index 0000000..acd40c8 --- /dev/null +++ b/indefero/src/IDF/locale/tr/idf.po @@ -0,0 +1,5396 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# Ozan , 2011. +msgid "" +msgstr "" +"Project-Id-Version: Indefero\n" +"Report-Msgid-Bugs-To: http://projects.ceondo.com/p/indefero/issues/\n" +"POT-Creation-Date: 2012-03-22 01:16+0100\n" +"PO-Revision-Date: 2011-10-31 14:56+0000\n" +"Last-Translator: uobasar \n" +"Language-Team: LANGUAGE \n" +"Language: tr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0\n" + +#: IDF/Commit.php:55 IDF/Conf.php:54 IDF/Issue.php:52 +#: IDF/ProjectActivity.php:49 IDF/Review.php:65 IDF/Search/Occ.php:69 +#: IDF/Tag.php:52 IDF/Upload.php:49 IDF/Wiki/Page.php:54 +#: IDF/Wiki/Resource.php:56 +msgid "project" +msgstr "proje" + +#: IDF/Commit.php:63 IDF/Issue.php:67 IDF/IssueComment.php:65 +#: IDF/IssueFile.php:57 IDF/IssueRelation.php:69 IDF/Review/Comment.php:69 +#: IDF/Review.php:80 IDF/Upload.php:91 IDF/Wiki/Page.php:78 +#: IDF/Wiki/PageRevision.php:79 IDF/Wiki/Resource.php:88 +#: IDF/Wiki/ResourceRevision.php:86 +msgid "submitter" +msgstr "" + +#: IDF/Commit.php:87 IDF/Issue.php:60 IDF/Review/Patch.php:60 +#: IDF/Review.php:73 IDF/Upload.php:57 IDF/Wiki/Page.php:70 +#: IDF/Wiki/PageRevision.php:65 IDF/Wiki/Resource.php:80 +#: IDF/Wiki/ResourceRevision.php:63 +msgid "summary" +msgstr "özet" + +#: IDF/Commit.php:93 +msgid "changelog" +msgstr "" + +#: IDF/Commit.php:100 IDF/Issue.php:105 IDF/IssueComment.php:79 +#: IDF/IssueFile.php:96 IDF/IssueRelation.php:75 IDF/Review/Comment.php:90 +#: IDF/Review/FileComment.php:75 IDF/Review/Patch.php:87 IDF/Review.php:108 +#: IDF/Upload.php:112 IDF/Wiki/Page.php:100 IDF/Wiki/PageRevision.php:92 +#: IDF/Wiki/Resource.php:95 IDF/Wiki/ResourceRevision.php:101 +msgid "creation date" +msgstr "oluşturulma tarihi" + +#: IDF/Commit.php:238 +#, php-format +msgid "Commit %1$s, by %2$s" +msgstr "" + +#: IDF/Commit.php:337 +#, php-format +msgid "New Commit %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Conf.php:61 IDF/Gconf.php:73 +msgid "key" +msgstr "anahtar" + +#: IDF/Conf.php:67 IDF/Gconf.php:79 IDF/ProjectActivity.php:62 +msgid "value" +msgstr "değer" + +#: IDF/Diff.php:460 +msgid "Old" +msgstr "" + +#: IDF/Diff.php:460 +msgid "New" +msgstr "" + +#: IDF/EmailAddress.php:49 IDF/Key.php:49 +msgid "user" +msgstr "kullanıcı" + +#: IDF/EmailAddress.php:55 +msgid "email" +msgstr "" + +#: IDF/Form/Admin/ForgeConf.php:34 +msgid "Custom forge page enabled" +msgstr "" + +#: IDF/Form/Admin/ForgeConf.php:39 IDF/Form/WikiPageCreate.php:80 +#: IDF/Form/WikiPageUpdate.php:72 +msgid "Content" +msgstr "" + +#: IDF/Form/Admin/LabelConf.php:40 +msgid "Predefined project labels" +msgstr "" + +#: IDF/Form/Admin/LabelConf.php:55 +#, php-format +msgid "" +"The label \"%s\" is invalid: A label must only consist of alphanumeric " +"characters and dashes, and can optionally contain a \":\" with a group " +"prefix." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:38 IDF/Views/Project.php:600 +msgid "git" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:39 IDF/Views/Project.php:601 +msgid "Subversion" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:40 IDF/Views/Project.php:602 +msgid "mercurial" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:41 IDF/Views/Project.php:603 +msgid "monotone" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:49 IDF/Form/Admin/ProjectUpdate.php:44 +#: IDF/Form/ProjectConf.php:39 IDF/Views/Admin.php:86 IDF/Views/Admin.php:273 +msgid "Name" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:55 IDF/Form/TabsConf.php:101 +#: IDF/gettexttemplates/idf/base-full.html.php:5 +#: IDF/gettexttemplates/idf/base-full.html~.php:5 +#: IDF/gettexttemplates/idf/base.html.php:5 +#: IDF/gettexttemplates/idf/base.html~.php:5 +#: IDF/gettexttemplates/idf/main-menu.html.php:9 +#: IDF/gettexttemplates/idf/project-list.html.php:5 +#: IDF/gettexttemplates/idf/project-list.html.php:7 +msgid "Private project" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:62 +msgid "Shortname" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:64 +msgid "" +"It must be unique for each project and composed only of letters, digits and " +"dash (-) like \"my-project\"." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:69 IDF/Form/Admin/ProjectUpdate.php:50 +msgid "Short description" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:70 IDF/Form/Admin/ProjectUpdate.php:51 +#: IDF/Project.php:79 +msgid "A one line description of the project." +msgstr "Projenin tek satırlık tanımı." + +#: IDF/Form/Admin/ProjectCreate.php:77 IDF/Form/Admin/ProjectUpdate.php:58 +#: IDF/Form/ProjectConf.php:56 +msgid "External URL" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:84 +msgid "Repository type" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:92 +msgid "Remote Subversion repository" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:99 IDF/Form/SourceConf.php:40 +msgid "Repository username" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:106 IDF/Form/SourceConf.php:47 +msgid "Repository password" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:113 IDF/Form/Admin/ProjectUpdate.php:66 +msgid "Master branch" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:116 IDF/Form/Admin/ProjectUpdate.php:69 +msgid "" +"This should be a world-wide unique identifier for your project. A reverse " +"DNS notation like \"com.my-domain.my-project\" is a good idea." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:121 IDF/Form/Admin/ProjectUpdate.php:95 +#: IDF/Form/MembersConf.php:46 IDF/Form/TabsConf.php:53 +#: IDF/Form/TabsConf.php:72 +msgid "Project owners" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:130 IDF/Form/Admin/ProjectUpdate.php:103 +#: IDF/Form/MembersConf.php:54 IDF/Form/TabsConf.php:52 +#: IDF/Form/TabsConf.php:78 +msgid "Project members" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:140 IDF/Form/Admin/ProjectUpdate.php:85 +#: IDF/Form/IssueCreate.php:168 IDF/Form/IssueUpdate.php:164 +#: IDF/Form/ProjectConf.php:73 IDF/Form/UpdateUpload.php:71 +#: IDF/Form/Upload.php:70 IDF/Form/WikiPageCreate.php:93 +#: IDF/Form/WikiPageUpdate.php:104 +msgid "Labels" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:155 +msgid "Project template" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:157 +msgid "" +"Use the given project to initialize the new project. Access rights and " +"general configuration will be taken from the template project." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:204 +msgid "" +"Only a remote repository available through HTTP or HTTPS is allowed. For " +"example \"http://somewhere.com/svn/trunk\"." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:220 IDF/Form/Admin/ProjectUpdate.php:117 +msgid "" +"The master branch is empty or contains illegal characters, please use only " +"letters, digits, dashes and dots as separators." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:230 IDF/Form/Admin/ProjectUpdate.php:128 +msgid "This master branch is already used. Please select another one." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:241 +msgid "" +"This shortname contains illegal characters, please use only letters, digits " +"and dash (-)." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:244 +msgid "The shortname cannot start with the dash (-) character." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:247 +msgid "The shortname cannot end with the dash (-) character." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:252 +msgid "This shortname is already used. Please select another one." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:303 IDF/Form/Admin/ProjectDelete.php:78 +#: IDF/Form/Admin/ProjectUpdate.php:153 IDF/Form/Admin/UserCreate.php:106 +#: IDF/Form/Admin/UserUpdate.php:191 IDF/Form/IssueCreate.php:338 +#: IDF/Form/IssueUpdate.php:329 IDF/Form/MembersConf.php:64 +#: IDF/Form/Password.php:76 IDF/Form/Register.php:112 +#: IDF/Form/ReviewCreate.php:187 IDF/Form/ReviewFileComment.php:143 +#: IDF/Form/TabsConf.php:122 IDF/Form/UpdateUpload.php:126 +#: IDF/Form/Upload.php:149 IDF/Form/UploadArchive.php:137 +#: IDF/Form/UserAccount.php:216 IDF/Form/UserChangeEmail.php:80 +#: IDF/Form/WikiPageCreate.php:167 IDF/Form/WikiPageDelete.php:59 +#: IDF/Form/WikiPageUpdate.php:178 IDF/Form/WikiResourceCreate.php:123 +#: IDF/Form/WikiResourceDelete.php:59 IDF/Form/WikiResourceUpdate.php:124 +msgid "Cannot save the model from an invalid form." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:341 +msgid "" +"Click on the Project Management tab to set the description of your project." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:426 +msgid "This project is not available." +msgstr "" + +#: IDF/Form/Admin/ProjectDelete.php:41 +msgid "Confirmation code" +msgstr "" + +#: IDF/Form/Admin/ProjectDelete.php:46 +msgid "I have made a backup of all the important data of this project." +msgstr "" + +#: IDF/Form/Admin/ProjectDelete.php:55 +msgid "" +"The confirmation code does not match. Please provide a valid confirmation " +"code to delete the project." +msgstr "" + +#: IDF/Form/Admin/ProjectDelete.php:63 +msgid "Sorry, you really need to backup your data before deletion." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:37 IDF/Form/Admin/UserUpdate.php:38 +#: IDF/Form/RegisterConfirmation.php:50 IDF/Form/UserAccount.php:40 +msgid "First name" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:46 IDF/Form/Admin/UserUpdate.php:47 +#: IDF/Form/RegisterConfirmation.php:59 IDF/Form/UserAccount.php:49 +msgid "Last name" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:56 +msgid "Login" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:60 +msgid "" +"The login must be between 3 and 15 characters long and contains only letters " +"and digits." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:69 IDF/Form/Admin/UserUpdate.php:57 +msgid "Email" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:71 +msgid "" +"Double check the email address as the password is sent directly to the user." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:76 IDF/Form/Admin/UserUpdate.php:67 +#: IDF/Form/UserAccount.php:66 +msgid "Language" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:87 IDF/Form/UserAccount.php:161 +msgid "Add a public key" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:92 +msgid "" +"Paste a SSH or monotone public key. Be careful to not provide your private " +"key here!" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:157 +msgid "Your details to access your forge." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:189 IDF/Form/UserAccount.php:429 +#: IDF/Form/UserAccount.php:438 +#, php-format +msgid "The email \"%s\" is already used." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:198 IDF/Form/Register.php:72 +#, php-format +msgid "The login \"%s\" can only contain letters and digits." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:203 IDF/Form/Register.php:77 +#, php-format +msgid "The login \"%s\" is already used, please find another one." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:78 +msgid "Password" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:81 +msgid "Leave blank if you do not want to change the password." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:81 +msgid "" +"The password must be hard for other people to guess, but easy for the user " +"to remember." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:89 +msgid "Confirm password" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:100 IDF/Form/IssueCreate.php:66 +#: IDF/Form/ProjectConf.php:48 IDF/Form/ReviewCreate.php:54 +#: IDF/Form/UpdateUpload.php:51 IDF/Form/Upload.php:49 +#: IDF/Form/UserAccount.php:101 IDF/Form/WikiPageCreate.php:70 +#: IDF/Form/WikiPageUpdate.php:60 IDF/Form/WikiResourceCreate.php:54 +#: IDF/Form/WikiResourceUpdate.php:46 IDF/Views/Wiki.php:102 +msgid "Description" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:109 IDF/Form/UserAccount.php:110 +msgid "Twitter username" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:119 IDF/Form/UserAccount.php:120 +msgid "Public email address" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:129 IDF/Form/UserAccount.php:130 +msgid "Website URL" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:139 IDF/Form/UserAccount.php:140 +msgid "Upload custom avatar" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:146 IDF/Form/UserAccount.php:147 +msgid "" +"An image file with a width and height not larger than 60 pixels (bigger " +"images are scaled down)." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:151 IDF/Form/UserAccount.php:152 +msgid "Remove custom avatar" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:155 IDF/Form/UserAccount.php:156 +msgid "Tick this to delete the custom avatar." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:161 IDF/Views/Admin.php:274 +msgid "Staff" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:164 +msgid "If you give staff rights to a user, you really need to trust him." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:172 IDF/Views/Admin.php:276 +msgid "Active" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:176 +msgid "" +"If the user is not getting the confirmation email or is abusing the system, " +"you can directly enable or disable their account here." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:274 +msgid "--- is not a valid first name." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:290 +msgid "" +"A user with this email already exists, please provide another email address." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:301 IDF/Form/UserAccount.php:398 +msgid "For security reason, you cannot upload a file with this extension." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:316 IDF/Form/UserAccount.php:461 +msgid "The passwords do not match. Please give them again." +msgstr "" + +#: IDF/Form/Field/EmailList.php:45 +msgid "Please enter one or more valid email addresses." +msgstr "" + +#: IDF/Form/IssueCreate.php:57 IDF/Form/IssueUpdate.php:46 +#: IDF/Form/ReviewCreate.php:45 IDF/Form/ReviewFileComment.php:73 +#: IDF/Form/UpdateUpload.php:42 IDF/Form/Upload.php:40 +#: IDF/gettexttemplates/idf/issues/base.html.php:3 IDF/Views/Download.php:65 +#: IDF/Views/Download.php:347 IDF/Views/Issue.php:62 IDF/Views/Issue.php:221 +#: IDF/Views/Issue.php:302 IDF/Views/Issue.php:391 IDF/Views/Issue.php:543 +#: IDF/Views/Issue.php:766 IDF/Views/Issue.php:825 IDF/Views/Review.php:58 +#: IDF/Views/User.php:83 IDF/Views/Wiki.php:62 IDF/Views/Wiki.php:145 +#: IDF/Views/Wiki.php:186 +msgid "Summary" +msgstr "" + +#: IDF/Form/IssueCreate.php:76 IDF/Form/IssueUpdate.php:66 +#: IDF/Form/ReviewCreate.php:83 +msgid "The \"upload_issue_path\" configuration variable was not set." +msgstr "" + +#: IDF/Form/IssueCreate.php:86 IDF/Form/IssueUpdate.php:76 +msgid "Attach a file" +msgstr "" + +#: IDF/Form/IssueCreate.php:99 IDF/Form/IssueUpdate.php:89 +#: IDF/Form/ReviewCreate.php:103 IDF/Form/ReviewFileComment.php:83 +#: IDF/Views/Issue.php:63 IDF/Views/Issue.php:222 IDF/Views/Issue.php:304 +#: IDF/Views/Issue.php:392 IDF/Views/Issue.php:544 IDF/Views/Issue.php:767 +#: IDF/Views/Issue.php:826 IDF/Views/Review.php:59 IDF/Views/User.php:84 +msgid "Status" +msgstr "" + +#: IDF/Form/IssueCreate.php:108 IDF/Form/IssueUpdate.php:99 +msgid "Owner" +msgstr "" + +#: IDF/Form/IssueCreate.php:118 IDF/Form/IssueUpdate.php:112 +#: IDF/Form/IssueUpdate.php:129 +msgid "This issue" +msgstr "" + +#: IDF/Form/IssueCreate.php:210 +msgid "You cannot add a label with the \"Status\" prefix to an issue." +msgstr "" + +#: IDF/Form/IssueCreate.php:211 IDF/Form/IssueCreate.php:218 +#: IDF/Form/UpdateUpload.php:110 IDF/Form/Upload.php:121 +#: IDF/Form/WikiPageCreate.php:151 IDF/Form/WikiPageUpdate.php:162 +msgid "You provided an invalid label." +msgstr "" + +#: IDF/Form/IssueCreate.php:217 IDF/Form/UpdateUpload.php:109 +#, php-format +msgid "You cannot provide more than one label from the %s class to an issue." +msgstr "" + +#: IDF/Form/IssueCreate.php:228 IDF/Form/IssueUpdate.php:194 +msgid "You need to provide a description of the issue." +msgstr "" + +#: IDF/Form/IssueCreate.php:251 IDF/Form/ReviewCreate.php:159 +msgid "You provided an invalid status." +msgstr "" + +#: IDF/Form/IssueCreate.php:272 +msgid "You provided an invalid relation type." +msgstr "" + +#: IDF/Form/IssueCreate.php:294 +#, php-format +msgid "The value \"%s\" is not a valid issue id." +msgstr "" + +#: IDF/Form/IssueCreate.php:300 +#, php-format +msgid "The issue \"%s\" does not exist." +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:86 +msgid "is related to" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:87 +msgid "blocks" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:88 +msgid "is blocked by" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:89 +msgid "duplicates" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:90 +msgid "is duplicated by" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:97 +msgid "" +"Define an issue template to hint the reporter to provide certain information" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:106 +msgid "Open issue status values" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:114 +msgid "Closed issue status values" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:123 +msgid "Predefined issue labels" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:125 +msgid "" +"The first \"Type:\" and \"Priority:\" entries found in this list are " +"automatically chosen as defaults for new issues." +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:133 +msgid "Each issue may have at most one label with each of these classes." +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:140 +msgid "Issue relations" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:142 +msgid "" +"You can define bidirectional relations like \"is related to\" or \"blocks, " +"is blocked by\". For standard relations pre-configured translations exist, " +"new relations should however be defined in a language that is understood by " +"all project members." +msgstr "" + +#: IDF/Form/IssueUpdate.php:56 IDF/Form/ReviewFileComment.php:45 +#: IDF/Form/WikiPageUpdate.php:82 IDF/Form/WikiResourceUpdate.php:66 +msgid "Comment" +msgstr "" + +#: IDF/Form/IssueUpdate.php:316 +msgid "No changes were entered." +msgstr "" + +#: IDF/Form/MembersConf.php:104 +#, php-format +msgid "The following login is invalid: %s." +msgid_plural "The following logins are invalid: %s." +msgstr[0] "" + +#: IDF/Form/Password.php:34 +msgid "Your login or email" +msgstr "" + +#: IDF/Form/Password.php:35 +msgid "Provide either your login or your email to recover your password." +msgstr "" + +#: IDF/Form/Password.php:49 IDF/Form/Password.php:64 +msgid "" +"Sorry, we cannot find a user with this email address or login. Feel free to " +"try again." +msgstr "" + +#: IDF/Form/Password.php:100 +msgid "Password Recovery - InDefero" +msgstr "" + +#: IDF/Form/PasswordInputKey.php:36 IDF/Form/PasswordReset.php:39 +#: IDF/Form/UserChangeEmail.php:36 +msgid "Your verification key" +msgstr "" + +#: IDF/Form/PasswordInputKey.php:50 IDF/Form/PasswordReset.php:89 +msgid "" +"We are sorry but this validation key is not valid. Maybe you should directly " +"copy/paste it from your validation email." +msgstr "" + +#: IDF/Form/PasswordInputKey.php:61 IDF/Form/PasswordReset.php:100 +msgid "" +"Sorry, but this verification key has expired, please restart the password " +"recovery sequence. For security reasons, the verification key is only valid " +"24h." +msgstr "" + +#: IDF/Form/PasswordInputKey.php:76 IDF/Form/PasswordReset.php:108 +#: IDF/Form/RegisterConfirmation.php:137 IDF/Form/RegisterInputKey.php:72 +msgid "Cannot save an invalid form." +msgstr "" + +#: IDF/Form/PasswordReset.php:45 IDF/Form/RegisterConfirmation.php:69 +#: IDF/Form/UserAccount.php:77 +msgid "Your password" +msgstr "" + +#: IDF/Form/PasswordReset.php:48 IDF/Form/UserAccount.php:80 +msgid "" +"Your password must be hard for other people to find it, but easy for you to " +"remember." +msgstr "" + +#: IDF/Form/PasswordReset.php:56 IDF/Form/RegisterConfirmation.php:80 +#: IDF/Form/UserAccount.php:89 +msgid "Confirm your password" +msgstr "" + +#: IDF/Form/PasswordReset.php:74 IDF/Form/RegisterConfirmation.php:122 +msgid "The two passwords must be the same." +msgstr "" + +#: IDF/Form/PasswordReset.php:77 +msgid "" +"This account is not active. Please contact the forge administrator to " +"activate it." +msgstr "" + +#: IDF/Form/ProjectConf.php:43 +msgid "Short Description" +msgstr "" + +#: IDF/Form/ProjectConf.php:85 +msgid "The \"upload_path\" configuration variable was not set." +msgstr "" + +#: IDF/Form/ProjectConf.php:90 +msgid "Update the logo" +msgstr "" + +#: IDF/Form/ProjectConf.php:92 +msgid "The logo must be a picture with a size of 32 by 32." +msgstr "" + +#: IDF/Form/ProjectConf.php:103 +msgid "Remove the current logo" +msgstr "" + +#: IDF/Form/ProjectConf.php:139 +msgid "Could not determine the size of the uploaded picture." +msgstr "" + +#: IDF/Form/ProjectConf.php:143 +msgid "The picture must have a size of 32 by 32." +msgstr "" + +#: IDF/Form/ProjectConf.php:164 +msgid "The entered URL is invalid. Only http and https URLs are allowed." +msgstr "" + +#: IDF/Form/Register.php:41 +msgid "Your login" +msgstr "" + +#: IDF/Form/Register.php:45 +msgid "" +"The login must be between 3 and 15 characters long and contain only letters " +"and digits." +msgstr "" + +#: IDF/Form/Register.php:53 IDF/Form/UserAccount.php:59 +msgid "Your email" +msgstr "" + +#: IDF/Form/Register.php:55 +msgid "We will never send you any unsolicited emails. We hate spam too!" +msgstr "" + +#: IDF/Form/Register.php:60 +msgid "I agree to the terms and conditions." +msgstr "" + +#: IDF/Form/Register.php:88 +msgid "" +"We know, this is boring, but you need to agree with the terms and conditions." +msgstr "" + +#: IDF/Form/Register.php:97 +#, php-format +msgid "" +"The email \"%1$s\" is already used. If you need to, you can recover your password." +msgstr "" + +#: IDF/Form/Register.php:148 +msgid "Confirm the creation of your account." +msgstr "" + +#: IDF/Form/RegisterConfirmation.php:40 IDF/Form/RegisterInputKey.php:36 +msgid "Your confirmation key" +msgstr "" + +#: IDF/Form/RegisterConfirmation.php:72 +msgid "" +"Your password must be hard for other people to guess, but easy for you to " +"remember." +msgstr "" + +#: IDF/Form/RegisterConfirmation.php:99 IDF/Form/RegisterInputKey.php:50 +msgid "" +"We are sorry but this confirmation key is not valid. Maybe you should " +"directly copy/paste it from your confirmation email." +msgstr "" + +#: IDF/Form/RegisterConfirmation.php:110 +#, php-format +msgid "" +"This account has already been confirmed. Maybe should you try to recover your password." +msgstr "" + +#: IDF/Form/ReviewCreate.php:74 +#: IDF/gettexttemplates/idf/source/base.html.php:5 +#: IDF/gettexttemplates/idf/source/changelog.html.php:7 +msgid "Commit" +msgstr "" + +#: IDF/Form/ReviewCreate.php:92 +msgid "Patch" +msgstr "" + +#: IDF/Form/ReviewCreate.php:119 +msgid "We were not able to parse your patch. Please provide a valid patch." +msgstr "" + +#: IDF/Form/ReviewCreate.php:128 +msgid "You provided an invalid commit." +msgstr "" + +#: IDF/Form/ReviewCreate.php:202 +msgid "Initial patch to be reviewed." +msgstr "" + +#: IDF/Form/ReviewFileComment.php:56 +msgid "General comment" +msgstr "" + +#: IDF/Form/ReviewFileComment.php:113 +msgid "" +"You need to provide your general comment about the proposal, or comments on " +"at least one file." +msgstr "" + +#: IDF/Form/ReviewFileComment.php:124 +msgid "The status have been updated." +msgstr "" + +#: IDF/Form/ReviewFileComment.php:130 +msgid "This field is required." +msgstr "" + +#: IDF/Form/SourceConf.php:54 IDF/Form/UploadConf.php:70 +msgid "Webhook URL" +msgstr "" + +#: IDF/Form/TabsConf.php:38 IDF/gettexttemplates/idf/admin/base.html.php:4 +#: IDF/gettexttemplates/idf/base-full.html.php:8 +#: IDF/gettexttemplates/idf/base-full.html~.php:7 +#: IDF/gettexttemplates/idf/base.html.php:8 +#: IDF/gettexttemplates/idf/base.html~.php:7 +#: IDF/gettexttemplates/idf/downloads/base.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:14 +#: IDF/Views/Project.php:97 +msgid "Downloads" +msgstr "" + +#: IDF/Form/TabsConf.php:39 IDF/gettexttemplates/idf/base-full.html.php:12 +#: IDF/gettexttemplates/idf/base-full.html~.php:11 +#: IDF/gettexttemplates/idf/base.html.php:12 +#: IDF/gettexttemplates/idf/base.html~.php:11 +msgid "Code Review" +msgstr "" + +#: IDF/Form/TabsConf.php:40 IDF/gettexttemplates/idf/admin/base.html.php:5 +#: IDF/gettexttemplates/idf/base-full.html.php:9 +#: IDF/gettexttemplates/idf/base-full.html~.php:8 +#: IDF/gettexttemplates/idf/base.html.php:9 +#: IDF/gettexttemplates/idf/base.html~.php:8 +msgid "Documentation" +msgstr "" + +#: IDF/Form/TabsConf.php:41 IDF/gettexttemplates/idf/admin/base.html.php:7 +#: IDF/gettexttemplates/idf/base-full.html.php:11 +#: IDF/gettexttemplates/idf/base-full.html~.php:10 +#: IDF/gettexttemplates/idf/base.html.php:11 +#: IDF/gettexttemplates/idf/base.html~.php:10 +msgid "Source" +msgstr "" + +#: IDF/Form/TabsConf.php:42 IDF/gettexttemplates/idf/base-full.html.php:10 +#: IDF/gettexttemplates/idf/base-full.html~.php:9 +#: IDF/gettexttemplates/idf/base.html.php:10 +#: IDF/gettexttemplates/idf/base.html~.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:17 +msgid "Issues" +msgstr "" + +#: IDF/Form/TabsConf.php:50 +msgid "Open to all" +msgstr "" + +#: IDF/Form/TabsConf.php:51 +msgid "Signed in users" +msgstr "" + +#: IDF/Form/TabsConf.php:54 +msgid "Closed" +msgstr "" + +#: IDF/Form/TabsConf.php:84 +#, fuzzy +msgid "Others" +msgstr "Diğer" + +#: IDF/Form/TabsConf.php:107 +msgid "Extra authorized users" +msgstr "" + +#: IDF/Form/Upload.php:59 IDF/Form/WikiResourceCreate.php:65 +#: IDF/Form/WikiResourceUpdate.php:56 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:7 +#: IDF/Views/Download.php:64 IDF/Views/Download.php:346 +msgid "File" +msgstr "" + +#: IDF/Form/Upload.php:87 IDF/Form/WikiResourceCreate.php:96 +#: IDF/Form/WikiResourceUpdate.php:83 +msgid "For security reasons, you cannot upload a file with this extension." +msgstr "" + +#: IDF/Form/Upload.php:120 +#, php-format +msgid "You cannot provide more than one label from the %s class to a download." +msgstr "" + +#: IDF/Form/UploadArchive.php:41 +#, fuzzy +msgid "Archive file" +msgstr "Arşiv" + +#: IDF/Form/UploadArchive.php:67 +#, php-format +msgid "" +"For security reasons, you cannot upload a file (%s) with this extension." +msgstr "" + +#: IDF/Form/UploadArchive.php:98 +#, php-format +msgid "" +"You cannot provide more than label from the %1$s class to a download (%2$s)." +msgstr "" + +#: IDF/Form/UploadArchive.php:109 +#, php-format +msgid "" +"A file with the name \"%s\" has already been uploaded and is not marked to " +"be replaced." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:41 +msgid "The archive does not exist." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:48 +#, php-format +msgid "The archive could not be read (code %d)." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:53 +msgid "The archive does not contain a manifest.xml." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:61 +#, php-format +msgid "The archive's manifest is invalid: %s" +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:77 +#, php-format +msgid "The entry %d in the manifest is missing a file name." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:82 +#, php-format +msgid "The entry %d in the manifest is missing a summary." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:86 +msgid "The manifest must not reference itself." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:91 +#, php-format +msgid "The entry %s in the manifest does not exist in the archive." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:96 +#, php-format +msgid "The entry %s in the manifest is referenced more than once." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:108 +#, php-format +msgid "The entry %s in the manifest has more than the six allowed labels set." +msgstr "" + +#: IDF/Form/UploadConf.php:53 +msgid "Predefined download labels" +msgstr "" + +#: IDF/Form/UploadConf.php:62 +msgid "Each download may have at most one label with each of these classes" +msgstr "" + +#: IDF/Form/UserAccount.php:61 +msgid "" +"If you change your email address, an email will be sent to the new address " +"to confirm it." +msgstr "" + +#: IDF/Form/UserAccount.php:80 +msgid "Leave blank if you do not want to change your password." +msgstr "" + +#: IDF/Form/UserAccount.php:166 +msgid "" +"Paste an SSH or monotone public key. Be careful to not provide your private " +"key here!" +msgstr "" + +#: IDF/Form/UserAccount.php:171 +msgid "Add a secondary email address" +msgstr "" + +#: IDF/Form/UserAccount.php:173 +msgid "You will get an email to confirm that you own the address you specify." +msgstr "" + +#: IDF/Form/UserAccount.php:200 +msgid "Confirm your new email address." +msgstr "" + +#: IDF/Form/UserAccount.php:203 +#, php-format +msgid "" +"A validation email has been sent to \"%s\" to validate the email address " +"change." +msgstr "" + +#: IDF/Form/UserAccount.php:341 +msgid "" +"Please check the key as it does not appear to be a valid SSH public key." +msgstr "" + +#: IDF/Form/UserAccount.php:363 +msgid "" +"Please check the key as it does not appear to be a valid monotone public key." +msgstr "" + +#: IDF/Form/UserAccount.php:371 +msgid "Public key looks like neither an SSH nor monotone public key." +msgstr "" + +#: IDF/Form/UserAccount.php:383 +msgid "You already have uploaded this key." +msgstr "" + +#: IDF/Form/UserChangeEmail.php:63 +msgid "" +"The validation key is not valid. Please copy/paste it from your confirmation " +"email." +msgstr "" + +#: IDF/Form/WikiConf.php:49 +msgid "Predefined documentation page labels" +msgstr "" + +#: IDF/Form/WikiConf.php:58 +msgid "" +"Each documentation page may have at most one label with each of these classes" +msgstr "" + +#: IDF/Form/WikiPageCreate.php:38 +msgid "" +"# Introduction\n" +"\n" +"Add your content here.\n" +"\n" +"\n" +"# Details\n" +"\n" +"Add your content here. Format your content with:\n" +"\n" +"* Text in **bold** or *italic*.\n" +"* Headings, paragraphs, and lists.\n" +"* Links to other [[WikiPage]].\n" +msgstr "" + +#: IDF/Form/WikiPageCreate.php:57 +msgid "PageName" +msgstr "" + +#: IDF/Form/WikiPageCreate.php:60 IDF/Form/WikiPageUpdate.php:50 +msgid "Page title" +msgstr "" + +#: IDF/Form/WikiPageCreate.php:66 IDF/Form/WikiPageUpdate.php:56 +msgid "" +"The page name must contains only letters, digits and the dash (-) character." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:71 IDF/Form/WikiPageUpdate.php:61 +msgid "This one line description is displayed in the list of pages." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:108 IDF/Form/WikiPageUpdate.php:119 +#: IDF/Form/WikiResourceCreate.php:78 +msgid "The title contains invalid characters." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:114 IDF/Form/WikiPageUpdate.php:125 +msgid "A page with this title already exists." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:150 IDF/Form/WikiPageUpdate.php:161 +#, php-format +msgid "You cannot provide more than one label from the %s class to a page." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:200 +msgid "Initial page creation" +msgstr "" + +#: IDF/Form/WikiPageDelete.php:39 +msgid "Yes, I understand that the page and all its revisions will be deleted." +msgstr "" + +#: IDF/Form/WikiPageDelete.php:50 IDF/Form/WikiResourceDelete.php:50 +msgid "You need to confirm the deletion." +msgstr "" + +#: IDF/Form/WikiPageUpdate.php:83 IDF/Form/WikiResourceUpdate.php:67 +msgid "One line to describe the changes you made." +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:40 +msgid "ResourceName" +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:44 +msgid "Resource title" +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:50 +msgid "" +"The resource name must contains only letters, digits and the dash (-) " +"character." +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:55 IDF/Form/WikiResourceUpdate.php:47 +#, fuzzy +msgid "This one line description is displayed in the list of resources." +msgstr "Projenin tek satırlık tanımı." + +#: IDF/Form/WikiResourceCreate.php:84 +msgid "A resource with this title already exists." +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:142 +msgid "Initial resource creation" +msgstr "" + +#: IDF/Form/WikiResourceDelete.php:39 +msgid "" +"Yes, I understand that the resource and all its revisions will be deleted." +msgstr "" + +#: IDF/Form/WikiResourceUpdate.php:89 +#, php-format +msgid "" +"The mime type of the uploaded file \"%1$s\" does not match the mime type of " +"this resource \"%2$s\"" +msgstr "" + +#: IDF/Form/WikiResourceUpdate.php:97 +msgid "The current version of the resource and the uploaded file are equal." +msgstr "" + +#: IDF/Gconf.php:60 IDF/Search/Occ.php:56 +msgid "model class" +msgstr "" + +#: IDF/Gconf.php:66 IDF/Search/Occ.php:62 +msgid "model id" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/base.html.php:3 +msgid "Project Summary" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/base.html.php:6 +msgid "Issue Tracking" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/base.html.php:8 +msgid "Project Members" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/base.html.php:9 +msgid "Tabs Access and Notifications" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:3 +#: IDF/gettexttemplates/idf/admin/issue-tracking.html.php:3 +#: IDF/gettexttemplates/idf/admin/wiki.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/labels.html.php:3 +msgid "" +"\n" +"

Instructions:

\n" +"

List one status value per line in desired sort-order.

\n" +"

Optionally, use an equals-sign to document the meaning of each status " +"value.

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:8 +msgid "" +"

The webhook URL setting specifies an URL to which a HTTP PUT\n" +"request is sent after a new download has been added or to which a HTTP " +"POST\n" +"request is sent after an existing download has been updated.\n" +"If this field is empty, notifications are disabled.

\n" +"\n" +"

Only properly-escaped HTTP URLs are supported, for " +"example:

\n" +"\n" +"
    \n" +"
  • http://domain.com/upload
  • \n" +"
  • http://domain.com/upload?my%20param
  • \n" +"
\n" +"\n" +"

In addition, the URL may contain the following \"%\" notation, which\n" +"will be replaced with specific project values for each download:

\n" +"\n" +"
    \n" +"
  • %p - project name
  • \n" +"
  • %d - download id
  • \n" +"
\n" +"\n" +"

For example, updating download 123 of project 'my-project' with\n" +"web hook URL http://mydomain.com/%p/%d would send a POST " +"request to\n" +"http://mydomain.com/my-project/123.

" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:31 +#: IDF/gettexttemplates/idf/admin/source.html.php:30 +msgid "Web-Hook authentication key:" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:32 +#: IDF/gettexttemplates/idf/admin/issue-tracking.html.php:8 +#: IDF/gettexttemplates/idf/admin/members.html.php:13 +#: IDF/gettexttemplates/idf/admin/source.html.php:31 +#: IDF/gettexttemplates/idf/admin/summary.html.php:11 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:12 +#: IDF/gettexttemplates/idf/admin/wiki.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/forge/index.html.php:13 +#: IDF/gettexttemplates/idf/gadmin/projects/labels.html.php:8 +msgid "Save Changes" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/members.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:3 +msgid "" +"\n" +"

Instructions:

\n" +"

Specify each person by its login. Each person must have already " +"registered with the given login.

\n" +"

Separate the logins with commas and/or new lines.

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/members.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:8 +msgid "" +"\n" +"

Notes:

\n" +"

A project owner may make any change to this project, including removing " +"other project owners. You need to be carefull when you give owner rights.\n" +"

A project member will not have access to the administration area but will " +"have more options available in the use of the project.

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:3 +msgid "You can find here the current repository configuration of your project." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:4 +msgid "" +"

The webhook URL setting specifies an URL to which a HTTP \n" +"%%hook_request_method%% request is sent after each " +"repository\n" +"commit. If this field is empty, notifications are disabled.

\n" +"\n" +"

Only properly-escaped HTTP URLs are supported, for " +"example:

\n" +"\n" +"
    \n" +"
  • http://domain.com/commit
  • \n" +"
  • http://domain.com/commit?my%20param
  • \n" +"
\n" +"\n" +"

In addition, the URL may contain the following \"%\" notation, which\n" +"will be replaced with specific project values for each commit:

\n" +"\n" +"
    \n" +"
  • %p - project name
  • \n" +"
  • %r - revision number
  • \n" +"
\n" +"\n" +"

For example, committing revision 123 to project 'my-project' with\n" +"post-commit URL http://mydomain.com/%p/%r would send a request " +"to\n" +"http://mydomain.com/my-project/123.

" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:26 +msgid "" +"The form contains some errors. Please correct them to update the source " +"configuration." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:27 +msgid "Repository type:" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:28 +msgid "Repository access:" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:29 +msgid "Repository size:" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

The description of the project can be improved using the Markdown syntax.

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:7 +msgid "" +"The form contains some errors. Please correct them to update the summary." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:8 +msgid "Current logo" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:9 +#: IDF/gettexttemplates/idf/base-full.html.php:4 +#: IDF/gettexttemplates/idf/base-full.html~.php:4 +#: IDF/gettexttemplates/idf/base.html.php:4 +#: IDF/gettexttemplates/idf/base.html~.php:4 +#: IDF/gettexttemplates/idf/main-menu.html.php:8 +#: IDF/gettexttemplates/idf/project-list.html.php:4 +msgid "Project logo" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:10 +msgid "Your project does not have a logo configured yet." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:3 +msgid "" +"This section allows you to configure project tabs access rights and " +"notifications." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:4 +msgid "" +"Tab access controls whether a single user can navigate into a particular " +"section of your project via the main menu or automatically generated object " +"links." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:5 +msgid "" +"If you mark a project as private, only the project members and " +"administrators, together with the extra authorized users you provide will " +"have access to the project as a whole. You will still be able to define " +"further access rights for the different tabs but the \"Open to all\" and " +"\"Signed in users\" will default to authorized users only." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:6 +msgid "" +"For the extra authorized user list, specify each person by its login. Each " +"person must have already registered with the given login. Separate the " +"logins with commas and/or new lines." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:7 +msgid "" +"Only project members and admins have write access to the source. If you " +"restrict the access to the source, anonymous access is not provided and the " +"users must authenticate themselves with their password or SSH key." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:8 +#, php-format +msgid "" +"Here you can configure who should be notified about changes in a particular " +"section. You can also configure additional addresses, like the one of a " +"mailing list, that should be notified. (Keep in mind that you might have to " +"register the sender address %%from_email%% to let the " +"mailing list actually accept notification emails.) Multiple email addresses " +"must be separated through commas (',')." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:9 +msgid "" +"The form contains some errors. Please correct them to update the access " +"rights." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:10 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:13 +msgid "Access Rights" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:11 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:14 +#, fuzzy +msgid "Notifications" +msgstr "düzenlenme tarihi" + +#: IDF/gettexttemplates/idf/base-full.html.php:3 +#: IDF/gettexttemplates/idf/base-full.html~.php:3 +#: IDF/gettexttemplates/idf/base.html.php:3 +#: IDF/gettexttemplates/idf/base.html~.php:3 +#, php-format +msgid "" +"Sign in or create your account to create issues or " +"add comments" +msgstr "" + +#: IDF/gettexttemplates/idf/base-full.html.php:6 +#: IDF/gettexttemplates/idf/base.html.php:6 +#: IDF/gettexttemplates/idf/project-list.html.php:6 +msgid "External link to project" +msgstr "" + +#: IDF/gettexttemplates/idf/base-full.html.php:7 +#: IDF/gettexttemplates/idf/base-full.html~.php:6 +#: IDF/gettexttemplates/idf/base.html.php:7 +#: IDF/gettexttemplates/idf/base.html~.php:6 +msgid "Project Home" +msgstr "" + +#: IDF/gettexttemplates/idf/base-full.html.php:13 +#: IDF/gettexttemplates/idf/base-full.html~.php:12 +#: IDF/gettexttemplates/idf/base.html.php:13 +#: IDF/gettexttemplates/idf/base.html~.php:12 +msgid "Project Management" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/base.html.php:4 +#: IDF/gettexttemplates/idf/downloads/index.html.php:4 +#: IDF/Views/Download.php:235 +msgid "New Download" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/base.html.php:5 +#, fuzzy +msgid "Upload Archive" +msgstr "Arşiv" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:3 +msgid "" +"Each file must have a distinct name and file contents\n" +"cannot be changed, so be sure to include release numbers in each file\n" +"name." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:6 +#, php-format +msgid "" +"You can use the Markdown syntax for the description." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:7 +msgid "The form contains some errors. Please correct them to submit the file." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:8 +msgid "Submit File" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:9 +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:8 +#: IDF/gettexttemplates/idf/downloads/delete.html.php:7 +#: IDF/gettexttemplates/idf/downloads/view.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:21 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:14 +#: IDF/gettexttemplates/idf/issues/create.html.php:14 +#: IDF/gettexttemplates/idf/issues/view.html.php:27 +#: IDF/gettexttemplates/idf/register/confirmation.html.php:7 +#: IDF/gettexttemplates/idf/register/index.html.php:8 +#: IDF/gettexttemplates/idf/register/inputkey.html.php:5 +#: IDF/gettexttemplates/idf/review/create.html.php:12 +#: IDF/gettexttemplates/idf/review/view.html.php:41 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:5 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:13 +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:7 +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:9 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:5 +msgid "Cancel" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:10 +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:9 +#: IDF/gettexttemplates/idf/register/inputkey.html.php:6 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:6 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:6 +msgid "Instructions" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:3 +msgid "" +"The archive must include a manifest.xml file with meta " +"information about the\n" +"files to process inside the archive. All processed files must be unique or " +"replace existing files explicitely." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:5 +#, php-format +msgid "" +"You can learn more about the archive format here." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:6 +msgid "" +"The form contains some errors. Please correct them to submit the archive." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:7 +#, fuzzy +msgid "Submit Archive" +msgstr "Arşiv" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:3 +msgid "" +"Attention! If you want to delete a specific version of your " +"software, maybe, someone is depending on this specific version to run his " +"systems. Are you sure, you will not affect anybody when removing this file?" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:4 +#, php-format +msgid "" +"Instead of deleting the file, you could mark it as " +"deprecated." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:5 +#: IDF/gettexttemplates/idf/downloads/view.html.php:4 +#: IDF/gettexttemplates/idf/issues/attachment.html.php:4 +#: IDF/gettexttemplates/idf/issues/view.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:5 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:7 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:7 +#, php-format +msgid "by %%submitter%%" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:6 +msgid "Delete File" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:8 +#: IDF/gettexttemplates/idf/downloads/view.html.php:14 +msgid "Uploaded:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:9 +#: IDF/gettexttemplates/idf/downloads/view.html.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:29 +#: IDF/gettexttemplates/idf/review/view.html.php:27 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:12 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:14 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:14 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:15 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:17 +msgid "Updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:10 +#: IDF/gettexttemplates/idf/downloads/view.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:6 +#: IDF/gettexttemplates/idf/listProjects.html.php:17 +msgid "Downloads:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:11 +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:7 +#: IDF/gettexttemplates/idf/downloads/view.html.php:17 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:6 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:6 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:11 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:16 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:10 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:21 +#: IDF/gettexttemplates/idf/issues/view.html.php:33 +#: IDF/gettexttemplates/idf/project-list.html.php:8 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:6 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:13 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:16 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:12 +#: IDF/IssueComment.php:157 IDF/Wiki/PageRevision.php:204 +msgid "Labels:" +msgstr "Etiketler:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:3 +msgid "A new file is available for download:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:4 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:6 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:5 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:8 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:4 +msgid "Hello," +msgstr "Merhaba," + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:6 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:5 +msgid "Project:" +msgstr "Proje:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:6 +msgid "Submitted by:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:8 +msgid "Download:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/view.html.php:31 +#: IDF/gettexttemplates/idf/user/public.html.php:4 +msgid "Description:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:3 +msgid "A file download was updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/feedfragment.xml.php:3 +msgid "Details" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/index.html.php:3 +#, php-format +msgid "See the deprecated files." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/index.html.php:5 +msgid "Number of files:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:3 +msgid "" +"Attention! This file is marked as deprecated, download it " +"only if you are sure you need this specific version." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:5 +msgid "md5:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:6 +msgid "Changes" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:7 +msgid "The form contains some errors. Please correct them to update the file." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:8 +msgid "Update File" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:10 +#: IDF/gettexttemplates/idf/downloads/view.html.php:12 +msgid "Remove this file" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:11 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:18 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:7 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:12 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:12 +msgid "Trash" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:13 +msgid "Delete this file" +msgstr "" + +#: IDF/gettexttemplates/idf/faq-api.html.php:3 +#: IDF/gettexttemplates/idf/faq-archive-format.html.php:3 +#: IDF/gettexttemplates/idf/faq.html.php:65 +msgid "Here we are, just to help you." +msgstr "" + +#: IDF/gettexttemplates/idf/faq-api.html.php:4 +#: IDF/gettexttemplates/idf/faq-archive-format.html.php:4 +#: IDF/gettexttemplates/idf/faq.html.php:66 +#: IDF/gettexttemplates/idf/gadmin/base.html.php:4 +#: IDF/gettexttemplates/idf/index.html.php:4 IDF/Views/Admin.php:77 +#: IDF/Views.php:91 +msgid "Projects" +msgstr "Projeler" + +#: IDF/gettexttemplates/idf/faq.html.php:3 +msgid "" +"

This is simple:

\n" +"
    \n" +"
  1. Write in the comments \"This is a duplicate of issue 123\" or - if you " +"are a member of the crew -\n" +"directly add the \"duplicates\" relation with the value \"123\" below the " +"comment field. Change \"123\"\n" +"with the corresponding issue number.
  2. \n" +"
  3. Change the status of the current issue to Duplicate.
  4. \n" +"
  5. Submit the changes.
  6. \n" +"
" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:11 +msgid "" +"You need to create an account on Gravatar, this takes about 5 minutes and is free." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:12 +msgid "" +"\n" +"

To embed any previously uploaded resource into your wiki page, you can " +"use the [[!ResourceName]] syntax.

\n" +"\n" +"

The rendering of the resource can then be further fine-tuned:\n" +"

    \n" +"
  • [[!ImageResource, align=right, width=200]] renders " +"\"ImageResource\" right-aligned and scale its width to 200
  • \n" +"
  • [[!TextResource, align=center, width=300, height=300]] " +"renders \"TextResource\" in a centered, 300 by 300 px iframe
  • \n" +"
  • [[!AnyResource, preview=no]] does not render a preview of " +"the resource, but only provides a download link (default for binary " +"resources)
  • \n" +"
  • [[!BinaryResource, title=Download]] renders the download " +"link of \"BinaryResource\" with an alternative title
  • \n" +"
\n" +"

\n" +"\n" +"Resources are versioned, just like wiki pages. If you update a resource, old " +"wiki pages still show the state of the resource\n" +"at the time when the wiki page was edited. If you specifically want to " +"update a resource on a page, you therefor need to update\n" +"the resource at first and then also the page where it is referenced, " +"otherwise the change won't be visible until the next regular edit. \n" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:28 +msgid "" +"

If you have to publish many files at once for a new release, it is a very " +"tedious task\n" +"to upload them one after another and enter meta information like a summary, " +"a description or additional\n" +"labels for each of them.

\n" +"

InDefero therefore supports a special archive format that is basically a " +"standard zip file which comes with\n" +"some meta information. These meta information are kept in a special manifest " +"file, which is distinctly kept from\n" +"the rest of the files in the archive that should be published.

\n" +"

Once this archive has been uploaded, InDefero reads in the meta " +"information, unpacks the other files from\n" +"the archive and creates new individual downloads for each of them.

" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:36 +#, php-format +msgid "Learn more about the archive format." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:37 +msgid "" +"The API (Application Programming Interface) is used to interact with " +"InDefero with another program. For example, this can be used to create a " +"desktop program to submit new tickets easily." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:38 +#, php-format +msgid "Learn more about the API." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:39 +#: IDF/gettexttemplates/idf/faq.html.php:45 +msgid "What are the keyboard shortcuts?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:40 +#: IDF/gettexttemplates/idf/faq.html.php:60 +msgid "How to mark an issue as duplicate?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:41 +#: IDF/gettexttemplates/idf/faq.html.php:61 +msgid "How can I display my head next to my comments?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:42 +#: IDF/gettexttemplates/idf/faq.html.php:62 +msgid "How can I embed images and other resources in my documentation pages?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:43 +#: IDF/gettexttemplates/idf/faq.html.php:63 +msgid "What is this \"Upload Archive\" functionality about?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:44 +#: IDF/gettexttemplates/idf/faq.html.php:64 +msgid "What is the API and how is it used?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:46 +msgid "Shift+h: This help page." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:47 +msgid "If you are in a project, you have the following shortcuts:" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:48 +msgid "Shift+u: Project updates." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:49 +msgid "Shift+d: Downloads." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:50 +msgid "Shift+o: Documentation." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:51 +msgid "Shift+a: Create a new issue." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:52 +msgid "Shift+i: List of open issues." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:53 +msgid "Shift+m: The issues you submitted." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:54 +msgid "Shift+w: The issues assigned to you." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:55 +msgid "Shift+s: Source." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:56 +msgid "You also have the standard access keys:" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:57 +msgid "Alt+1: Home." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:58 +msgid "Alt+2: Skip the menus." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:59 +msgid "Alt+4: Search (when available)." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:3 +msgid "Forge" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:5 +msgid "People" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:6 +msgid "Usher" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/forge/base.html.php:3 +#, fuzzy +msgid "Frontpage" +msgstr "sayfa" + +#: IDF/gettexttemplates/idf/gadmin/forge/index.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

You can set up a custom forge page that is used as entry page for the " +"forge instead of the plain project listing. This page is then also " +"accessible via the 'Home' link in main menu bar.

\n" +"

The content of the page can use the Markdown syntax with the Extra extension.

\n" +"

Additionally, the following macros are available:
\n" +"

    \n" +"
  • {projectlist, label=..., order=(name|activity), limit=...} - Renders a project list that can optionally be filtered by label, " +"ordered by 'name' or 'activity' and / or limited to a specific number of " +"projects.
  • \n" +"
\n" +"

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:3 +#: IDF/gettexttemplates/idf/main-menu.html.php:7 +msgid "Project List" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:4 +#: IDF/Views/Admin.php:110 +#, fuzzy +msgid "Project Labels" +msgstr "Projeler" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:16 +#: IDF/gettexttemplates/idf/listProjects.html.php:6 IDF/Views/Admin.php:186 +msgid "Create Project" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:6 +msgid "Change Project Details" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:3 +msgid "" +"You can select the type of repository you want. In the case of subversion, " +"you can use optionally a remote repository instead of the local one." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:4 +msgid "" +"Once you have defined the repository type, you cannot change it." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:5 +msgid "" +"\n" +"

Specify each person by its login. Each person must have already " +"registered with the given login.

\n" +"

Separate the logins with commas and/or new lines.

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:14 +msgid "" +"The form contains some errors. Please correct them to create the project." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:15 +msgid "Provide at least one owner for the project or use a template." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:15 +msgid "Instructions:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:3 +#, php-format +msgid "" +"Confirmation code to confirm the deletion of the project: \n" +"%%code%%." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:5 +msgid "" +"\n" +"Attention! Deleting a project is a one second operation\n" +"with the consequences that all the data related to the \n" +"project will be deleted.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:10 +msgid "" +"The form contains some errors. Please correct them to delete the project." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:11 +msgid "Project Statistics" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:12 +msgid "Tab" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:13 +msgid "Number" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:15 +msgid "Code reviews" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:16 +#: IDF/Views/Project.php:93 +msgid "Commits" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:18 +msgid "Documentation pages" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:19 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:20 +msgid "Delete Project" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:22 +msgid "" +"For large projects, the suppression can take a while, please be patient." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:3 +msgid "Space Usage Statistics" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:4 +msgid "Repositories:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:5 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:11 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:18 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:16 +msgid "Attachments:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:7 +msgid "Database:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:8 +msgid "Total Forge:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:13 +msgid "" +"The form contains some errors. Please correct them to update the project." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:14 +msgid "Provide at least one owner for the project." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:15 +msgid "Update Project" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:19 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:20 +msgid "Delete this project" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:21 +msgid "You will be asked to confirm." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:3 +#: IDF/Views/Admin.php:264 +msgid "User List" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:13 +msgid "Update User" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:4 +msgid "Create User" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:3 +msgid "The form contains some errors. Please correct them to create the user." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:6 +msgid "The user password will be sent by email to the user." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/createuser-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"An account on the forge has been created for you by\n" +"the administrator %%admin%%.\n" +"\n" +"Please find here your details to access the forge:\n" +"\n" +" Address: %%url%%\n" +" Login: %%user.login%%\n" +" Password: %%password%%\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:3 +#, php-format +msgid "See not validated users." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:4 +msgid "

You have here an overview of the users registered in the forge.

" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:5 +msgid "Number of users:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:3 +msgid "" +"If you are changing the email address of the user, you\n" +"need to ensure that you are providing a valid email\n" +"address" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:6 +msgid "" +"If you give the user staff rights, the user will be\n" +"able to create new projects and update other non staff users.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:9 +msgid "The form contains some errors. Please correct them to update the user." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:10 +#: IDF/gettexttemplates/idf/register/confirmation.html.php:4 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:4 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:4 +msgid "Login:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:11 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:5 +msgid "Public Profile" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:12 +msgid "Administrative" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/base.html.php:3 +msgid "Configured servers" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/base.html.php:4 +#: IDF/Views/Admin.php:421 +msgid "Usher control" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html~.php:3 +msgid "address" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html~.php:4 +msgid "port" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:5 +msgid "No connections found." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:3 +msgid "current server status:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:4 +msgid "startup" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:5 +msgid "shutdown" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:6 +msgid "reload server configuration:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:7 +msgid "reload" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:11 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:11 +msgid "Status explanation" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:9 +msgid "active with n total open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:10 +msgid "waiting for new connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:11 +msgid "usher is being shut down, not accepting connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:12 +msgid "" +"usher is shut down, all local servers are stopped and not accepting " +"connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:3 +msgid "server name" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:4 IDF/Issue.php:99 +#: IDF/Review.php:102 +msgid "status" +msgstr "durum" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:5 +msgid "action" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:6 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:6 +msgid "No monotone servers configured." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:7 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:7 +msgid "stop" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:8 +msgid "start" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:9 +msgid "kill" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:10 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:10 +msgid "active connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:12 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:12 +msgid "remote server without open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:13 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:13 +msgid "server with n open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:14 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:14 +msgid "local server running, without open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:15 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:15 +msgid "local server not running, waiting for connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:16 +msgid "local server is about to stop, n connections still open" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:17 +msgid "local server not running, not accepting connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:18 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:18 +msgid "usher is shut down, not running and not accepting connections" +msgstr "" + +#: IDF/gettexttemplates/idf/index.atom.php:3 +#, php-format +msgid "Personal project feed for %%user%%." +msgstr "" + +#: IDF/gettexttemplates/idf/index.html.php:3 +#: IDF/gettexttemplates/idf/main-menu.html.php:6 +msgid "Home" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:3 +#, php-format +msgid "Attachment to issue %%issue.id%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:5 +#: IDF/gettexttemplates/idf/review/view.html.php:35 +#: IDF/gettexttemplates/idf/source/commit.html.php:23 +#: IDF/gettexttemplates/idf/source/commit.html~.php:22 +#: IDF/gettexttemplates/idf/source/git/file.html.php:6 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:7 +msgid "Archive" +msgstr "Arşiv" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:6 +#: IDF/gettexttemplates/idf/source/git/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:12 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:12 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:10 +msgid "Download this file" +msgstr "Bu dosyayı indir" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:7 +#: IDF/gettexttemplates/idf/issues/view.html.php:28 +#: IDF/gettexttemplates/idf/review/view.html.php:26 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:13 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:14 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:16 +msgid "Created:" +msgstr "Oluşturulma tarihi:" + +#: IDF/gettexttemplates/idf/issues/base.html.php:4 +msgid "All Issues" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/base.html.php:5 +msgid "My Issues" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/base.html.php:6 +msgid "My watch list" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/base.html.php:7 +#: IDF/gettexttemplates/idf/issues/by-label.html.php:6 +#: IDF/gettexttemplates/idf/issues/index.html.php:5 +#: IDF/gettexttemplates/idf/issues/project-watchlist.html.php:5 +#: IDF/gettexttemplates/idf/issues/search.html.php:8 +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:5 +msgid "New Issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/base.html.php:8 +#: IDF/gettexttemplates/idf/wiki/base.html.php:9 +msgid "Search" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/base.html.php:9 +msgid "Back to the issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:3 +#, php-format +msgid "" +"

Open issues: %%open%%

\n" +"

Closed issues: %%closed%%

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:7 +msgid "Label:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:8 +msgid "Completion:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/create.html.php:3 +msgid "" +"

When you submit the issue do not forget to provide the following " +"information:

\n" +"
    \n" +"
  • The steps to reproduce the problem.
  • \n" +"
  • The version of the software and your operating system.
  • \n" +"
  • Any information that can help the developers to solve the issue.
  • \n" +"
  • Do not provide any password or confidential information!
  • \n" +"
" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/create.html.php:10 +msgid "The form contains some errors. Please correct them to submit the issue." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/create.html.php:11 +#: IDF/gettexttemplates/idf/issues/create.html.php:13 +#: IDF/gettexttemplates/idf/issues/view.html.php:24 +#: IDF/gettexttemplates/idf/issues/view.html.php:26 +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:5 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:5 +msgid "Preview" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/create.html.php:12 +msgid "Submit Issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/create.html.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:34 +msgid "Attach file" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/create.html.php:16 +#: IDF/gettexttemplates/idf/issues/create.html.php:17 +#: IDF/gettexttemplates/idf/issues/view.html.php:35 +#: IDF/gettexttemplates/idf/issues/view.html.php:36 +msgid "Attach another file" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:3 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:3 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:13 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:12 +#: IDF/gettexttemplates/idf/issues/view.html.php:18 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:3 +#: IDF/gettexttemplates/idf/review/view.html.php:38 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:11 +#: IDF/IssueComment.php:151 +msgid "Summary:" +msgstr "Özet:" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:4 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:4 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:8 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:14 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:13 +#: IDF/gettexttemplates/idf/issues/view.html.php:19 +#: IDF/gettexttemplates/idf/issues/view.html.php:30 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:4 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/view.html.php:39 IDF/IssueComment.php:153 +msgid "Status:" +msgstr "Durum:" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:5 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:15 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:14 +#: IDF/gettexttemplates/idf/issues/view.html.php:20 +#: IDF/gettexttemplates/idf/issues/view.html.php:31 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:5 +#: IDF/IssueComment.php:155 +msgid "Owner:" +msgstr "Sahibi:" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:17 +#: IDF/gettexttemplates/idf/issues/view.html.php:22 IDF/IssueComment.php:159 +msgid "Relations:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/forge-watchlist.html.php:3 +#: IDF/gettexttemplates/idf/issues/index.html.php:3 +#: IDF/gettexttemplates/idf/issues/project-watchlist.html.php:3 +#, php-format +msgid "" +"

Open issues: %%open%%

\n" +"

Closed issues: %%closed%%

" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:3 +#, fuzzy +msgid "A new issue has been created and assigned to you:" +msgstr "Yeni bir sorun bildirildi ve size atandı:" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:4 +#, fuzzy +msgid "A new issue has been created:" +msgstr "Yeni bir sorun bildirildi ve size atandı:" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:8 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:11 +msgid "Reported by:" +msgstr "Bildiren:" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:12 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:19 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:17 +msgid "Issue:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:3 +msgid "The following issue you are owning has been updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:4 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:3 +msgid "The following issue has been updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:4 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:4 +#, php-format +msgid "By %%who%%, %%c.creation_dtime%%:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:10 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:9 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:12 +msgid "URL:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:12 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:11 +msgid "Comments (last first):" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/search.html.php:3 +#, php-format +msgid "" +"\n" +"

Found open issues: %%open%%

\n" +"

Found closed issues: %%closed" +"%%

" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/search.html.php:6 +#, php-format +msgid "" +"

Label:\n" +"%%tag.class%%:" +"%%tag.name%%

" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:3 +msgid "View all open issues." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:4 +msgid "Create an issue." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:5 +#, php-format +msgid "" +"The issue tracker is empty.
Create your " +"first issue." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:6 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:4 +#, php-format +msgid "Unresolved: By %%key%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:7 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:5 +msgid "Status Summary" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:8 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:6 +msgid "Unresolved: By Assignee" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html~.php:3 +#, php-format +msgid "" +"The issue tracker is empty.
You can create your first issue here." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:3 +#, php-format +msgid "" +"See the %%nb_submit_closed%% closed." +msgid_plural "" +"See the %%nb_submit_closed%% closed." +msgstr[0] "" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:4 +#, php-format +msgid "" +"See the %%nb_owner_closed%% closed." +msgid_plural "" +"See the %%nb_owner_closed%% closed." +msgstr[0] "" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:6 +#: IDF/gettexttemplates/idf/user/dashboard.html.php:7 +msgid "Submitted issues:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:7 +#: IDF/gettexttemplates/idf/user/dashboard.html.php:6 +msgid "Working issues:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:3 +#, php-format +msgid "Reported by %%submitter%%, %%c.creation_dtime%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:4 +#: IDF/gettexttemplates/idf/review/view.html.php:22 +#, php-format +msgid "" +"Comment %%i%% by %%submitter%%, %%c.creation_dtime%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:5 +#, php-format +msgid "Sign in to reply to this comment." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:6 +msgid "" +"This issue is marked as closed, add a comment only if you think this issue " +"is still valid and more work is needed to fully fix it." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:8 +#, php-format +msgid "%%interested%% person" +msgid_plural "%%interested%% persons" +msgstr[0] "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:9 +#, php-format +msgid "This issue %%verb%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:10 +msgid "Remove this issue from your watch list" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:11 +msgid "Add this issue to your watch list" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:12 +msgid "View the previous closed issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:13 +msgid "View the previous open issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:14 +msgid "View the next closed issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:15 +msgid "View the next open issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:16 +msgid "download" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:17 +msgid "view" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:23 +msgid "The form contains some errors. Please correct them to change the issue." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:25 +msgid "Submit Changes" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:32 +msgid "Followed by:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:3 +#, fuzzy, php-format +msgid "1 project" +msgid_plural "%%label.project_count%% projects" +msgstr[0] "proje" + +#: IDF/gettexttemplates/idf/listProjects.html.php:4 +#, php-format +msgid "Remove filter for %%tag%%" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:5 +msgid "No projects managed with InDefero were found." +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:7 +msgid "Filter projects by label" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:8 +#, fuzzy +msgid "No projects with labels found." +msgstr "\"%s\" isimli proje bulunamadı." + +#: IDF/gettexttemplates/idf/listProjects.html.php:9 +msgid "Order" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:10 +#, fuzzy +msgid "By name" +msgstr "isim" + +#: IDF/gettexttemplates/idf/listProjects.html.php:11 +msgid "By activity" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:12 +msgid "Filtered project stats" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:13 +msgid "Members:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:14 +msgid "Issues:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:15 +msgid "Commits:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:16 +msgid "Documentations:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:18 +msgid "Code reviews:" +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:3 +#, php-format +msgid "" +"You can create an account if you don't have one yet." +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:4 +msgid "What is your account information?" +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:5 +msgid "My login is" +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:6 +msgid "My password is" +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:7 +msgid "Sign in" +msgstr "Giriş" + +#: IDF/gettexttemplates/idf/login_form.html.php:8 +msgid "I lost my password!" +msgstr "Parolamı unuttum!" + +#: IDF/gettexttemplates/idf/login_form.html.php:9 +msgid "Welcome." +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:10 +msgid "It takes less than a minute to create your account." +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:3 +#, php-format +msgid "" +"Welcome, %%user%%." +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:4 +msgid "Sign Out" +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:5 +msgid "Sign in or create your account" +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:10 IDF/Views/Admin.php:40 +msgid "Forge Management" +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:11 +msgid "Help and accessibility features" +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:12 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:14 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:14 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:15 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:13 +msgid "Help" +msgstr "" + +#: IDF/gettexttemplates/idf/project/home.html.php:3 +#: IDF/gettexttemplates/idf/project/timeline.html.php:4 IDF/Views.php:46 +msgid "Welcome" +msgstr "Hoşgeldiniz" + +#: IDF/gettexttemplates/idf/project/home.html.php:4 +#: IDF/gettexttemplates/idf/project/timeline.html.php:5 +msgid "Latest Updates" +msgstr "Son Güncellemeler" + +#: IDF/gettexttemplates/idf/project/home.html.php:5 +msgid "Featured Downloads" +msgstr "Sunulan yüklemeler" + +#: IDF/gettexttemplates/idf/project/home.html.php:6 +#, fuzzy +msgid "Show more featured downloads" +msgstr "Sunulan yüklemeler" + +#: IDF/gettexttemplates/idf/project/home.html.php:7 +#: IDF/gettexttemplates/idf/project/home.html.php:10 +msgid "show more..." +msgstr "Daha fazla göster..." + +#: IDF/gettexttemplates/idf/project/home.html.php:8 +msgid "Featured Documentation" +msgstr "Sunulan Dokümanlar" + +#: IDF/gettexttemplates/idf/project/home.html.php:9 +#, fuzzy +msgid "Show more featured documentation" +msgstr "Sunulan Dokümanlar" + +#: IDF/gettexttemplates/idf/project/home.html.php:11 +msgid "Development Team" +msgstr "Geliştirme Ekibi" + +#: IDF/gettexttemplates/idf/project/home.html.php:12 +msgid "Admins" +msgstr "Yöneticiler" + +#: IDF/gettexttemplates/idf/project/home.html.php:13 +msgid "Happy Crew" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:3 +msgid "Latest updates" +msgstr "Son güncellemeler" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:6 +#: IDF/Views/Project.php:90 +msgid "All Updates" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:7 +msgid "Filter by type" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:8 +msgid "Subscribe to this timeline" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:9 +msgid "RSS" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:10 +msgid "Atom feed" +msgstr "" + +#: IDF/gettexttemplates/idf/project-list.html.php:3 +msgid "Project activity: %%activity%%%" +msgstr "" + +#: IDF/gettexttemplates/idf/project-list.html.php:9 +msgid "n/a" +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation-email.txt.php:3 +#, php-format +msgid "" +"Hello,\n" +"\n" +"You have requested the creation of an account to\n" +"participate in the life of a software project.\n" +"\n" +"To confirm the account please follow this link:\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following confirmation key:\n" +"\n" +"%%key%%\n" +"\n" +"If you are not interested any longer in taking\n" +"part in the life of the software project or if\n" +"you can't remember having requested the creation\n" +"of an account, please excuse us and simply ignore\n" +"this email. \n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:3 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:3 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:3 +msgid "Oops, please check the form for errors." +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:5 +msgid "Email:" +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:6 +msgid "Enable Your Account" +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:8 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:8 +msgid "" +"This is the last step, but just be sure to have the cookies enabled to log in afterwards." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:3 +msgid "" +"Read the terms and conditions – " +"basically \"Please be nice, we respect you\"." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:4 +#, php-format +msgid "" +"If you have just forgotten your login information, then there is no need to " +"create a new account. You can just recover your login " +"name and password." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:5 +#, php-format +msgid "" +"With your account, you will able to participate in the life of all the " +"projects hosted here. Participating in a software project must be fun, so if " +"you have troubles, you can let us know about your issues " +"at anytime!" +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:6 +msgid "Oops, please check the provided login and email address to register." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:7 IDF/Views.php:137 +msgid "Create Your Account" +msgstr "Yeni Hesap Oluştur" + +#: IDF/gettexttemplates/idf/register/index.html.php:9 +msgid "" +"Be sure to provide a valid email address, as we are sending a validation " +"link by email." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:10 +msgid "Did you know?" +msgstr "" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:3 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:3 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:3 +msgid "Oops, we found an error in the form." +msgstr "" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:4 +msgid "Confirm Your Account" +msgstr "" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:7 +msgid "" +"Use your email software to read your emails and open your confirmation " +"email. Either click directly on the confirmation link or copy/paste the " +"confirmation key in the box and submit the form." +msgstr "" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:8 +msgid "" +"Just after providing the confirmation key, you will be able to set your " +"password and start using this website fully." +msgstr "" + +#: IDF/gettexttemplates/idf/review/base-full.html.php:3 +#: IDF/gettexttemplates/idf/review/base.html.php:3 +msgid "Open Reviews" +msgstr "" + +#: IDF/gettexttemplates/idf/review/base.html.php:4 +#: IDF/gettexttemplates/idf/review/create.html.php:11 +#: IDF/gettexttemplates/idf/review/index.html.php:3 IDF/Views/Review.php:83 +msgid "Start Code Review" +msgstr "" + +#: IDF/gettexttemplates/idf/review/create.html.php:3 +msgid "" +"

To start a code review, you need to provide:

\n" +"
    \n" +"
  • A commit or revision of the current code in the repository from which " +"you started your work.
  • \n" +"
  • A patch describing your changes with respect to the reference commit.\n" +"
  • Check your patch does not provide any password or confidential " +"information!
  • \n" +"
" +msgstr "" + +#: IDF/gettexttemplates/idf/review/create.html.php:9 +msgid "" +"The form contains some errors. Please correct them to submit the code review." +msgstr "" + +#: IDF/gettexttemplates/idf/review/create.html.php:10 +msgid "" +"Select the commit against which you created your patch to be sure it applies " +"correctly." +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:3 +msgid "The following review has been created:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:16 +msgid "Review:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:3 +msgid "The following review has been updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:5 +#, php-format +msgid "" +"By %%who%%, %%c.creation_dtime%%, on file:\n" +"%%c.cfile%%\n" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:14 +msgid "General comments (last first):" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:15 +msgid "Detailed file comments (last first):" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:3 +msgid "" +"Code review is a process in which\n" +"after or before changes are commited into the code repository,\n" +"different people discuss the code changes. The goal is\n" +"to improve the quality of the code and the\n" +"contributions, as such, you must be pragmatic when writing\n" +"your review. Correctly mention the line numbers (in the old or in the\n" +"new file) and try to keep a good balance between seriousness and fun.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:11 +msgid "" +"\n" +"Proposing code for review is intimidating, you know\n" +"you will receive critics, so please, as a reviewer, keep this\n" +"process fun, use it to help your contributor learn your\n" +"coding standards and the structure of the code and make them want\n" +"to propose more contributions.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:18 +#: IDF/gettexttemplates/idf/source/commit.html.php:3 +#: IDF/gettexttemplates/idf/source/commit.html~.php:3 +#, php-format +msgid "%%ndiff%% diff" +msgid_plural "%%ndiff%% diffs" +msgstr[0] "" + +#: IDF/gettexttemplates/idf/review/view.html.php:19 +#, php-format +msgid "%%nc%% comment" +msgid_plural "%%nc%% comments" +msgstr[0] "" + +#: IDF/gettexttemplates/idf/review/view.html.php:20 +#, php-format +msgid "" +"Comment %%i%% by %%who%%, " +"%%c.creation_dtime%%" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:21 +#, php-format +msgid "Your comments on the changes in file %%file%%:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:23 +#, php-format +msgid "Sign in to participate in the review." +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:24 +msgid "" +"The form contains some errors. Please correct them to submit your review." +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:25 +msgid "How to Participate in a Code Review" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:28 +#: IDF/gettexttemplates/idf/source/commit.html.php:5 +#: IDF/gettexttemplates/idf/source/commit.html~.php:5 +msgid "Author:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:29 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/source/commit.html.php:7 +#: IDF/gettexttemplates/idf/source/commit.html~.php:7 +msgid "Commit:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:30 +#: IDF/gettexttemplates/idf/source/commit.html.php:8 +#: IDF/gettexttemplates/idf/source/commit.html~.php:8 +msgid "View corresponding source tree" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:32 +msgid "Reviewers:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:33 +msgid "No reviewers at the moment." +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:34 +msgid "Files:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:36 +#: IDF/gettexttemplates/idf/source/commit.html.php:24 +#: IDF/gettexttemplates/idf/source/commit.html~.php:23 +msgid "Download the corresponding diff file" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:37 +msgid "General Comments" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:40 +msgid "Submit Code Review" +msgstr "" + +#: IDF/gettexttemplates/idf/source/base.html.php:3 +msgid "Source Tree" +msgstr "" + +#: IDF/gettexttemplates/idf/source/base.html.php:4 +msgid "Change Log" +msgstr "" + +#: IDF/gettexttemplates/idf/source/base.html.php:6 +msgid "How To Get The Code" +msgstr "" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:3 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:8 +#: IDF/Views/Project.php:190 +msgid "Age" +msgstr "" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:4 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:10 +msgid "Message" +msgstr "" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:5 +msgid "Parent:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:6 +#: IDF/gettexttemplates/idf/source/commit.html.php:10 +#: IDF/gettexttemplates/idf/source/commit.html~.php:10 +msgid "View corresponding commit" +msgstr "" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:8 +msgid "by" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:3 +msgid "A new commit has been created:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:8 +msgid "Created by:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:8 +msgid "Created at:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:8 +msgid "Content:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:10 +msgid "Commit details:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:4 +#: IDF/gettexttemplates/idf/source/commit.html~.php:4 +msgid "Date:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:6 +#: IDF/gettexttemplates/idf/source/commit.html~.php:6 +msgid "Branch:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:9 +#: IDF/gettexttemplates/idf/source/commit.html~.php:9 +msgid "Parents:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:11 +#: IDF/gettexttemplates/idf/source/commit.html~.php:11 +msgid "Message:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:12 +#: IDF/gettexttemplates/idf/source/commit.html~.php:12 +#: IDF/gettexttemplates/idf/wiki/feedfragment-page.xml.php:3 +#: IDF/gettexttemplates/idf/wiki/feedfragment-resource.xml.php:3 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:10 +msgid "Changes:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:13 +#: IDF/gettexttemplates/idf/source/commit.html~.php:13 +msgid "deleted" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:14 +#: IDF/gettexttemplates/idf/source/commit.html.php:18 +#: IDF/gettexttemplates/idf/source/commit.html~.php:14 +#: IDF/gettexttemplates/idf/source/commit.html~.php:17 +msgid "full" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:15 +#: IDF/gettexttemplates/idf/source/commit.html~.php:15 +msgid "renamed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:16 +msgid "copied" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:17 +#: IDF/gettexttemplates/idf/source/commit.html~.php:16 +msgid "added" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:19 +#: IDF/gettexttemplates/idf/source/commit.html~.php:18 +msgid "modified" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:20 +msgid "properties changed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:21 +#: IDF/gettexttemplates/idf/source/commit.html~.php:20 +msgid "removed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:22 +#: IDF/gettexttemplates/idf/source/commit.html~.php:21 +msgid "File differences" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html~.php:19 +msgid "properies changed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:3 +#, php-format +msgid "" +"The revision identifier %%commit%% is ambiguous and can be\n" +"expanded to multiple valid revisions - please choose one:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:5 +msgid "Title" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:6 +msgid "Author" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:7 +msgid "Date" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:8 +msgid "Branch" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:9 +msgid "Revision" +msgstr "" + +#: IDF/gettexttemplates/idf/source/feedfragment.xml.php:3 +#, php-format +msgid "%%cproject.name%%: Commit %%c.scm_id%%" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:3 +msgid "Branches" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:4 +msgid "filter branches" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:5 +msgid "Tags" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:6 +msgid "filter tags" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/file.html.php:3 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:4 +#, php-format +msgid "" +"Source at commit %%commit%% created " +"%%cobject.date%%." +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/file.html.php:4 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:5 +#, php-format +msgid "By %%cobject.author%%, %%cobject.title%%" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/file.html.php:5 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:6 +msgid "Root" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the git software to manage the source\n" +"code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:6 +#, php-format +msgid "" +"You may need to provide your SSH key. The " +"synchronization of your SSH key can take a couple of minutes. You can learn " +"more about SSH key authentication." +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:6 +msgid "To make a first commit in the repository, perform the following steps:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:8 +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:7 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:7 +#, php-format +msgid "Find here more details on how to access %%project%% source code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:9 +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:8 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:8 +msgid "Command-Line Access" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:10 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:9 +msgid "First Commit" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:11 +#: IDF/Views/Download.php:66 IDF/Views/Download.php:348 +msgid "Size" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:12 +msgid ":" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:13 +msgid "Download this version" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:13 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:13 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:14 +msgid "or" +msgstr "" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:3 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:3 +#, php-format +msgid "" +"The branch or revision %%commit%% is not valid or does not exist\n" +"in this repository." +msgstr "" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:5 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:5 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:5 +msgid "The following list shows all available branches:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:6 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:6 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:6 +#, php-format +msgid "" +"If this is a new repository, the reason for this error\n" +"could be that you have not committed and / or pushed any change so far.\n" +"In this case please take a look at the Help page\n" +"how to access your repository." +msgstr "" + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the Mercurial software to manage the source\n" +"code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:6 +#, php-format +msgid "" +"To get write access to the repository, you need to use your username and " +"your extra password." +msgstr "" + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:9 +msgid "Write Access Authentication" +msgstr "" + +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:3 +#, php-format +msgid "Property %%prop%% set to %%val%%" +msgstr "" + +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the monotone software to manage the source\n" +"code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/changelog.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/commit.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/commit.html~.php:3 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:14 +msgid "Revision:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/changelog.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/commit.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/commit.html~.php:4 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:10 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:15 +msgid "Switch" +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the subversion software to manage the source\n" +"code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:3 +#, php-format +msgid "" +"The revision %%commit%% is not valid or does not exist\n" +"in this repository." +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:9 +msgid "Rev" +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:16 +msgid "Branches:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:17 +msgid "Tags:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/changeemail-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"To confirm that you want %%email%%\n" +"to be your new email address, just follow this link:\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following verification key:\n" +"\n" +"%%key%%\n" +"\n" +"If you do not want to change your email address, \n" +"just ignore this message.\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/user/changeemail.html.php:4 +msgid "Confirm Your New Email Address" +msgstr "" + +#: IDF/gettexttemplates/idf/user/changeemail.html.php:7 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:7 +msgid "" +"Use your email software to read your emails and open your verification " +"email. Either click directly on the verification link or copy/paste the " +"verification key in the box and submit the form." +msgstr "" + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:3 +#, php-format +msgid "Update your account." +msgstr "" + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:4 +#, php-format +msgid "See your public profile." +msgstr "" + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:5 +#, php-format +msgid "See your forge issue watch list." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:6 +msgid "Key Management" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:7 +msgid "Secondary Emails" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:8 +msgid "Extra password" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:9 +msgid "" +"This password is used to access some of the external systems managed by our " +"infrastructure. It will be regenerated if you change your password." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:10 +msgid "API key" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:11 +msgid "" +"Your API key will be regenerated automatically if you change your password." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:12 +msgid "Update Your Account" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:14 +msgid "Your Current Public Keys" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:15 +msgid "Delete this key" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:16 +msgid "Your additional email addresses" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:17 +msgid "Delete this address" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:18 +msgid "" +"If possible, use your real name. By using your real name, people will have " +"more trust in your comments and remarks." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:19 +msgid "" +"The extra password is used to access some of the external systems and the " +"API key is used to interact with this website using a program." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:20 +msgid "Show API key and extra password" +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:3 +msgid "" +"Oops, please check the provided login or email address to recover your " +"password." +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:4 +msgid "Recover My Password" +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:6 +msgid "" +"Provide either your login or email address, if a corresponding user is found " +"in the database, we will send you an email with the details on how to reset " +"your password." +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"You lost your password and wanted to recover it.\n" +"To provide a new password for your account, you\n" +"just have to follow the provided link. You will\n" +"get a simple form to provide a new password.\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following verification key:\n" +"\n" +"%%key%%\n" +"\n" +"If you are not the one who requested to reset\n" +"your password, simply ignore this email, your\n" +"password will not be changed.\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:4 +msgid "Recover Your Password" +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:8 +msgid "" +"Just after providing the confirmation key, you will be able to reset your " +"password and use this website fully." +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:6 +msgid "Reset Your Password" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:3 +#, php-format +msgid "You are looking at the public profile of %%member%%." +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:5 +msgid "Twitter:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:6 +msgid "Public Email:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:7 +msgid "Website:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:8 +msgid "Last time seen:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:9 +msgid "Member since:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:3 +msgid "List Pages" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:4 +msgid "List Resources" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:5 +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:4 +#: IDF/gettexttemplates/idf/wiki/search.html.php:3 IDF/Views/Wiki.php:211 +msgid "New Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:6 +#: IDF/gettexttemplates/idf/wiki/listResources.html.php:3 +#: IDF/Views/Wiki.php:256 +msgid "New Resource" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:7 +msgid "Update This Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:8 +msgid "Update This Resource" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:3 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:3 +msgid "Preview of the Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:7 +msgid "The form contains some errors. Please correct them to create the page." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:6 +msgid "Create Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:3 +msgid "" +"\n" +"Wiki resources are later addressed in wiki pages by their title, so ensure " +"that you\n" +"give your resource a unique and an easy to remember name.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:8 +#, fuzzy +msgid "Create Resource" +msgstr "Yeni Hesap Oluştur" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:3 +msgid "" +"If you delete this documentation page, it will be removed from the database " +"with all the associated revisions and you will not be able to " +"recover it." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:6 +msgid "Delete Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:14 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:15 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:15 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:17 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:18 +msgid "Old Revisions" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:3 +#, php-format +msgid "" +"You are looking at an old revision (%%oldrev.summary%%) of the " +"page \n" +"%%page.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:5 +msgid "" +"If you delete this old revision, it will be removed from the database and " +"you will not be able to recover it." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:8 +msgid "Delete Revision" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:3 +msgid "" +"If you delete this documentation resource, it will be removed from the " +"database with all the associated revisions \n" +"and you will not be able to recover it. Any documentation " +"pages that reference this resource,\n" +"will no longer be able to render it, but won't be deleted." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:8 +msgid "Delete Resource" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:10 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:8 +#, fuzzy +msgid "File size" +msgstr "dosya boyutu" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:9 +#: IDF/Views/Wiki.php:101 +#, fuzzy +msgid "MIME type" +msgstr "tip" + +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:3 +#, php-format +msgid "" +"You are looking at an old revision (%%oldrev.summary%%) of the " +"resource \n" +"%%resource.title%%. This revision was created by " +"%%submitter%%." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/edit-info.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

The content of the page can use the Markdown syntax with the Extra extension.

\n" +"

Website addresses are automatically linked and you can link to another " +"page in the documentation using double square brackets like that " +"[[AnotherPage]].

\n" +"

If you want to embed uploaded resources, use the [[!ResourceName]] syntax for that. This is described more in detail in the FAQ.

\n" +"

To directly include a file content from the repository, embrace its path " +"with triple square brackets: [[[my/file.txt]]].

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/feedfragment-resource.xml.php:4 +msgid "Initial creation" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:3 +#, php-format +msgid "See the deprecated pages." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:5 +msgid "Number of pages:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/listResources.html.php:4 +msgid "Number of resources:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/search.html.php:4 +msgid "Pages found:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:3 +msgid "The form contains some errors. Please correct them to update the page." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:6 +msgid "Update Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:10 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:11 +msgid "Delete this page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:4 +msgid "Update Resource" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:8 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:9 +msgid "Delete this resource" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:3 +msgid "" +"Attention! This page is marked as deprecated, \n" +"use it as reference only if you are sure you need these specific information." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:5 +#, php-format +msgid "" +"You are looking at an old revision of the page \n" +"%%page.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:10 +msgid "Table of Content" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:13 +msgid "Delete this revision" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:3 +#, php-format +msgid "" +"You are looking at an old revision of the resource \n" +"%%resource.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:14 +msgid "Page Usage" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:15 +msgid "This resource is not used on any pages yet." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:3 +msgid "A new documentation page has been created:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:14 +msgid "Documentation page:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:3 +msgid "The following documentation page has been updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:7 +msgid "Updated by:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:13 +msgid "New content:" +msgstr "" + +#: IDF/Issue.php:76 +msgid "owner" +msgstr "sahip" + +#: IDF/Issue.php:84 IDF/Wiki/Page.php:86 +msgid "interested users" +msgstr "ilgilenen kullanıcılar" + +#: IDF/Issue.php:85 +msgid "" +"Interested users will get an email notification when the issue is changed." +msgstr "" + +#: IDF/Issue.php:92 IDF/Project.php:94 IDF/Review.php:95 IDF/Upload.php:99 +#: IDF/Wiki/Page.php:94 +msgid "labels" +msgstr "etiketler" + +#: IDF/Issue.php:111 IDF/IssueFile.php:102 IDF/Review.php:114 +#: IDF/Upload.php:118 IDF/Wiki/Page.php:106 IDF/Wiki/Resource.php:101 +msgid "modification date" +msgstr "düzenlenme tarihi" + +#: IDF/Issue.php:212 IDF/IssueComment.php:143 +#, php-format +msgid "" +"Issue %3$d, %4$s" +msgstr "" + +#: IDF/Issue.php:214 +#, php-format +msgid "Creation of issue %3$d, by %4$s" +msgstr "" + +#: IDF/Issue.php:224 +#, php-format +msgid "%1$s: Issue %2$d created - %3$s" +msgstr "" + +#: IDF/Issue.php:307 +#, php-format +msgid "Issue %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Issue.php:311 +#, php-format +msgid "Updated Issue %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/IssueComment.php:51 IDF/IssueRelation.php:47 +msgid "issue" +msgstr "sorun" + +#: IDF/IssueComment.php:58 IDF/IssueFile.php:49 IDF/Review/Comment.php:62 +#: IDF/Review/FileComment.php:49 IDF/Review/FileComment.php:69 +msgid "comment" +msgstr "yorum" + +#: IDF/IssueComment.php:72 IDF/Review/Comment.php:75 IDF/Upload.php:63 +#: IDF/Wiki/PageRevision.php:85 +msgid "changes" +msgstr "değişiklikler" + +#: IDF/IssueComment.php:73 +msgid "Serialized array of the changes in the issue." +msgstr "" + +#: IDF/IssueComment.php:180 +#, php-format +msgid "Comment on issue %3$d, by %4$s" +msgstr "" + +#: IDF/IssueComment.php:191 +#, php-format +msgid "%1$s: Comment on issue %2$d - %3$s" +msgstr "" + +#: IDF/IssueFile.php:64 +msgid "file name" +msgstr "dosya adı" + +#: IDF/IssueFile.php:70 +msgid "the file" +msgstr "dosya" + +#: IDF/IssueFile.php:76 +msgid "file size" +msgstr "dosya boyutu" + +#: IDF/IssueFile.php:84 +msgid "type" +msgstr "tip" + +#: IDF/IssueFile.php:86 +msgid "Image" +msgstr "Resim" + +#: IDF/IssueFile.php:87 +msgid "Other" +msgstr "Diğer" + +#: IDF/IssueRelation.php:54 +msgid "verb" +msgstr "" + +#: IDF/IssueRelation.php:61 +msgid "other issue" +msgstr "" + +#: IDF/Key.php:55 +msgid "public key" +msgstr "" + +#: IDF/Key.php:90 +msgid "Invalid or unknown key data detected." +msgstr "" + +#: IDF/Plugin/SyncMercurial.php:78 IDF/Plugin/SyncSvn.php:81 +#, php-format +msgid "The repository %s already exists." +msgstr "" + +#: IDF/Plugin/SyncMercurial.php:142 +#, php-format +msgid "%s does not exist or is not writable." +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:107 IDF/Plugin/SyncMonotone.php:492 +msgid "\"mtn_repositories\" must be defined in your configuration file" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:114 IDF/Plugin/SyncMonotone.php:482 +msgid "\"mtn_usher_conf\" does not exist or is not writable" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:121 +#, php-format +msgid "Could not find mtn-post-push script \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:155 +#, php-format +msgid "The configuration file \"%s\" is missing" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:164 +#, php-format +msgid "The project path \"%s\" already exists" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:170 +#, php-format +msgid "The project path \"%s\" could not be created" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:208 +#, php-format +msgid "The key directory \"%s\" could not be created" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:227 +#, php-format +msgid "Could not parse key information: %s" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:265 +#, php-format +msgid "Could not create configuration directory \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:275 +#, php-format +msgid "Could not create symlink for configuration file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:293 +#, php-format +msgid "Could not write configuration file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:309 IDF/Plugin/SyncMonotone.php:525 +#, php-format +msgid "Could not parse usher configuration in \"%1$s\": %2$s" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:320 +#, php-format +msgid "usher configuration already contains a server entry named \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:345 IDF/Plugin/SyncMonotone.php:546 +#, php-format +msgid "Could not write usher configuration file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:395 +#, php-format +msgid "Could not write write-permissions file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:420 +#, php-format +msgid "Could not write read-permissions file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:438 +#, php-format +msgid "Could not remove symlink \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:446 +#, php-format +msgid "Could not create symlink \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:500 +#, php-format +msgid "One or more paths underneath %s could not be deleted" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:512 +#, php-format +msgid "Could not delete client private key \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:599 IDF/Plugin/SyncMonotone.php:718 +#, php-format +msgid "Could not parse read-permissions for project \"%1$s\": %2$s" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:643 IDF/Plugin/SyncMonotone.php:741 +#, php-format +msgid "Could not write read-permissions for project \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:657 IDF/Plugin/SyncMonotone.php:760 +#, php-format +msgid "Could not write write-permissions file for project \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:813 +msgid "\"mtn_repositories\" must be defined in your configuration file." +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:820 +#, php-format +msgid "The project path %s does not exists." +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:838 +#, php-format +msgid "The command \"%s\" could not be executed." +msgstr "" + +#: IDF/Project.php:62 IDF/Tag.php:66 +msgid "name" +msgstr "isim" + +#: IDF/Project.php:69 +msgid "short name" +msgstr "kısa isim" + +#: IDF/Project.php:70 +msgid "" +"Used in the URL to access the project, must be short with only letters and " +"numbers." +msgstr "" + +#: IDF/Project.php:78 +msgid "short description" +msgstr "kısa tanım" + +#: IDF/Project.php:86 IDF/Review/Patch.php:74 +msgid "description" +msgstr "tanım" + +#: IDF/Project.php:87 +msgid "The description can be extended using the Markdown syntax." +msgstr "" + +#: IDF/Project.php:100 +msgid "private" +msgstr "özel" + +#: IDF/Project.php:108 +msgid "current project activity" +msgstr "" + +#: IDF/Project.php:159 +#, php-format +msgid "Project \"%s\" not found." +msgstr "\"%s\" isimli proje bulunamadı." + +#: IDF/ProjectActivity.php:56 +msgid "date" +msgstr "" + +#: IDF/Review/Comment.php:55 IDF/Review/Patch.php:80 +msgid "patch" +msgstr "" + +#: IDF/Review/Comment.php:83 +msgid "vote" +msgstr "" + +#: IDF/Review/Comment.php:139 IDF/Review/Patch.php:151 +#, php-format +msgid "" +"Review %3$d, %4$s" +msgstr "" + +#: IDF/Review/Comment.php:141 +#, php-format +msgid "Update of review %3$d, by %4$s" +msgstr "" + +#: IDF/Review/Comment.php:151 +#, php-format +msgid "%1$s: Updated review %2$d - %3$s" +msgstr "" + +#: IDF/Review/Comment.php:222 +#, php-format +msgid "Updated Code Review %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Review/Patch.php:52 +msgid "review" +msgstr "" + +#: IDF/Review/Patch.php:67 +msgid "commit" +msgstr "" + +#: IDF/Review/Patch.php:153 +#, php-format +msgid "Creation of review %3$d, by %4$s" +msgstr "" + +#: IDF/Review/Patch.php:163 +#, php-format +msgid "%1$s: Creation of Review %2$d - %3$s" +msgstr "" + +#: IDF/Review/Patch.php:208 +#, php-format +msgid "New Code Review %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Scm/Git.php:309 IDF/Scm/Mercurial.php:199 +#, php-format +msgid "Folder %1$s not found in commit %2$s." +msgstr "" + +#: IDF/Scm/Git.php:433 IDF/Scm/Mercurial.php:216 +#, php-format +msgid "Not a valid tree: %s." +msgstr "" + +#: IDF/Scm/Monotone/Stdio.php:81 +msgid "Monotone client key name or hash not in project conf." +msgstr "" + +#: IDF/Scm/Monotone/Stdio.php:89 +#, php-format +msgid "The key directory %s could not be created." +msgstr "" + +#: IDF/Scm/Monotone/Stdio.php:100 +#, php-format +msgid "Could not write client key \"%s\"" +msgstr "" + +#: IDF/Search/Occ.php:33 +msgid "occurrence" +msgstr "" + +#: IDF/Search/Occ.php:49 +msgid "word" +msgstr "" + +#: IDF/Search/Occ.php:75 +msgid "occurrences" +msgstr "" + +#: IDF/Search/Occ.php:81 +msgid "ponderated occurrence" +msgstr "" + +#: IDF/Tag.php:59 +msgid "tag class" +msgstr "etiket sınıfı" + +#: IDF/Tag.php:60 +msgid "The class of the tag." +msgstr "Etiketin sınıfı." + +#: IDF/Tag.php:73 +msgid "lcname" +msgstr "" + +#: IDF/Tag.php:74 +msgid "Lower case version of the name for fast searching." +msgstr "Hızlı arama için ismin küçük harf hali." + +#: IDF/Template/Markdown.php:84 +msgid "Create this documentation page" +msgstr "" + +#: IDF/Template/Markdown.php:97 +msgid "You are not allowed to access the wiki." +msgstr "" + +#: IDF/Template/Markdown.php:106 +msgid "The wiki resource has not been found." +msgstr "" + +#: IDF/Template/Markdown.php:113 +msgid "The wiki resource has not been found. Create it!" +msgstr "" + +#: IDF/Template/Markdown.php:146 +msgid "This revision of the resource is no longer available." +msgstr "" + +#: IDF/Template/ShowUser.php:51 +msgid "Anonymous" +msgstr "" + +#: IDF/Template/ShowUser.php:54 +msgid "Me" +msgstr "" + +#: IDF/Timeline/Paginator.php:49 +msgid "Today" +msgstr "" + +#: IDF/Upload.php:70 +msgid "file" +msgstr "dosya" + +#: IDF/Upload.php:71 +msgid "The path is relative to the upload path." +msgstr "" + +#: IDF/Upload.php:78 IDF/Wiki/ResourceRevision.php:71 +msgid "file size in bytes" +msgstr "bayt cinsinden dosya boyutu" + +#: IDF/Upload.php:84 +msgid "MD5" +msgstr "" + +#: IDF/Upload.php:106 +msgid "number of downloads" +msgstr "indirme sayısı" + +#: IDF/Upload.php:201 +#, php-format +msgid "Download %2$d, %3$s" +msgstr "" + +#: IDF/Upload.php:204 +#, php-format +msgid "Addition of download %2$d, by %3$s" +msgstr "" + +#: IDF/Upload.php:214 +#, php-format +msgid "%1$s: Download %2$d added - %3$s" +msgstr "" + +#: IDF/Upload.php:301 +#, php-format +msgid "New download - %1$s (%2$s)" +msgstr "" + +#: IDF/Upload.php:305 +#, php-format +msgid "Updated download - %1$s (%2$s)" +msgstr "" + +#: IDF/Views/Admin.php:47 +msgid "The forge configuration has been saved." +msgstr "" + +#: IDF/Views/Admin.php:80 +msgid "This table shows the projects in the forge." +msgstr "" + +#: IDF/Views/Admin.php:85 +msgid "Short Name" +msgstr "" + +#: IDF/Views/Admin.php:87 +msgid "Repository Size" +msgstr "" + +#: IDF/Views/Admin.php:93 +msgid "No projects were found." +msgstr "" + +#: IDF/Views/Admin.php:116 +msgid "The label configuration has been saved." +msgstr "" + +#: IDF/Views/Admin.php:147 IDF/Views/Admin.php:314 IDF/Views/Wiki.php:484 +#: IDF/Views/Wiki.php:536 +#, php-format +msgid "Update %s" +msgstr "" + +#: IDF/Views/Admin.php:155 IDF/Views/Project.php:304 +msgid "The project has been updated." +msgstr "" + +#: IDF/Views/Admin.php:192 +msgid "The project has been created." +msgstr "" + +#: IDF/Views/Admin.php:223 +#, php-format +msgid "Delete %s Project" +msgstr "" + +#: IDF/Views/Admin.php:230 +msgid "The project has been deleted." +msgstr "" + +#: IDF/Views/Admin.php:260 +msgid "Not Validated User List" +msgstr "" + +#: IDF/Views/Admin.php:268 +msgid "This table shows the users in the forge." +msgstr "" + +#: IDF/Views/Admin.php:272 +msgid "login" +msgstr "" + +#: IDF/Views/Admin.php:275 +msgid "Admin" +msgstr "" + +#: IDF/Views/Admin.php:277 +msgid "Last Login" +msgstr "" + +#: IDF/Views/Admin.php:284 +msgid "No users were found." +msgstr "" + +#: IDF/Views/Admin.php:321 +msgid "You do not have the rights to update this user." +msgstr "" + +#: IDF/Views/Admin.php:339 +msgid "The user has been updated." +msgstr "" + +#: IDF/Views/Admin.php:372 +#, php-format +msgid "The user %s has been created." +msgstr "" + +#: IDF/Views/Admin.php:379 +msgid "Add User" +msgstr "" + +#: IDF/Views/Admin.php:395 +msgid "Usher management" +msgstr "" + +#: IDF/Views/Admin.php:432 +msgid "Usher configuration has been reloaded" +msgstr "" + +#: IDF/Views/Admin.php:436 +msgid "Usher has been shut down" +msgstr "" + +#: IDF/Views/Admin.php:441 +msgid "Usher has been started up" +msgstr "" + +#: IDF/Views/Admin.php:479 +#, php-format +msgid "The server \"%s\" has been started" +msgstr "" + +#: IDF/Views/Admin.php:483 +#, php-format +msgid "The server \"%s\" has been stopped" +msgstr "" + +#: IDF/Views/Admin.php:488 +#, php-format +msgid "The server \"%s\" has been killed" +msgstr "" + +#: IDF/Views/Admin.php:508 +#, php-format +msgid "Open connections for \"%s\"" +msgstr "" + +#: IDF/Views/Admin.php:513 +#, php-format +msgid "no connections for server \"%s\"" +msgstr "" + +#: IDF/Views/Admin.php:534 +msgid "Yes" +msgstr "Evet" + +#: IDF/Views/Admin.php:534 +msgid "No" +msgstr "" + +#: IDF/Views/Download.php:45 +#, php-format +msgid "%s Downloads" +msgstr "" + +#: IDF/Views/Download.php:51 +msgid "This table shows the files to download." +msgstr "" + +#: IDF/Views/Download.php:67 IDF/Views/Download.php:349 +msgid "Uploaded" +msgstr "" + +#: IDF/Views/Download.php:71 IDF/Views/Download.php:353 +msgid "No downloads were found." +msgstr "" + +#: IDF/Views/Download.php:94 +#, php-format +msgid "Download %s" +msgstr "" + +#: IDF/Views/Download.php:111 +#, php-format +msgid "The file %2$s has been updated." +msgstr "" + +#: IDF/Views/Download.php:144 +#, php-format +msgid "Delete Download %s" +msgstr "" + +#: IDF/Views/Download.php:177 +msgid "The file has been deleted." +msgstr "" + +#: IDF/Views/Download.php:244 +#, php-format +msgid "The file has been uploaded." +msgstr "" + +#: IDF/Views/Download.php:271 +msgid "New Downloads from Archive" +msgstr "" + +#: IDF/Views/Download.php:278 +msgid "The archive has been uploaded and processed." +msgstr "" + +#: IDF/Views/Download.php:331 +#, php-format +msgid "%1$s Downloads with Label %2$s" +msgstr "" + +#: IDF/Views/Download.php:341 +#, php-format +msgid "This table shows the downloads with label %s." +msgstr "" + +#: IDF/Views/Issue.php:41 +#, php-format +msgid "%s Open Issues" +msgstr "" + +#: IDF/Views/Issue.php:51 IDF/Views/Issue.php:382 IDF/Views/User.php:75 +msgid "This table shows the open issues." +msgstr "" + +#: IDF/Views/Issue.php:61 IDF/Views/Issue.php:220 IDF/Views/Issue.php:301 +#: IDF/Views/Issue.php:390 IDF/Views/Issue.php:542 IDF/Views/Issue.php:765 +#: IDF/Views/Issue.php:824 IDF/Views/Review.php:57 IDF/Views/User.php:81 +msgid "Id" +msgstr "" + +#: IDF/Views/Issue.php:64 IDF/Views/Issue.php:223 IDF/Views/Issue.php:305 +#: IDF/Views/Issue.php:393 IDF/Views/Issue.php:545 IDF/Views/Issue.php:768 +#: IDF/Views/Issue.php:827 IDF/Views/Review.php:60 IDF/Views/User.php:85 +msgid "Last Updated" +msgstr "" + +#: IDF/Views/Issue.php:68 IDF/Views/Issue.php:227 IDF/Views/Issue.php:309 +#: IDF/Views/Issue.php:397 IDF/Views/Issue.php:549 IDF/Views/Issue.php:772 +#: IDF/Views/Issue.php:831 +msgid "No issues were found." +msgstr "" + +#: IDF/Views/Issue.php:113 +msgid "Not assigned" +msgstr "" + +#: IDF/Views/Issue.php:149 +#, php-format +msgid "Summary of tracked issues in %s." +msgstr "" + +#: IDF/Views/Issue.php:194 +#, php-format +msgid "Watch List: Closed Issues for %s" +msgstr "" + +#: IDF/Views/Issue.php:195 +#, php-format +msgid "This table shows the closed issues in your watch list for %s project." +msgstr "" + +#: IDF/Views/Issue.php:200 +#, php-format +msgid "Watch List: Open Issues for %s" +msgstr "" + +#: IDF/Views/Issue.php:201 +#, php-format +msgid "This table shows the open issues in your watch list for %s project." +msgstr "" + +#: IDF/Views/Issue.php:277 +msgid "Watch List: Closed Issues" +msgstr "" + +#: IDF/Views/Issue.php:278 +msgid "This table shows the closed issues in your watch list." +msgstr "" + +#: IDF/Views/Issue.php:283 +msgid "Watch List: Open Issues" +msgstr "" + +#: IDF/Views/Issue.php:284 +msgid "This table shows the open issues in your watch list." +msgstr "" + +#: IDF/Views/Issue.php:303 IDF/Views/User.php:82 +msgid "Project" +msgstr "" + +#: IDF/Views/Issue.php:344 +#, php-format +msgid "%1$s %2$s Submitted %3$s Issues" +msgstr "" + +#: IDF/Views/Issue.php:348 +#, php-format +msgid "%1$s %2$s Closed Submitted %3$s Issues" +msgstr "" + +#: IDF/Views/Issue.php:352 +#, php-format +msgid "%1$s %2$s Closed Working %3$s Issues" +msgstr "" + +#: IDF/Views/Issue.php:356 +#, php-format +msgid "%1$s %2$s Working %3$s Issues" +msgstr "" + +#: IDF/Views/Issue.php:417 +msgid "Submit a new issue" +msgstr "" + +#: IDF/Views/Issue.php:433 +#, php-format +msgid "Issue %2$d has been created." +msgstr "" + +#: IDF/Views/Issue.php:490 +#, php-format +msgid "Search issues - %s" +msgstr "" + +#: IDF/Views/Issue.php:492 +#, php-format +msgid "Search closed issues - %s" +msgstr "" + +#: IDF/Views/Issue.php:539 +msgid "This table shows the found issues." +msgstr "" + +#: IDF/Views/Issue.php:604 +#, php-format +msgid "Issue %2$d: %3$s" +msgstr "" + +#: IDF/Views/Issue.php:628 +#, php-format +msgid "Issue %2$d has been updated." +msgstr "" + +#: IDF/Views/Issue.php:718 +#, php-format +msgid "View %s" +msgstr "" + +#: IDF/Views/Issue.php:745 +#, php-format +msgid "%s Closed Issues" +msgstr "" + +#: IDF/Views/Issue.php:755 +msgid "This table shows the closed issues." +msgstr "" + +#: IDF/Views/Issue.php:798 +#, php-format +msgid "%1$s Issues with Label %2$s" +msgstr "" + +#: IDF/Views/Issue.php:801 +#, php-format +msgid "%1$s Closed Issues with Label %2$s" +msgstr "" + +#: IDF/Views/Issue.php:814 +#, php-format +msgid "This table shows the issues with label %s." +msgstr "" + +#: IDF/Views/Issue.php:937 +msgid "The issue has been removed from your watch list." +msgstr "" + +#: IDF/Views/Issue.php:940 +msgid "The issue has been added to your watch list." +msgstr "" + +#: IDF/Views/Issue.php:1037 +msgid "On your watch list." +msgstr "" + +#: IDF/Views/Project.php:95 +msgid "Issues and Comments" +msgstr "" + +#: IDF/Views/Project.php:99 +msgid "Documents" +msgstr "" + +#: IDF/Views/Project.php:101 +msgid "Reviews and Patches" +msgstr "" + +#: IDF/Views/Project.php:180 +msgid "This table shows the project updates." +msgstr "" + +#: IDF/Views/Project.php:191 +msgid "Change" +msgstr "" + +#: IDF/Views/Project.php:195 +msgid "No changes were found." +msgstr "" + +#: IDF/Views/Project.php:296 +#, php-format +msgid "%s Project Summary" +msgstr "" + +#: IDF/Views/Project.php:335 +#, php-format +msgid "%s Issue Tracking Configuration" +msgstr "" + +#: IDF/Views/Project.php:344 +msgid "The issue tracking configuration has been saved." +msgstr "" + +#: IDF/Views/Project.php:381 +#, php-format +msgid "%s Downloads Configuration" +msgstr "" + +#: IDF/Views/Project.php:393 +msgid "The downloads configuration has been saved." +msgstr "" + +#: IDF/Views/Project.php:428 +#, php-format +msgid "%s Documentation Configuration" +msgstr "" + +#: IDF/Views/Project.php:437 +msgid "The documentation configuration has been saved." +msgstr "" + +#: IDF/Views/Project.php:471 +#, php-format +msgid "%s Project Members" +msgstr "" + +#: IDF/Views/Project.php:480 +msgid "The project membership has been saved." +msgstr "" + +#: IDF/Views/Project.php:503 +#, php-format +msgid "%s Tabs Access Rights" +msgstr "" + +#: IDF/Views/Project.php:517 +msgid "" +"The project tabs access rights and notification settings have been saved." +msgstr "" + +#: IDF/Views/Project.php:566 +#, php-format +msgid "%s Source" +msgstr "" + +#: IDF/Views/Project.php:580 +msgid "The project source configuration has been saved." +msgstr "" + +#: IDF/Views/Review.php:41 +#, php-format +msgid "%s Code Reviews" +msgstr "" + +#: IDF/Views/Review.php:48 +msgid "This table shows the latest reviews." +msgstr "" + +#: IDF/Views/Review.php:64 +msgid "No reviews were found." +msgstr "" + +#: IDF/Views/Review.php:94 +#, php-format +msgid "The code review %2$d has been created." +msgstr "" + +#: IDF/Views/Review.php:140 +#, php-format +msgid "Review %2$d: %3$s" +msgstr "" + +#: IDF/Views/Review.php:160 +#, php-format +msgid "Your code review %2$d has been published." +msgstr "" + +#: IDF/Views/Source.php:40 +#, php-format +msgid "%s Source Help" +msgstr "" + +#: IDF/Views/Source.php:58 +#, php-format +msgid "%s Invalid Revision" +msgstr "" + +#: IDF/Views/Source.php:82 +#, php-format +msgid "%s Ambiguous Revision" +msgstr "" + +#: IDF/Views/Source.php:107 +#, php-format +msgid "%1$s %2$s Change Log" +msgstr "" + +#: IDF/Views/Source.php:153 IDF/Views/Source.php:234 IDF/Views/Source.php:362 +#, php-format +msgid "%1$s %2$s Source Tree" +msgstr "" + +#: IDF/Views/Source.php:310 +#, php-format +msgid "%s Commit Details" +msgstr "" + +#: IDF/Views/Source.php:311 +#, php-format +msgid "%1$s Commit Details - %2$s" +msgstr "" + +#: IDF/Views/User.php:59 +msgid "Your Dashboard - Working Issues" +msgstr "" + +#: IDF/Views/User.php:62 +msgid "Your Dashboard - Submitted Issues" +msgstr "" + +#: IDF/Views/User.php:89 +msgid "No issues are assigned to you, yeah!" +msgstr "" + +#: IDF/Views/User.php:89 +msgid "All the issues you submitted are fixed, yeah!" +msgstr "" + +#: IDF/Views/User.php:121 +msgid "Your personal information has been updated." +msgstr "" + +#: IDF/Views/User.php:133 +msgid "Your Account" +msgstr "" + +#: IDF/Views/User.php:157 +msgid "The public key has been deleted." +msgstr "" + +#: IDF/Views/User.php:177 +msgid "The address has been deleted." +msgstr "" + +#: IDF/Views/User.php:200 +msgid "Confirm The Email Change" +msgstr "" + +#: IDF/Views/User.php:232 +#, php-format +msgid "Your new email address \"%s\" has been validated. Thank you!" +msgstr "" + +#: IDF/Views/Wiki.php:41 +#, php-format +msgid "%s Documentation" +msgstr "" + +#: IDF/Views/Wiki.php:48 +msgid "This table shows the documentation pages." +msgstr "" + +#: IDF/Views/Wiki.php:61 IDF/Views/Wiki.php:144 IDF/Views/Wiki.php:185 +msgid "Page Title" +msgstr "" + +#: IDF/Views/Wiki.php:63 IDF/Views/Wiki.php:103 IDF/Views/Wiki.php:146 +#: IDF/Views/Wiki.php:187 +msgid "Updated" +msgstr "" + +#: IDF/Views/Wiki.php:67 IDF/Views/Wiki.php:191 +msgid "No documentation pages were found." +msgstr "" + +#: IDF/Views/Wiki.php:88 +#, php-format +msgid "%s Documentation Resources" +msgstr "" + +#: IDF/Views/Wiki.php:94 +msgid "This table shows the resources that can be used on documentation pages." +msgstr "" + +#: IDF/Views/Wiki.php:100 +msgid "Resource Title" +msgstr "" + +#: IDF/Views/Wiki.php:107 +msgid "No resources were found." +msgstr "" + +#: IDF/Views/Wiki.php:128 +#, php-format +msgid "Documentation Search - %s" +msgstr "" + +#: IDF/Views/Wiki.php:139 +msgid "This table shows the pages found." +msgstr "" + +#: IDF/Views/Wiki.php:150 +msgid "No pages were found." +msgstr "" + +#: IDF/Views/Wiki.php:169 +#, php-format +msgid "%1$s Documentation Pages with Label %2$s" +msgstr "" + +#: IDF/Views/Wiki.php:179 +#, php-format +msgid "This table shows the documentation pages with label %s." +msgstr "" + +#: IDF/Views/Wiki.php:222 +#, php-format +msgid "The page %2$s has been created." +msgstr "" + +#: IDF/Views/Wiki.php:265 +#, php-format +msgid "The resource %2$s has been created." +msgstr "" + +#: IDF/Views/Wiki.php:409 IDF/Views/Wiki.php:448 +msgid "The old revision has been deleted." +msgstr "" + +#: IDF/Views/Wiki.php:415 IDF/Views/Wiki.php:454 +#, php-format +msgid "Delete Old Revision of %s" +msgstr "" + +#: IDF/Views/Wiki.php:496 +#, php-format +msgid "The page %2$s has been updated." +msgstr "" + +#: IDF/Views/Wiki.php:548 +#, php-format +msgid "The resource %2$s has been updated." +msgstr "" + +#: IDF/Views/Wiki.php:583 +msgid "The documentation page has been deleted." +msgstr "" + +#: IDF/Views/Wiki.php:591 +#, php-format +msgid "Delete Page %s" +msgstr "" + +#: IDF/Views/Wiki.php:623 +msgid "The documentation resource has been deleted." +msgstr "" + +#: IDF/Views/Wiki.php:631 +#, php-format +msgid "Delete Resource %s" +msgstr "" + +#: IDF/Views.php:173 IDF/Views.php:199 +msgid "Confirm Your Account Creation" +msgstr "Hesabınızın Oluşturulmasını Onaylayın" + +#: IDF/Views.php:219 +msgid "Welcome! You can now participate in the life of your project of choice." +msgstr "" + +#: IDF/Views.php:245 IDF/Views.php:269 IDF/Views.php:310 +msgid "Password Recovery" +msgstr "" + +#: IDF/Views.php:289 +msgid "" +"Welcome back! Next time, you can use your broswer options to remember the " +"password." +msgstr "" + +#: IDF/Views.php:331 +msgid "Here to Help You!" +msgstr "" + +#: IDF/Views.php:347 +msgid "InDefero Upload Archive Format" +msgstr "" + +#: IDF/Views.php:363 +msgid "InDefero API (Application Programming Interface)" +msgstr "" + +#: IDF/Wiki/Page.php:62 IDF/Wiki/Resource.php:64 +msgid "title" +msgstr "başlık" + +#: IDF/Wiki/Page.php:63 +msgid "" +"The title of the page must only contain letters, digits or the dash " +"character. For example: My-new-Wiki-Page." +msgstr "" + +#: IDF/Wiki/Page.php:71 +msgid "A one line description of the page content." +msgstr "" + +#: IDF/Wiki/Page.php:196 IDF/Wiki/PageRevision.php:196 +#, php-format +msgid "%2$s, %3$s" +msgstr "" + +#: IDF/Wiki/Page.php:198 +#, php-format +msgid "Creation of page %2$s, by %3$s" +msgstr "" + +#: IDF/Wiki/Page.php:208 +#, php-format +msgid "%1$s: Documentation page %2$s added - %3$s" +msgstr "" + +#: IDF/Wiki/PageRevision.php:48 +msgid "page" +msgstr "sayfa" + +#: IDF/Wiki/PageRevision.php:66 IDF/Wiki/ResourceRevision.php:64 +msgid "A one line description of the changes." +msgstr "" + +#: IDF/Wiki/PageRevision.php:72 +msgid "content" +msgstr "içerik" + +#: IDF/Wiki/PageRevision.php:218 IDF/Wiki/ResourceRevision.php:311 +#, php-format +msgid "Change of %2$s, by %3$s" +msgstr "" + +#: IDF/Wiki/PageRevision.php:231 +#, php-format +msgid "%1$s: Documentation page %2$s updated - %3$s" +msgstr "" + +#: IDF/Wiki/PageRevision.php:293 +#, php-format +msgid "New Documentation Page %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Wiki/PageRevision.php:297 +#, php-format +msgid "Documentation Page Changed %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Wiki/Resource.php:65 +msgid "" +"The title of the resource must only contain letters, digits, dots or the " +"dash character. For example: my-resource.png." +msgstr "" + +#: IDF/Wiki/Resource.php:72 +msgid "MIME media type" +msgstr "" + +#: IDF/Wiki/Resource.php:73 +msgid "The MIME media type of the resource." +msgstr "" + +#: IDF/Wiki/Resource.php:81 +#, fuzzy +msgid "A one line description of the resource." +msgstr "Projenin tek satırlık tanımı." + +#: IDF/Wiki/Resource.php:176 IDF/Wiki/ResourceRevision.php:308 +#, php-format +msgid "%2$s, %3$s" +msgstr "" + +#: IDF/Wiki/Resource.php:178 +#, php-format +msgid "Creation of resource %2$s, by %3$s" +msgstr "" + +#: IDF/Wiki/Resource.php:188 +#, php-format +msgid "%1$s: Documentation resource %2$s added - %3$s" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:47 +msgid "resource" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:78 +msgid "File extension" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:79 +msgid "The file extension of the uploaded resource." +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:94 +msgid "page usage" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:116 +#, php-format +msgid "id %d: %s" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:263 +#, fuzzy, php-format +msgid "Download (%s)" +msgstr "Bu dosyayı indir" + +#: IDF/Wiki/ResourceRevision.php:270 +msgid "View resource details" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:324 +#, php-format +msgid "%1$s: Documentation resource %2$s updated - %3$s" +msgstr "" diff --git a/indefero/src/IDF/locale/zh_CN/idf.po b/indefero/src/IDF/locale/zh_CN/idf.po new file mode 100644 index 0000000..0572584 --- /dev/null +++ b/indefero/src/IDF/locale/zh_CN/idf.po @@ -0,0 +1,5467 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# +# Translators: +# William MARTIN , 2011. +msgid "" +msgstr "" +"Project-Id-Version: Indefero\n" +"Report-Msgid-Bugs-To: http://projects.ceondo.com/p/indefero/issues/\n" +"POT-Creation-Date: 2012-03-22 01:16+0100\n" +"PO-Revision-Date: 2011-10-31 00:19+0000\n" +"Last-Translator: tommyd \n" +"Language-Team: LANGUAGE \n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0\n" + +#: IDF/Commit.php:55 IDF/Conf.php:54 IDF/Issue.php:52 +#: IDF/ProjectActivity.php:49 IDF/Review.php:65 IDF/Search/Occ.php:69 +#: IDF/Tag.php:52 IDF/Upload.php:49 IDF/Wiki/Page.php:54 +#: IDF/Wiki/Resource.php:56 +msgid "project" +msgstr "项目" + +#: IDF/Commit.php:63 IDF/Issue.php:67 IDF/IssueComment.php:65 +#: IDF/IssueFile.php:57 IDF/IssueRelation.php:69 IDF/Review/Comment.php:69 +#: IDF/Review.php:80 IDF/Upload.php:91 IDF/Wiki/Page.php:78 +#: IDF/Wiki/PageRevision.php:79 IDF/Wiki/Resource.php:88 +#: IDF/Wiki/ResourceRevision.php:86 +msgid "submitter" +msgstr "上传者" + +#: IDF/Commit.php:87 IDF/Issue.php:60 IDF/Review/Patch.php:60 +#: IDF/Review.php:73 IDF/Upload.php:57 IDF/Wiki/Page.php:70 +#: IDF/Wiki/PageRevision.php:65 IDF/Wiki/Resource.php:80 +#: IDF/Wiki/ResourceRevision.php:63 +msgid "summary" +msgstr "摘要" + +#: IDF/Commit.php:93 +msgid "changelog" +msgstr "修改日志" + +#: IDF/Commit.php:100 IDF/Issue.php:105 IDF/IssueComment.php:79 +#: IDF/IssueFile.php:96 IDF/IssueRelation.php:75 IDF/Review/Comment.php:90 +#: IDF/Review/FileComment.php:75 IDF/Review/Patch.php:87 IDF/Review.php:108 +#: IDF/Upload.php:112 IDF/Wiki/Page.php:100 IDF/Wiki/PageRevision.php:92 +#: IDF/Wiki/Resource.php:95 IDF/Wiki/ResourceRevision.php:101 +msgid "creation date" +msgstr "创建日期" + +#: IDF/Commit.php:238 +#, php-format +msgid "Commit %1$s, by %2$s" +msgstr "" + +#: IDF/Commit.php:337 +#, php-format +msgid "New Commit %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Conf.php:61 IDF/Gconf.php:73 +msgid "key" +msgstr "键" + +#: IDF/Conf.php:67 IDF/Gconf.php:79 IDF/ProjectActivity.php:62 +msgid "value" +msgstr "值" + +#: IDF/Diff.php:460 +msgid "Old" +msgstr "旧" + +#: IDF/Diff.php:460 +msgid "New" +msgstr "新" + +#: IDF/EmailAddress.php:49 IDF/Key.php:49 +msgid "user" +msgstr "用户" + +#: IDF/EmailAddress.php:55 +msgid "email" +msgstr "" + +#: IDF/Form/Admin/ForgeConf.php:34 +msgid "Custom forge page enabled" +msgstr "" + +#: IDF/Form/Admin/ForgeConf.php:39 IDF/Form/WikiPageCreate.php:80 +#: IDF/Form/WikiPageUpdate.php:72 +msgid "Content" +msgstr "内容" + +#: IDF/Form/Admin/LabelConf.php:40 +#, fuzzy +msgid "Predefined project labels" +msgstr "预定义问题标签" + +#: IDF/Form/Admin/LabelConf.php:55 +#, php-format +msgid "" +"The label \"%s\" is invalid: A label must only consist of alphanumeric " +"characters and dashes, and can optionally contain a \":\" with a group " +"prefix." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:38 IDF/Views/Project.php:600 +msgid "git" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:39 IDF/Views/Project.php:601 +msgid "Subversion" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:40 IDF/Views/Project.php:602 +msgid "mercurial" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:41 IDF/Views/Project.php:603 +msgid "monotone" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:49 IDF/Form/Admin/ProjectUpdate.php:44 +#: IDF/Form/ProjectConf.php:39 IDF/Views/Admin.php:86 IDF/Views/Admin.php:273 +msgid "Name" +msgstr "名字" + +#: IDF/Form/Admin/ProjectCreate.php:55 IDF/Form/TabsConf.php:101 +#: IDF/gettexttemplates/idf/base-full.html.php:5 +#: IDF/gettexttemplates/idf/base-full.html~.php:5 +#: IDF/gettexttemplates/idf/base.html.php:5 +#: IDF/gettexttemplates/idf/base.html~.php:5 +#: IDF/gettexttemplates/idf/main-menu.html.php:9 +#: IDF/gettexttemplates/idf/project-list.html.php:5 +#: IDF/gettexttemplates/idf/project-list.html.php:7 +msgid "Private project" +msgstr "私有项目" + +#: IDF/Form/Admin/ProjectCreate.php:62 +msgid "Shortname" +msgstr "短名称" + +#: IDF/Form/Admin/ProjectCreate.php:64 +msgid "" +"It must be unique for each project and composed only of letters, digits and " +"dash (-) like \"my-project\"." +msgstr "必须唯一且只能包含字母、数字和连接符(-) 如 \"my-project\"" + +#: IDF/Form/Admin/ProjectCreate.php:69 IDF/Form/Admin/ProjectUpdate.php:50 +msgid "Short description" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:70 IDF/Form/Admin/ProjectUpdate.php:51 +#: IDF/Project.php:79 +msgid "A one line description of the project." +msgstr "项目简单描述" + +#: IDF/Form/Admin/ProjectCreate.php:77 IDF/Form/Admin/ProjectUpdate.php:58 +#: IDF/Form/ProjectConf.php:56 +msgid "External URL" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:84 +msgid "Repository type" +msgstr "仓库类型" + +#: IDF/Form/Admin/ProjectCreate.php:92 +msgid "Remote Subversion repository" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:99 IDF/Form/SourceConf.php:40 +msgid "Repository username" +msgstr "仓库用户名称" + +#: IDF/Form/Admin/ProjectCreate.php:106 IDF/Form/SourceConf.php:47 +msgid "Repository password" +msgstr "仓库用户密码" + +#: IDF/Form/Admin/ProjectCreate.php:113 IDF/Form/Admin/ProjectUpdate.php:66 +msgid "Master branch" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:116 IDF/Form/Admin/ProjectUpdate.php:69 +msgid "" +"This should be a world-wide unique identifier for your project. A reverse " +"DNS notation like \"com.my-domain.my-project\" is a good idea." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:121 IDF/Form/Admin/ProjectUpdate.php:95 +#: IDF/Form/MembersConf.php:46 IDF/Form/TabsConf.php:53 +#: IDF/Form/TabsConf.php:72 +msgid "Project owners" +msgstr "项目所有者" + +#: IDF/Form/Admin/ProjectCreate.php:130 IDF/Form/Admin/ProjectUpdate.php:103 +#: IDF/Form/MembersConf.php:54 IDF/Form/TabsConf.php:52 +#: IDF/Form/TabsConf.php:78 +msgid "Project members" +msgstr "项目成员" + +#: IDF/Form/Admin/ProjectCreate.php:140 IDF/Form/Admin/ProjectUpdate.php:85 +#: IDF/Form/IssueCreate.php:168 IDF/Form/IssueUpdate.php:164 +#: IDF/Form/ProjectConf.php:73 IDF/Form/UpdateUpload.php:71 +#: IDF/Form/Upload.php:70 IDF/Form/WikiPageCreate.php:93 +#: IDF/Form/WikiPageUpdate.php:104 +msgid "Labels" +msgstr "标签" + +#: IDF/Form/Admin/ProjectCreate.php:155 +msgid "Project template" +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:157 +msgid "" +"Use the given project to initialize the new project. Access rights and " +"general configuration will be taken from the template project." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:204 +msgid "" +"Only a remote repository available through HTTP or HTTPS is allowed. For " +"example \"http://somewhere.com/svn/trunk\"." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:220 IDF/Form/Admin/ProjectUpdate.php:117 +msgid "" +"The master branch is empty or contains illegal characters, please use only " +"letters, digits, dashes and dots as separators." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:230 IDF/Form/Admin/ProjectUpdate.php:128 +msgid "This master branch is already used. Please select another one." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:241 +msgid "" +"This shortname contains illegal characters, please use only letters, digits " +"and dash (-)." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:244 +msgid "The shortname cannot start with the dash (-) character." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:247 +msgid "The shortname cannot end with the dash (-) character." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:252 +msgid "This shortname is already used. Please select another one." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:303 IDF/Form/Admin/ProjectDelete.php:78 +#: IDF/Form/Admin/ProjectUpdate.php:153 IDF/Form/Admin/UserCreate.php:106 +#: IDF/Form/Admin/UserUpdate.php:191 IDF/Form/IssueCreate.php:338 +#: IDF/Form/IssueUpdate.php:329 IDF/Form/MembersConf.php:64 +#: IDF/Form/Password.php:76 IDF/Form/Register.php:112 +#: IDF/Form/ReviewCreate.php:187 IDF/Form/ReviewFileComment.php:143 +#: IDF/Form/TabsConf.php:122 IDF/Form/UpdateUpload.php:126 +#: IDF/Form/Upload.php:149 IDF/Form/UploadArchive.php:137 +#: IDF/Form/UserAccount.php:216 IDF/Form/UserChangeEmail.php:80 +#: IDF/Form/WikiPageCreate.php:167 IDF/Form/WikiPageDelete.php:59 +#: IDF/Form/WikiPageUpdate.php:178 IDF/Form/WikiResourceCreate.php:123 +#: IDF/Form/WikiResourceDelete.php:59 IDF/Form/WikiResourceUpdate.php:124 +msgid "Cannot save the model from an invalid form." +msgstr "" + +#: IDF/Form/Admin/ProjectCreate.php:341 +msgid "" +"Click on the Project Management tab to set the description of your project." +msgstr "在项目管理里管理项目描述" + +#: IDF/Form/Admin/ProjectCreate.php:426 +msgid "This project is not available." +msgstr "" + +#: IDF/Form/Admin/ProjectDelete.php:41 +msgid "Confirmation code" +msgstr "确认码" + +#: IDF/Form/Admin/ProjectDelete.php:46 +msgid "I have made a backup of all the important data of this project." +msgstr "" + +#: IDF/Form/Admin/ProjectDelete.php:55 +msgid "" +"The confirmation code does not match. Please provide a valid confirmation " +"code to delete the project." +msgstr "" + +#: IDF/Form/Admin/ProjectDelete.php:63 +msgid "Sorry, you really need to backup your data before deletion." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:37 IDF/Form/Admin/UserUpdate.php:38 +#: IDF/Form/RegisterConfirmation.php:50 IDF/Form/UserAccount.php:40 +msgid "First name" +msgstr "名" + +#: IDF/Form/Admin/UserCreate.php:46 IDF/Form/Admin/UserUpdate.php:47 +#: IDF/Form/RegisterConfirmation.php:59 IDF/Form/UserAccount.php:49 +msgid "Last name" +msgstr "姓" + +#: IDF/Form/Admin/UserCreate.php:56 +msgid "Login" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:60 +msgid "" +"The login must be between 3 and 15 characters long and contains only letters " +"and digits." +msgstr "账号必须是3至15位的字母或数字组成的字符串" + +#: IDF/Form/Admin/UserCreate.php:69 IDF/Form/Admin/UserUpdate.php:57 +msgid "Email" +msgstr "Email" + +#: IDF/Form/Admin/UserCreate.php:71 +msgid "" +"Double check the email address as the password is sent directly to the user." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:76 IDF/Form/Admin/UserUpdate.php:67 +#: IDF/Form/UserAccount.php:66 +msgid "Language" +msgstr "语言" + +#: IDF/Form/Admin/UserCreate.php:87 IDF/Form/UserAccount.php:161 +msgid "Add a public key" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:92 +msgid "" +"Paste a SSH or monotone public key. Be careful to not provide your private " +"key here!" +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:157 +msgid "Your details to access your forge." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:189 IDF/Form/UserAccount.php:429 +#: IDF/Form/UserAccount.php:438 +#, php-format +msgid "The email \"%s\" is already used." +msgstr "" + +#: IDF/Form/Admin/UserCreate.php:198 IDF/Form/Register.php:72 +#, php-format +msgid "The login \"%s\" can only contain letters and digits." +msgstr " 账号 \"%s\" 只能包含数字和字母" + +#: IDF/Form/Admin/UserCreate.php:203 IDF/Form/Register.php:77 +#, php-format +msgid "The login \"%s\" is already used, please find another one." +msgstr "账号 \"%s\" 已存在,请换一个再试" + +#: IDF/Form/Admin/UserUpdate.php:78 +msgid "Password" +msgstr "密码" + +#: IDF/Form/Admin/UserUpdate.php:81 +msgid "Leave blank if you do not want to change the password." +msgstr "不修改密码请留空" + +#: IDF/Form/Admin/UserUpdate.php:81 +msgid "" +"The password must be hard for other people to guess, but easy for the user " +"to remember." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:89 +msgid "Confirm password" +msgstr "确认密码" + +#: IDF/Form/Admin/UserUpdate.php:100 IDF/Form/IssueCreate.php:66 +#: IDF/Form/ProjectConf.php:48 IDF/Form/ReviewCreate.php:54 +#: IDF/Form/UpdateUpload.php:51 IDF/Form/Upload.php:49 +#: IDF/Form/UserAccount.php:101 IDF/Form/WikiPageCreate.php:70 +#: IDF/Form/WikiPageUpdate.php:60 IDF/Form/WikiResourceCreate.php:54 +#: IDF/Form/WikiResourceUpdate.php:46 IDF/Views/Wiki.php:102 +msgid "Description" +msgstr "描述" + +#: IDF/Form/Admin/UserUpdate.php:109 IDF/Form/UserAccount.php:110 +msgid "Twitter username" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:119 IDF/Form/UserAccount.php:120 +msgid "Public email address" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:129 IDF/Form/UserAccount.php:130 +msgid "Website URL" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:139 IDF/Form/UserAccount.php:140 +msgid "Upload custom avatar" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:146 IDF/Form/UserAccount.php:147 +msgid "" +"An image file with a width and height not larger than 60 pixels (bigger " +"images are scaled down)." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:151 IDF/Form/UserAccount.php:152 +msgid "Remove custom avatar" +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:155 IDF/Form/UserAccount.php:156 +msgid "Tick this to delete the custom avatar." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:161 IDF/Views/Admin.php:274 +msgid "Staff" +msgstr "工作人员" + +#: IDF/Form/Admin/UserUpdate.php:164 +msgid "If you give staff rights to a user, you really need to trust him." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:172 IDF/Views/Admin.php:276 +msgid "Active" +msgstr "激活" + +#: IDF/Form/Admin/UserUpdate.php:176 +msgid "" +"If the user is not getting the confirmation email or is abusing the system, " +"you can directly enable or disable their account here." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:274 +msgid "--- is not a valid first name." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:290 +msgid "" +"A user with this email already exists, please provide another email address." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:301 IDF/Form/UserAccount.php:398 +msgid "For security reason, you cannot upload a file with this extension." +msgstr "" + +#: IDF/Form/Admin/UserUpdate.php:316 IDF/Form/UserAccount.php:461 +msgid "The passwords do not match. Please give them again." +msgstr "" + +#: IDF/Form/Field/EmailList.php:45 +msgid "Please enter one or more valid email addresses." +msgstr "" + +#: IDF/Form/IssueCreate.php:57 IDF/Form/IssueUpdate.php:46 +#: IDF/Form/ReviewCreate.php:45 IDF/Form/ReviewFileComment.php:73 +#: IDF/Form/UpdateUpload.php:42 IDF/Form/Upload.php:40 +#: IDF/gettexttemplates/idf/issues/base.html.php:3 IDF/Views/Download.php:65 +#: IDF/Views/Download.php:347 IDF/Views/Issue.php:62 IDF/Views/Issue.php:221 +#: IDF/Views/Issue.php:302 IDF/Views/Issue.php:391 IDF/Views/Issue.php:543 +#: IDF/Views/Issue.php:766 IDF/Views/Issue.php:825 IDF/Views/Review.php:58 +#: IDF/Views/User.php:83 IDF/Views/Wiki.php:62 IDF/Views/Wiki.php:145 +#: IDF/Views/Wiki.php:186 +msgid "Summary" +msgstr "摘要" + +#: IDF/Form/IssueCreate.php:76 IDF/Form/IssueUpdate.php:66 +#: IDF/Form/ReviewCreate.php:83 +msgid "The \"upload_issue_path\" configuration variable was not set." +msgstr "" + +#: IDF/Form/IssueCreate.php:86 IDF/Form/IssueUpdate.php:76 +msgid "Attach a file" +msgstr "添加附件" + +#: IDF/Form/IssueCreate.php:99 IDF/Form/IssueUpdate.php:89 +#: IDF/Form/ReviewCreate.php:103 IDF/Form/ReviewFileComment.php:83 +#: IDF/Views/Issue.php:63 IDF/Views/Issue.php:222 IDF/Views/Issue.php:304 +#: IDF/Views/Issue.php:392 IDF/Views/Issue.php:544 IDF/Views/Issue.php:767 +#: IDF/Views/Issue.php:826 IDF/Views/Review.php:59 IDF/Views/User.php:84 +msgid "Status" +msgstr "状态" + +#: IDF/Form/IssueCreate.php:108 IDF/Form/IssueUpdate.php:99 +msgid "Owner" +msgstr "所有者" + +#: IDF/Form/IssueCreate.php:118 IDF/Form/IssueUpdate.php:112 +#: IDF/Form/IssueUpdate.php:129 +msgid "This issue" +msgstr "" + +#: IDF/Form/IssueCreate.php:210 +msgid "You cannot add a label with the \"Status\" prefix to an issue." +msgstr "" + +#: IDF/Form/IssueCreate.php:211 IDF/Form/IssueCreate.php:218 +#: IDF/Form/UpdateUpload.php:110 IDF/Form/Upload.php:121 +#: IDF/Form/WikiPageCreate.php:151 IDF/Form/WikiPageUpdate.php:162 +msgid "You provided an invalid label." +msgstr "" + +#: IDF/Form/IssueCreate.php:217 IDF/Form/UpdateUpload.php:109 +#, php-format +msgid "You cannot provide more than one label from the %s class to an issue." +msgstr "" + +#: IDF/Form/IssueCreate.php:228 IDF/Form/IssueUpdate.php:194 +msgid "You need to provide a description of the issue." +msgstr "" + +#: IDF/Form/IssueCreate.php:251 IDF/Form/ReviewCreate.php:159 +msgid "You provided an invalid status." +msgstr "" + +#: IDF/Form/IssueCreate.php:272 +msgid "You provided an invalid relation type." +msgstr "" + +#: IDF/Form/IssueCreate.php:294 +#, php-format +msgid "The value \"%s\" is not a valid issue id." +msgstr "" + +#: IDF/Form/IssueCreate.php:300 +#, php-format +msgid "The issue \"%s\" does not exist." +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:86 +msgid "is related to" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:87 +msgid "blocks" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:88 +msgid "is blocked by" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:89 +msgid "duplicates" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:90 +msgid "is duplicated by" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:97 +msgid "" +"Define an issue template to hint the reporter to provide certain information" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:106 +msgid "Open issue status values" +msgstr "打开问题状态值" + +#: IDF/Form/IssueTrackingConf.php:114 +msgid "Closed issue status values" +msgstr "关闭问题状态值" + +#: IDF/Form/IssueTrackingConf.php:123 +msgid "Predefined issue labels" +msgstr "预定义问题标签" + +#: IDF/Form/IssueTrackingConf.php:125 +msgid "" +"The first \"Type:\" and \"Priority:\" entries found in this list are " +"automatically chosen as defaults for new issues." +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:133 +#, fuzzy +msgid "Each issue may have at most one label with each of these classes." +msgstr "每个问题必须包含的标签" + +#: IDF/Form/IssueTrackingConf.php:140 +msgid "Issue relations" +msgstr "" + +#: IDF/Form/IssueTrackingConf.php:142 +msgid "" +"You can define bidirectional relations like \"is related to\" or \"blocks, " +"is blocked by\". For standard relations pre-configured translations exist, " +"new relations should however be defined in a language that is understood by " +"all project members." +msgstr "" + +#: IDF/Form/IssueUpdate.php:56 IDF/Form/ReviewFileComment.php:45 +#: IDF/Form/WikiPageUpdate.php:82 IDF/Form/WikiResourceUpdate.php:66 +msgid "Comment" +msgstr "评论" + +#: IDF/Form/IssueUpdate.php:316 +msgid "No changes were entered." +msgstr "" + +#: IDF/Form/MembersConf.php:104 +#, php-format +msgid "The following login is invalid: %s." +msgid_plural "The following logins are invalid: %s." +msgstr[0] "" + +#: IDF/Form/Password.php:34 +msgid "Your login or email" +msgstr "账号或Email" + +#: IDF/Form/Password.php:35 +msgid "Provide either your login or your email to recover your password." +msgstr "使用账号或email来恢复密码" + +#: IDF/Form/Password.php:49 IDF/Form/Password.php:64 +msgid "" +"Sorry, we cannot find a user with this email address or login. Feel free to " +"try again." +msgstr "对不起,没有找到使用这个账号或email的用户" + +#: IDF/Form/Password.php:100 +msgid "Password Recovery - InDefero" +msgstr "" + +#: IDF/Form/PasswordInputKey.php:36 IDF/Form/PasswordReset.php:39 +#: IDF/Form/UserChangeEmail.php:36 +msgid "Your verification key" +msgstr "" + +#: IDF/Form/PasswordInputKey.php:50 IDF/Form/PasswordReset.php:89 +msgid "" +"We are sorry but this validation key is not valid. Maybe you should directly " +"copy/paste it from your validation email." +msgstr "" + +#: IDF/Form/PasswordInputKey.php:61 IDF/Form/PasswordReset.php:100 +msgid "" +"Sorry, but this verification key has expired, please restart the password " +"recovery sequence. For security reasons, the verification key is only valid " +"24h." +msgstr "" + +#: IDF/Form/PasswordInputKey.php:76 IDF/Form/PasswordReset.php:108 +#: IDF/Form/RegisterConfirmation.php:137 IDF/Form/RegisterInputKey.php:72 +msgid "Cannot save an invalid form." +msgstr "" + +#: IDF/Form/PasswordReset.php:45 IDF/Form/RegisterConfirmation.php:69 +#: IDF/Form/UserAccount.php:77 +msgid "Your password" +msgstr "密码" + +#: IDF/Form/PasswordReset.php:48 IDF/Form/UserAccount.php:80 +msgid "" +"Your password must be hard for other people to find it, but easy for you to " +"remember." +msgstr " " + +#: IDF/Form/PasswordReset.php:56 IDF/Form/RegisterConfirmation.php:80 +#: IDF/Form/UserAccount.php:89 +msgid "Confirm your password" +msgstr "确认密码" + +#: IDF/Form/PasswordReset.php:74 IDF/Form/RegisterConfirmation.php:122 +msgid "The two passwords must be the same." +msgstr "" + +#: IDF/Form/PasswordReset.php:77 +msgid "" +"This account is not active. Please contact the forge administrator to " +"activate it." +msgstr "" + +#: IDF/Form/ProjectConf.php:43 +msgid "Short Description" +msgstr "" + +#: IDF/Form/ProjectConf.php:85 +msgid "The \"upload_path\" configuration variable was not set." +msgstr "" + +#: IDF/Form/ProjectConf.php:90 +msgid "Update the logo" +msgstr "" + +#: IDF/Form/ProjectConf.php:92 +msgid "The logo must be a picture with a size of 32 by 32." +msgstr "" + +#: IDF/Form/ProjectConf.php:103 +msgid "Remove the current logo" +msgstr "" + +#: IDF/Form/ProjectConf.php:139 +msgid "Could not determine the size of the uploaded picture." +msgstr "" + +#: IDF/Form/ProjectConf.php:143 +msgid "The picture must have a size of 32 by 32." +msgstr "" + +#: IDF/Form/ProjectConf.php:164 +msgid "The entered URL is invalid. Only http and https URLs are allowed." +msgstr "" + +#: IDF/Form/Register.php:41 +msgid "Your login" +msgstr "账号" + +#: IDF/Form/Register.php:45 +msgid "" +"The login must be between 3 and 15 characters long and contain only letters " +"and digits." +msgstr "" + +#: IDF/Form/Register.php:53 IDF/Form/UserAccount.php:59 +msgid "Your email" +msgstr "你的Email" + +#: IDF/Form/Register.php:55 +msgid "We will never send you any unsolicited emails. We hate spam too!" +msgstr "" + +#: IDF/Form/Register.php:60 +msgid "I agree to the terms and conditions." +msgstr "同意注册协议" + +#: IDF/Form/Register.php:88 +msgid "" +"We know, this is boring, but you need to agree with the terms and conditions." +msgstr "" + +#: IDF/Form/Register.php:97 +#, php-format +msgid "" +"The email \"%1$s\" is already used. If you need to, you can recover your password." +msgstr "" + +#: IDF/Form/Register.php:148 +msgid "Confirm the creation of your account." +msgstr "" + +#: IDF/Form/RegisterConfirmation.php:40 IDF/Form/RegisterInputKey.php:36 +msgid "Your confirmation key" +msgstr "" + +#: IDF/Form/RegisterConfirmation.php:72 +msgid "" +"Your password must be hard for other people to guess, but easy for you to " +"remember." +msgstr "" + +#: IDF/Form/RegisterConfirmation.php:99 IDF/Form/RegisterInputKey.php:50 +msgid "" +"We are sorry but this confirmation key is not valid. Maybe you should " +"directly copy/paste it from your confirmation email." +msgstr "" + +#: IDF/Form/RegisterConfirmation.php:110 +#, php-format +msgid "" +"This account has already been confirmed. Maybe should you try to recover your password." +msgstr "" + +#: IDF/Form/ReviewCreate.php:74 +#: IDF/gettexttemplates/idf/source/base.html.php:5 +#: IDF/gettexttemplates/idf/source/changelog.html.php:7 +msgid "Commit" +msgstr "" + +#: IDF/Form/ReviewCreate.php:92 +msgid "Patch" +msgstr "补丁" + +#: IDF/Form/ReviewCreate.php:119 +msgid "We were not able to parse your patch. Please provide a valid patch." +msgstr "" + +#: IDF/Form/ReviewCreate.php:128 +msgid "You provided an invalid commit." +msgstr "" + +#: IDF/Form/ReviewCreate.php:202 +msgid "Initial patch to be reviewed." +msgstr "" + +#: IDF/Form/ReviewFileComment.php:56 +msgid "General comment" +msgstr "" + +#: IDF/Form/ReviewFileComment.php:113 +msgid "" +"You need to provide your general comment about the proposal, or comments on " +"at least one file." +msgstr "" + +#: IDF/Form/ReviewFileComment.php:124 +msgid "The status have been updated." +msgstr "" + +#: IDF/Form/ReviewFileComment.php:130 +msgid "This field is required." +msgstr "" + +#: IDF/Form/SourceConf.php:54 IDF/Form/UploadConf.php:70 +msgid "Webhook URL" +msgstr "" + +#: IDF/Form/TabsConf.php:38 IDF/gettexttemplates/idf/admin/base.html.php:4 +#: IDF/gettexttemplates/idf/base-full.html.php:8 +#: IDF/gettexttemplates/idf/base-full.html~.php:7 +#: IDF/gettexttemplates/idf/base.html.php:8 +#: IDF/gettexttemplates/idf/base.html~.php:7 +#: IDF/gettexttemplates/idf/downloads/base.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:14 +#: IDF/Views/Project.php:97 +msgid "Downloads" +msgstr "下载列表" + +#: IDF/Form/TabsConf.php:39 IDF/gettexttemplates/idf/base-full.html.php:12 +#: IDF/gettexttemplates/idf/base-full.html~.php:11 +#: IDF/gettexttemplates/idf/base.html.php:12 +#: IDF/gettexttemplates/idf/base.html~.php:11 +msgid "Code Review" +msgstr "代码审核" + +#: IDF/Form/TabsConf.php:40 IDF/gettexttemplates/idf/admin/base.html.php:5 +#: IDF/gettexttemplates/idf/base-full.html.php:9 +#: IDF/gettexttemplates/idf/base-full.html~.php:8 +#: IDF/gettexttemplates/idf/base.html.php:9 +#: IDF/gettexttemplates/idf/base.html~.php:8 +msgid "Documentation" +msgstr "文档" + +#: IDF/Form/TabsConf.php:41 IDF/gettexttemplates/idf/admin/base.html.php:7 +#: IDF/gettexttemplates/idf/base-full.html.php:11 +#: IDF/gettexttemplates/idf/base-full.html~.php:10 +#: IDF/gettexttemplates/idf/base.html.php:11 +#: IDF/gettexttemplates/idf/base.html~.php:10 +msgid "Source" +msgstr "源代码" + +#: IDF/Form/TabsConf.php:42 IDF/gettexttemplates/idf/base-full.html.php:10 +#: IDF/gettexttemplates/idf/base-full.html~.php:9 +#: IDF/gettexttemplates/idf/base.html.php:10 +#: IDF/gettexttemplates/idf/base.html~.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:17 +msgid "Issues" +msgstr "问题跟踪" + +#: IDF/Form/TabsConf.php:50 +msgid "Open to all" +msgstr "全部开放" + +#: IDF/Form/TabsConf.php:51 +msgid "Signed in users" +msgstr "登录用户" + +#: IDF/Form/TabsConf.php:54 +msgid "Closed" +msgstr "已关闭" + +#: IDF/Form/TabsConf.php:84 +#, fuzzy +msgid "Others" +msgstr "其它" + +#: IDF/Form/TabsConf.php:107 +msgid "Extra authorized users" +msgstr "允许访问用户(客户列表)" + +#: IDF/Form/Upload.php:59 IDF/Form/WikiResourceCreate.php:65 +#: IDF/Form/WikiResourceUpdate.php:56 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:7 +#: IDF/Views/Download.php:64 IDF/Views/Download.php:346 +msgid "File" +msgstr "文件" + +#: IDF/Form/Upload.php:87 IDF/Form/WikiResourceCreate.php:96 +#: IDF/Form/WikiResourceUpdate.php:83 +msgid "For security reasons, you cannot upload a file with this extension." +msgstr "" + +#: IDF/Form/Upload.php:120 +#, php-format +msgid "You cannot provide more than one label from the %s class to a download." +msgstr "" + +#: IDF/Form/UploadArchive.php:41 +#, fuzzy +msgid "Archive file" +msgstr "归档" + +#: IDF/Form/UploadArchive.php:67 +#, php-format +msgid "" +"For security reasons, you cannot upload a file (%s) with this extension." +msgstr "" + +#: IDF/Form/UploadArchive.php:98 +#, php-format +msgid "" +"You cannot provide more than label from the %1$s class to a download (%2$s)." +msgstr "" + +#: IDF/Form/UploadArchive.php:109 +#, php-format +msgid "" +"A file with the name \"%s\" has already been uploaded and is not marked to " +"be replaced." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:41 +msgid "The archive does not exist." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:48 +#, php-format +msgid "The archive could not be read (code %d)." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:53 +msgid "The archive does not contain a manifest.xml." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:61 +#, php-format +msgid "The archive's manifest is invalid: %s" +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:77 +#, php-format +msgid "The entry %d in the manifest is missing a file name." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:82 +#, php-format +msgid "The entry %d in the manifest is missing a summary." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:86 +msgid "The manifest must not reference itself." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:91 +#, php-format +msgid "The entry %s in the manifest does not exist in the archive." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:96 +#, php-format +msgid "The entry %s in the manifest is referenced more than once." +msgstr "" + +#: IDF/Form/UploadArchiveHelper.php:108 +#, php-format +msgid "The entry %s in the manifest has more than the six allowed labels set." +msgstr "" + +#: IDF/Form/UploadConf.php:53 +msgid "Predefined download labels" +msgstr "预定义下载标签" + +#: IDF/Form/UploadConf.php:62 +msgid "Each download may have at most one label with each of these classes" +msgstr "每个下载必须包含的标签" + +#: IDF/Form/UserAccount.php:61 +msgid "" +"If you change your email address, an email will be sent to the new address " +"to confirm it." +msgstr "如果你改变你的电子邮件地址,系统将发送一份邮件到新地址账户确认。" + +#: IDF/Form/UserAccount.php:80 +msgid "Leave blank if you do not want to change your password." +msgstr "如果不修改密码请留空" + +#: IDF/Form/UserAccount.php:166 +msgid "" +"Paste an SSH or monotone public key. Be careful to not provide your private " +"key here!" +msgstr "" + +#: IDF/Form/UserAccount.php:171 +msgid "Add a secondary email address" +msgstr "" + +#: IDF/Form/UserAccount.php:173 +msgid "You will get an email to confirm that you own the address you specify." +msgstr "" + +#: IDF/Form/UserAccount.php:200 +msgid "Confirm your new email address." +msgstr "" + +#: IDF/Form/UserAccount.php:203 +#, php-format +msgid "" +"A validation email has been sent to \"%s\" to validate the email address " +"change." +msgstr "" + +#: IDF/Form/UserAccount.php:341 +msgid "" +"Please check the key as it does not appear to be a valid SSH public key." +msgstr "" + +#: IDF/Form/UserAccount.php:363 +msgid "" +"Please check the key as it does not appear to be a valid monotone public key." +msgstr "" + +#: IDF/Form/UserAccount.php:371 +msgid "Public key looks like neither an SSH nor monotone public key." +msgstr "" + +#: IDF/Form/UserAccount.php:383 +msgid "You already have uploaded this key." +msgstr "" + +#: IDF/Form/UserChangeEmail.php:63 +msgid "" +"The validation key is not valid. Please copy/paste it from your confirmation " +"email." +msgstr "" + +#: IDF/Form/WikiConf.php:49 +msgid "Predefined documentation page labels" +msgstr "预定义文档页面标签" + +#: IDF/Form/WikiConf.php:58 +msgid "" +"Each documentation page may have at most one label with each of these classes" +msgstr "每个文档必须包含的标签" + +#: IDF/Form/WikiPageCreate.php:38 +msgid "" +"# Introduction\n" +"\n" +"Add your content here.\n" +"\n" +"\n" +"# Details\n" +"\n" +"Add your content here. Format your content with:\n" +"\n" +"* Text in **bold** or *italic*.\n" +"* Headings, paragraphs, and lists.\n" +"* Links to other [[WikiPage]].\n" +msgstr "" + +#: IDF/Form/WikiPageCreate.php:57 +msgid "PageName" +msgstr "页面名称" + +#: IDF/Form/WikiPageCreate.php:60 IDF/Form/WikiPageUpdate.php:50 +msgid "Page title" +msgstr "标题" + +#: IDF/Form/WikiPageCreate.php:66 IDF/Form/WikiPageUpdate.php:56 +msgid "" +"The page name must contains only letters, digits and the dash (-) character." +msgstr "标题只能包含字母、数字和连接号(-)" + +#: IDF/Form/WikiPageCreate.php:71 IDF/Form/WikiPageUpdate.php:61 +msgid "This one line description is displayed in the list of pages." +msgstr "描述显示在文档列表页面" + +#: IDF/Form/WikiPageCreate.php:108 IDF/Form/WikiPageUpdate.php:119 +#: IDF/Form/WikiResourceCreate.php:78 +msgid "The title contains invalid characters." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:114 IDF/Form/WikiPageUpdate.php:125 +msgid "A page with this title already exists." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:150 IDF/Form/WikiPageUpdate.php:161 +#, php-format +msgid "You cannot provide more than one label from the %s class to a page." +msgstr "" + +#: IDF/Form/WikiPageCreate.php:200 +msgid "Initial page creation" +msgstr "" + +#: IDF/Form/WikiPageDelete.php:39 +msgid "Yes, I understand that the page and all its revisions will be deleted." +msgstr "" + +#: IDF/Form/WikiPageDelete.php:50 IDF/Form/WikiResourceDelete.php:50 +msgid "You need to confirm the deletion." +msgstr "" + +#: IDF/Form/WikiPageUpdate.php:83 IDF/Form/WikiResourceUpdate.php:67 +msgid "One line to describe the changes you made." +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:40 +msgid "ResourceName" +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:44 +msgid "Resource title" +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:50 +#, fuzzy +msgid "" +"The resource name must contains only letters, digits and the dash (-) " +"character." +msgstr "标题只能包含字母、数字和连接号(-)" + +#: IDF/Form/WikiResourceCreate.php:55 IDF/Form/WikiResourceUpdate.php:47 +#, fuzzy +msgid "This one line description is displayed in the list of resources." +msgstr "描述显示在文档列表页面" + +#: IDF/Form/WikiResourceCreate.php:84 +msgid "A resource with this title already exists." +msgstr "" + +#: IDF/Form/WikiResourceCreate.php:142 +msgid "Initial resource creation" +msgstr "" + +#: IDF/Form/WikiResourceDelete.php:39 +msgid "" +"Yes, I understand that the resource and all its revisions will be deleted." +msgstr "" + +#: IDF/Form/WikiResourceUpdate.php:89 +#, php-format +msgid "" +"The mime type of the uploaded file \"%1$s\" does not match the mime type of " +"this resource \"%2$s\"" +msgstr "" + +#: IDF/Form/WikiResourceUpdate.php:97 +msgid "The current version of the resource and the uploaded file are equal." +msgstr "" + +#: IDF/Gconf.php:60 IDF/Search/Occ.php:56 +msgid "model class" +msgstr "" + +#: IDF/Gconf.php:66 IDF/Search/Occ.php:62 +msgid "model id" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/base.html.php:3 +msgid "Project Summary" +msgstr "项目摘要" + +#: IDF/gettexttemplates/idf/admin/base.html.php:6 +msgid "Issue Tracking" +msgstr "问题跟踪" + +#: IDF/gettexttemplates/idf/admin/base.html.php:8 +msgid "Project Members" +msgstr "项目成员" + +#: IDF/gettexttemplates/idf/admin/base.html.php:9 +msgid "Tabs Access and Notifications" +msgstr "访问权限与提醒" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:3 +#: IDF/gettexttemplates/idf/admin/issue-tracking.html.php:3 +#: IDF/gettexttemplates/idf/admin/wiki.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/labels.html.php:3 +msgid "" +"\n" +"

Instructions:

\n" +"

List one status value per line in desired sort-order.

\n" +"

Optionally, use an equals-sign to document the meaning of each status " +"value.

\n" +msgstr "" +"\n" +"

提示:

\n" +"

List one status value per line in desired sort-order.

\n" +"

Optionally, use an equals-sign to document the meaning of each status " +"value.

\n" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:8 +msgid "" +"

The webhook URL setting specifies an URL to which a HTTP PUT\n" +"request is sent after a new download has been added or to which a HTTP " +"POST\n" +"request is sent after an existing download has been updated.\n" +"If this field is empty, notifications are disabled.

\n" +"\n" +"

Only properly-escaped HTTP URLs are supported, for " +"example:

\n" +"\n" +"
    \n" +"
  • http://domain.com/upload
  • \n" +"
  • http://domain.com/upload?my%20param
  • \n" +"
\n" +"\n" +"

In addition, the URL may contain the following \"%\" notation, which\n" +"will be replaced with specific project values for each download:

\n" +"\n" +"
    \n" +"
  • %p - project name
  • \n" +"
  • %d - download id
  • \n" +"
\n" +"\n" +"

For example, updating download 123 of project 'my-project' with\n" +"web hook URL http://mydomain.com/%p/%d would send a POST " +"request to\n" +"http://mydomain.com/my-project/123.

" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:31 +#: IDF/gettexttemplates/idf/admin/source.html.php:30 +msgid "Web-Hook authentication key:" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/downloads.html.php:32 +#: IDF/gettexttemplates/idf/admin/issue-tracking.html.php:8 +#: IDF/gettexttemplates/idf/admin/members.html.php:13 +#: IDF/gettexttemplates/idf/admin/source.html.php:31 +#: IDF/gettexttemplates/idf/admin/summary.html.php:11 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:12 +#: IDF/gettexttemplates/idf/admin/wiki.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/forge/index.html.php:13 +#: IDF/gettexttemplates/idf/gadmin/projects/labels.html.php:8 +msgid "Save Changes" +msgstr "保存更改" + +#: IDF/gettexttemplates/idf/admin/members.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:3 +msgid "" +"\n" +"

Instructions:

\n" +"

Specify each person by its login. Each person must have already " +"registered with the given login.

\n" +"

Separate the logins with commas and/or new lines.

\n" +msgstr "" +"\n" +"

提示:

\n" +"

Specify each person by its login. Each person must have already " +"registered with the given login.

\n" +"

Separate the logins with commas and/or new lines.

\n" + +#: IDF/gettexttemplates/idf/admin/members.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:8 +msgid "" +"\n" +"

Notes:

\n" +"

A project owner may make any change to this project, including removing " +"other project owners. You need to be carefull when you give owner rights.\n" +"

A project member will not have access to the administration area but will " +"have more options available in the use of the project.

\n" +msgstr "" +"\n" +"

提示:

\n" +"

A project owner may make any change to this project, including removing " +"other project owners. You need to be carefull when you give owner rights.\n" +"

A project member will not have access to the administration area but will " +"have more options available in the use of the project.

\n" + +#: IDF/gettexttemplates/idf/admin/source.html.php:3 +msgid "You can find here the current repository configuration of your project." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:4 +msgid "" +"

The webhook URL setting specifies an URL to which a HTTP \n" +"%%hook_request_method%% request is sent after each " +"repository\n" +"commit. If this field is empty, notifications are disabled.

\n" +"\n" +"

Only properly-escaped HTTP URLs are supported, for " +"example:

\n" +"\n" +"
    \n" +"
  • http://domain.com/commit
  • \n" +"
  • http://domain.com/commit?my%20param
  • \n" +"
\n" +"\n" +"

In addition, the URL may contain the following \"%\" notation, which\n" +"will be replaced with specific project values for each commit:

\n" +"\n" +"
    \n" +"
  • %p - project name
  • \n" +"
  • %r - revision number
  • \n" +"
\n" +"\n" +"

For example, committing revision 123 to project 'my-project' with\n" +"post-commit URL http://mydomain.com/%p/%r would send a request " +"to\n" +"http://mydomain.com/my-project/123.

" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:26 +msgid "" +"The form contains some errors. Please correct them to update the source " +"configuration." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/source.html.php:27 +msgid "Repository type:" +msgstr "仓库类型:" + +#: IDF/gettexttemplates/idf/admin/source.html.php:28 +msgid "Repository access:" +msgstr "仓库地址:" + +#: IDF/gettexttemplates/idf/admin/source.html.php:29 +msgid "Repository size:" +msgstr "仓库使用空间:" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

The description of the project can be improved using the Markdown syntax.

\n" +msgstr "" +"\n" +"

提示:

\n" +"

The description of the project can be improved using the Markdown syntax.

\n" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:7 +msgid "" +"The form contains some errors. Please correct them to update the summary." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:8 +msgid "Current logo" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:9 +#: IDF/gettexttemplates/idf/base-full.html.php:4 +#: IDF/gettexttemplates/idf/base-full.html~.php:4 +#: IDF/gettexttemplates/idf/base.html.php:4 +#: IDF/gettexttemplates/idf/base.html~.php:4 +#: IDF/gettexttemplates/idf/main-menu.html.php:8 +#: IDF/gettexttemplates/idf/project-list.html.php:4 +msgid "Project logo" +msgstr "" + +#: IDF/gettexttemplates/idf/admin/summary.html.php:10 +msgid "Your project does not have a logo configured yet." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:3 +msgid "" +"This section allows you to configure project tabs access rights and " +"notifications." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:4 +msgid "" +"Tab access controls whether a single user can navigate into a particular " +"section of your project via the main menu or automatically generated object " +"links." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:5 +msgid "" +"If you mark a project as private, only the project members and " +"administrators, together with the extra authorized users you provide will " +"have access to the project as a whole. You will still be able to define " +"further access rights for the different tabs but the \"Open to all\" and " +"\"Signed in users\" will default to authorized users only." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:6 +#, fuzzy +msgid "" +"For the extra authorized user list, specify each person by its login. Each " +"person must have already registered with the given login. Separate the " +"logins with commas and/or new lines." +msgstr "" +"\n" +"

提示:

\n" +"

Specify each person by its login. Each person must have already " +"registered with the given login.

\n" +"

Separate the logins with commas and/or new lines.

\n" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:7 +msgid "" +"Only project members and admins have write access to the source. If you " +"restrict the access to the source, anonymous access is not provided and the " +"users must authenticate themselves with their password or SSH key." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:8 +#, php-format +msgid "" +"Here you can configure who should be notified about changes in a particular " +"section. You can also configure additional addresses, like the one of a " +"mailing list, that should be notified. (Keep in mind that you might have to " +"register the sender address %%from_email%% to let the " +"mailing list actually accept notification emails.) Multiple email addresses " +"must be separated through commas (',')." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:9 +msgid "" +"The form contains some errors. Please correct them to update the access " +"rights." +msgstr "" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:10 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:13 +msgid "Access Rights" +msgstr "访问权限" + +#: IDF/gettexttemplates/idf/admin/tabs.html.php:11 +#: IDF/gettexttemplates/idf/admin/tabs.html.php:14 +#, fuzzy +msgid "Notifications" +msgstr "提醒Email" + +#: IDF/gettexttemplates/idf/base-full.html.php:3 +#: IDF/gettexttemplates/idf/base-full.html~.php:3 +#: IDF/gettexttemplates/idf/base.html.php:3 +#: IDF/gettexttemplates/idf/base.html~.php:3 +#, php-format +msgid "" +"Sign in or create your account to create issues or " +"add comments" +msgstr "登录 以便提交问题或评论" + +#: IDF/gettexttemplates/idf/base-full.html.php:6 +#: IDF/gettexttemplates/idf/base.html.php:6 +#: IDF/gettexttemplates/idf/project-list.html.php:6 +msgid "External link to project" +msgstr "" + +#: IDF/gettexttemplates/idf/base-full.html.php:7 +#: IDF/gettexttemplates/idf/base-full.html~.php:6 +#: IDF/gettexttemplates/idf/base.html.php:7 +#: IDF/gettexttemplates/idf/base.html~.php:6 +msgid "Project Home" +msgstr "项目首页" + +#: IDF/gettexttemplates/idf/base-full.html.php:13 +#: IDF/gettexttemplates/idf/base-full.html~.php:12 +#: IDF/gettexttemplates/idf/base.html.php:13 +#: IDF/gettexttemplates/idf/base.html~.php:12 +msgid "Project Management" +msgstr "管理" + +#: IDF/gettexttemplates/idf/downloads/base.html.php:4 +#: IDF/gettexttemplates/idf/downloads/index.html.php:4 +#: IDF/Views/Download.php:235 +msgid "New Download" +msgstr "上传" + +#: IDF/gettexttemplates/idf/downloads/base.html.php:5 +#, fuzzy +msgid "Upload Archive" +msgstr "归档" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:3 +msgid "" +"Each file must have a distinct name and file contents\n" +"cannot be changed, so be sure to include release numbers in each file\n" +"name." +msgstr "" +"每个文件名称都必须唯一用且内容不能修改
因此请确保文件版本号包含在文件名" +"中" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:6 +#, php-format +msgid "" +"You can use the Markdown syntax for the description." +msgstr "你可以在描述中使用 Markdown 语法" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:7 +msgid "The form contains some errors. Please correct them to submit the file." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:8 +msgid "Submit File" +msgstr "提交文件" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:9 +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:8 +#: IDF/gettexttemplates/idf/downloads/delete.html.php:7 +#: IDF/gettexttemplates/idf/downloads/view.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:21 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:14 +#: IDF/gettexttemplates/idf/issues/create.html.php:14 +#: IDF/gettexttemplates/idf/issues/view.html.php:27 +#: IDF/gettexttemplates/idf/register/confirmation.html.php:7 +#: IDF/gettexttemplates/idf/register/index.html.php:8 +#: IDF/gettexttemplates/idf/register/inputkey.html.php:5 +#: IDF/gettexttemplates/idf/review/create.html.php:12 +#: IDF/gettexttemplates/idf/review/view.html.php:41 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:5 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:13 +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:7 +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:9 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:7 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:5 +msgid "Cancel" +msgstr "取消" + +#: IDF/gettexttemplates/idf/downloads/create.html.php:10 +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:9 +#: IDF/gettexttemplates/idf/register/inputkey.html.php:6 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:6 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:6 +msgid "Instructions" +msgstr "提示" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:3 +msgid "" +"The archive must include a manifest.xml file with meta " +"information about the\n" +"files to process inside the archive. All processed files must be unique or " +"replace existing files explicitely." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:5 +#, php-format +msgid "" +"You can learn more about the archive format here." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:6 +msgid "" +"The form contains some errors. Please correct them to submit the archive." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/createFromArchive.html.php:7 +#, fuzzy +msgid "Submit Archive" +msgstr "提交文件" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:3 +msgid "" +"Attention! If you want to delete a specific version of your " +"software, maybe, someone is depending on this specific version to run his " +"systems. Are you sure, you will not affect anybody when removing this file?" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:4 +#, php-format +msgid "" +"Instead of deleting the file, you could mark it as " +"deprecated." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:5 +#: IDF/gettexttemplates/idf/downloads/view.html.php:4 +#: IDF/gettexttemplates/idf/issues/attachment.html.php:4 +#: IDF/gettexttemplates/idf/issues/view.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:5 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:7 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:7 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:7 +#, php-format +msgid "by %%submitter%%" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:6 +msgid "Delete File" +msgstr "删除文件" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:8 +#: IDF/gettexttemplates/idf/downloads/view.html.php:14 +msgid "Uploaded:" +msgstr "上传时间:" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:9 +#: IDF/gettexttemplates/idf/downloads/view.html.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:29 +#: IDF/gettexttemplates/idf/review/view.html.php:27 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:12 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:14 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:14 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:15 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:17 +msgid "Updated:" +msgstr "更新:" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:10 +#: IDF/gettexttemplates/idf/downloads/view.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:6 +#: IDF/gettexttemplates/idf/listProjects.html.php:17 +msgid "Downloads:" +msgstr "下载:" + +#: IDF/gettexttemplates/idf/downloads/delete.html.php:11 +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:7 +#: IDF/gettexttemplates/idf/downloads/view.html.php:17 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:6 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:6 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:11 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:16 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:10 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:21 +#: IDF/gettexttemplates/idf/issues/view.html.php:33 +#: IDF/gettexttemplates/idf/project-list.html.php:8 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:6 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:13 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:16 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:12 +#: IDF/IssueComment.php:157 IDF/Wiki/PageRevision.php:204 +msgid "Labels:" +msgstr "标签" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:3 +msgid "A new file is available for download:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:4 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:6 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:5 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:8 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:4 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:4 +msgid "Hello," +msgstr "你好," + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:6 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:5 +msgid "Project:" +msgstr "项目:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:6 +msgid "Submitted by:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:8 +msgid "Download:" +msgstr "下载:" + +#: IDF/gettexttemplates/idf/downloads/download-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/view.html.php:31 +#: IDF/gettexttemplates/idf/user/public.html.php:4 +msgid "Description:" +msgstr "描述:" + +#: IDF/gettexttemplates/idf/downloads/download-updated-email.txt.php:3 +msgid "A file download was updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/feedfragment.xml.php:3 +msgid "Details" +msgstr "详情" + +#: IDF/gettexttemplates/idf/downloads/index.html.php:3 +#, php-format +msgid "See the deprecated files." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/index.html.php:5 +msgid "Number of files:" +msgstr "文件数目:" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:3 +msgid "" +"Attention! This file is marked as deprecated, download it " +"only if you are sure you need this specific version." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:5 +msgid "md5:" +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:6 +msgid "Changes" +msgstr "修改" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:7 +msgid "The form contains some errors. Please correct them to update the file." +msgstr "" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:8 +msgid "Update File" +msgstr "更新文件" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:10 +#: IDF/gettexttemplates/idf/downloads/view.html.php:12 +msgid "Remove this file" +msgstr "删除此文件" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:11 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:18 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:9 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:7 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:12 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:12 +msgid "Trash" +msgstr "回收" + +#: IDF/gettexttemplates/idf/downloads/view.html.php:13 +msgid "Delete this file" +msgstr "删除此文件" + +#: IDF/gettexttemplates/idf/faq-api.html.php:3 +#: IDF/gettexttemplates/idf/faq-archive-format.html.php:3 +#: IDF/gettexttemplates/idf/faq.html.php:65 +msgid "Here we are, just to help you." +msgstr "" + +#: IDF/gettexttemplates/idf/faq-api.html.php:4 +#: IDF/gettexttemplates/idf/faq-archive-format.html.php:4 +#: IDF/gettexttemplates/idf/faq.html.php:66 +#: IDF/gettexttemplates/idf/gadmin/base.html.php:4 +#: IDF/gettexttemplates/idf/index.html.php:4 IDF/Views/Admin.php:77 +#: IDF/Views.php:91 +msgid "Projects" +msgstr "项目列表" + +#: IDF/gettexttemplates/idf/faq.html.php:3 +msgid "" +"

This is simple:

\n" +"
    \n" +"
  1. Write in the comments \"This is a duplicate of issue 123\" or - if you " +"are a member of the crew -\n" +"directly add the \"duplicates\" relation with the value \"123\" below the " +"comment field. Change \"123\"\n" +"with the corresponding issue number.
  2. \n" +"
  3. Change the status of the current issue to Duplicate.
  4. \n" +"
  5. Submit the changes.
  6. \n" +"
" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:11 +msgid "" +"You need to create an account on Gravatar, this takes about 5 minutes and is free." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:12 +msgid "" +"\n" +"

To embed any previously uploaded resource into your wiki page, you can " +"use the [[!ResourceName]] syntax.

\n" +"\n" +"

The rendering of the resource can then be further fine-tuned:\n" +"

    \n" +"
  • [[!ImageResource, align=right, width=200]] renders " +"\"ImageResource\" right-aligned and scale its width to 200
  • \n" +"
  • [[!TextResource, align=center, width=300, height=300]] " +"renders \"TextResource\" in a centered, 300 by 300 px iframe
  • \n" +"
  • [[!AnyResource, preview=no]] does not render a preview of " +"the resource, but only provides a download link (default for binary " +"resources)
  • \n" +"
  • [[!BinaryResource, title=Download]] renders the download " +"link of \"BinaryResource\" with an alternative title
  • \n" +"
\n" +"

\n" +"\n" +"Resources are versioned, just like wiki pages. If you update a resource, old " +"wiki pages still show the state of the resource\n" +"at the time when the wiki page was edited. If you specifically want to " +"update a resource on a page, you therefor need to update\n" +"the resource at first and then also the page where it is referenced, " +"otherwise the change won't be visible until the next regular edit. \n" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:28 +msgid "" +"

If you have to publish many files at once for a new release, it is a very " +"tedious task\n" +"to upload them one after another and enter meta information like a summary, " +"a description or additional\n" +"labels for each of them.

\n" +"

InDefero therefore supports a special archive format that is basically a " +"standard zip file which comes with\n" +"some meta information. These meta information are kept in a special manifest " +"file, which is distinctly kept from\n" +"the rest of the files in the archive that should be published.

\n" +"

Once this archive has been uploaded, InDefero reads in the meta " +"information, unpacks the other files from\n" +"the archive and creates new individual downloads for each of them.

" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:36 +#, fuzzy, php-format +msgid "Learn more about the archive format." +msgstr "更新你的账户" + +#: IDF/gettexttemplates/idf/faq.html.php:37 +msgid "" +"The API (Application Programming Interface) is used to interact with " +"InDefero with another program. For example, this can be used to create a " +"desktop program to submit new tickets easily." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:38 +#, php-format +msgid "Learn more about the API." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:39 +#: IDF/gettexttemplates/idf/faq.html.php:45 +msgid "What are the keyboard shortcuts?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:40 +#: IDF/gettexttemplates/idf/faq.html.php:60 +msgid "How to mark an issue as duplicate?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:41 +#: IDF/gettexttemplates/idf/faq.html.php:61 +msgid "How can I display my head next to my comments?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:42 +#: IDF/gettexttemplates/idf/faq.html.php:62 +msgid "How can I embed images and other resources in my documentation pages?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:43 +#: IDF/gettexttemplates/idf/faq.html.php:63 +msgid "What is this \"Upload Archive\" functionality about?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:44 +#: IDF/gettexttemplates/idf/faq.html.php:64 +msgid "What is the API and how is it used?" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:46 +msgid "Shift+h: This help page." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:47 +msgid "If you are in a project, you have the following shortcuts:" +msgstr "如果你在一个项目中,你有以下快捷方式:" + +#: IDF/gettexttemplates/idf/faq.html.php:48 +msgid "Shift+u: Project updates." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:49 +msgid "Shift+d: Downloads." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:50 +msgid "Shift+o: Documentation." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:51 +msgid "Shift+a: Create a new issue." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:52 +msgid "Shift+i: List of open issues." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:53 +msgid "Shift+m: The issues you submitted." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:54 +msgid "Shift+w: The issues assigned to you." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:55 +msgid "Shift+s: Source." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:56 +msgid "You also have the standard access keys:" +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:57 +msgid "Alt+1: Home." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:58 +msgid "Alt+2: Skip the menus." +msgstr "" + +#: IDF/gettexttemplates/idf/faq.html.php:59 +msgid "Alt+4: Search (when available)." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:3 +msgid "Forge" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:5 +msgid "People" +msgstr "用户列表" + +#: IDF/gettexttemplates/idf/gadmin/base.html.php:6 +msgid "Usher" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/forge/base.html.php:3 +msgid "Frontpage" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/forge/index.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

You can set up a custom forge page that is used as entry page for the " +"forge instead of the plain project listing. This page is then also " +"accessible via the 'Home' link in main menu bar.

\n" +"

The content of the page can use the Markdown syntax with the Extra extension.

\n" +"

Additionally, the following macros are available:
\n" +"

    \n" +"
  • {projectlist, label=..., order=(name|activity), limit=...} - Renders a project list that can optionally be filtered by label, " +"ordered by 'name' or 'activity' and / or limited to a specific number of " +"projects.
  • \n" +"
\n" +"

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:3 +#: IDF/gettexttemplates/idf/main-menu.html.php:7 +msgid "Project List" +msgstr "项目列表" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:4 +#: IDF/Views/Admin.php:110 +#, fuzzy +msgid "Project Labels" +msgstr "项目列表" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:16 +#: IDF/gettexttemplates/idf/listProjects.html.php:6 IDF/Views/Admin.php:186 +msgid "Create Project" +msgstr "创建项目" + +#: IDF/gettexttemplates/idf/gadmin/projects/base.html.php:6 +msgid "Change Project Details" +msgstr "修改项目摘要" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:3 +msgid "" +"You can select the type of repository you want. In the case of subversion, " +"you can use optionally a remote repository instead of the local one." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:4 +msgid "" +"Once you have defined the repository type, you cannot change it." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:5 +msgid "" +"\n" +"

Specify each person by its login. Each person must have already " +"registered with the given login.

\n" +"

Separate the logins with commas and/or new lines.

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:14 +msgid "" +"The form contains some errors. Please correct them to create the project." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:15 +msgid "Provide at least one owner for the project or use a template." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:15 +msgid "Instructions:" +msgstr "提示:" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:3 +#, php-format +msgid "" +"Confirmation code to confirm the deletion of the project: \n" +"%%code%%." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:5 +msgid "" +"\n" +"Attention! Deleting a project is a one second operation\n" +"with the consequences that all the data related to the \n" +"project will be deleted.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:10 +msgid "" +"The form contains some errors. Please correct them to delete the project." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:11 +msgid "Project Statistics" +msgstr "项目统计" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:12 +msgid "Tab" +msgstr "标签" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:13 +msgid "Number" +msgstr "数字" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:15 +msgid "Code reviews" +msgstr "代码审核" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:16 +#: IDF/Views/Project.php:93 +msgid "Commits" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:18 +msgid "Documentation pages" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:19 +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:20 +msgid "Delete Project" +msgstr "删除项目" + +#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:22 +msgid "" +"For large projects, the suppression can take a while, please be patient." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:3 +msgid "Space Usage Statistics" +msgstr "空间使用率" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:4 +msgid "Repositories:" +msgstr "仓库:" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:5 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:11 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:18 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:16 +msgid "Attachments:" +msgstr "附件:" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:7 +msgid "Database:" +msgstr "数据库:" + +#: IDF/gettexttemplates/idf/gadmin/projects/index.html.php:8 +msgid "Total Forge:" +msgstr "合计:" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:13 +msgid "" +"The form contains some errors. Please correct them to update the project." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:14 +msgid "Provide at least one owner for the project." +msgstr "项目至少要有一个所有者" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:15 +msgid "Update Project" +msgstr "更新项目" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:19 +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:20 +msgid "Delete this project" +msgstr "删除此项目" + +#: IDF/gettexttemplates/idf/gadmin/projects/update.html.php:21 +msgid "You will be asked to confirm." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:3 +#: IDF/Views/Admin.php:264 +msgid "User List" +msgstr "用户列表" + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:13 +msgid "Update User" +msgstr "更新用户" + +#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:4 +msgid "Create User" +msgstr "添加用户" + +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:3 +msgid "The form contains some errors. Please correct them to create the user." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:6 +msgid "The user password will be sent by email to the user." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/createuser-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"An account on the forge has been created for you by\n" +"the administrator %%admin%%.\n" +"\n" +"Please find here your details to access the forge:\n" +"\n" +" Address: %%url%%\n" +" Login: %%user.login%%\n" +" Password: %%password%%\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:3 +#, php-format +msgid "See not validated users." +msgstr "查看 未验证用户" + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:4 +msgid "

You have here an overview of the users registered in the forge.

" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:5 +msgid "Number of users:" +msgstr "用户数量:" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:3 +msgid "" +"If you are changing the email address of the user, you\n" +"need to ensure that you are providing a valid email\n" +"address" +msgstr "如果要更改用户的电子邮件地址,你需要确保提供一个有效的电子邮件地址" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:6 +msgid "" +"If you give the user staff rights, the user will be\n" +"able to create new projects and update other non staff users.\n" +msgstr "" +"如果你给一个用户工作人员权限,他就可以\n" +"创建项目和用户并且修改其它非工作人员信息\n" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:9 +msgid "The form contains some errors. Please correct them to update the user." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:10 +#: IDF/gettexttemplates/idf/register/confirmation.html.php:4 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:4 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:4 +msgid "Login:" +msgstr "账号:" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:11 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:5 +msgid "Public Profile" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:12 +msgid "Administrative" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/base.html.php:3 +msgid "Configured servers" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/base.html.php:4 +#: IDF/Views/Admin.php:421 +msgid "Usher control" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html~.php:3 +msgid "address" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html~.php:4 +msgid "port" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/connections.html.php:5 +msgid "No connections found." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:3 +msgid "current server status:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:4 +msgid "startup" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:5 +msgid "shutdown" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:6 +msgid "reload server configuration:" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:7 +msgid "reload" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:11 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:11 +msgid "Status explanation" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:9 +msgid "active with n total open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:10 +msgid "waiting for new connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:11 +msgid "usher is being shut down, not accepting connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/control.html.php:12 +msgid "" +"usher is shut down, all local servers are stopped and not accepting " +"connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:3 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:3 +msgid "server name" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:4 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:4 IDF/Issue.php:99 +#: IDF/Review.php:102 +msgid "status" +msgstr "状态" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:5 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:5 +msgid "action" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:6 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:6 +msgid "No monotone servers configured." +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:7 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:7 +msgid "stop" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:8 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:8 +msgid "start" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:9 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:9 +msgid "kill" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:10 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:10 +msgid "active connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:12 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:12 +msgid "remote server without open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:13 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:13 +msgid "server with n open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:14 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:14 +msgid "local server running, without open connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:15 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:15 +msgid "local server not running, waiting for connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:16 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:16 +msgid "local server is about to stop, n connections still open" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:17 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:17 +msgid "local server not running, not accepting connections" +msgstr "" + +#: IDF/gettexttemplates/idf/gadmin/usher/index.html.php:18 +#: IDF/gettexttemplates/idf/gadmin/usher/index.html~.php:18 +msgid "usher is shut down, not running and not accepting connections" +msgstr "" + +#: IDF/gettexttemplates/idf/index.atom.php:3 +#, php-format +msgid "Personal project feed for %%user%%." +msgstr "" + +#: IDF/gettexttemplates/idf/index.html.php:3 +#: IDF/gettexttemplates/idf/main-menu.html.php:6 +msgid "Home" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:3 +#, php-format +msgid "Attachment to issue %%issue.id%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:5 +#: IDF/gettexttemplates/idf/review/view.html.php:35 +#: IDF/gettexttemplates/idf/source/commit.html.php:23 +#: IDF/gettexttemplates/idf/source/commit.html~.php:22 +#: IDF/gettexttemplates/idf/source/git/file.html.php:6 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:7 +msgid "Archive" +msgstr "归档" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:6 +#: IDF/gettexttemplates/idf/source/git/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:12 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:12 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:10 +msgid "Download this file" +msgstr "下载此文件" + +#: IDF/gettexttemplates/idf/issues/attachment.html.php:7 +#: IDF/gettexttemplates/idf/issues/view.html.php:28 +#: IDF/gettexttemplates/idf/review/view.html.php:26 +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:13 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:14 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:16 +msgid "Created:" +msgstr "创建:" + +#: IDF/gettexttemplates/idf/issues/base.html.php:4 +msgid "All Issues" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/base.html.php:5 +msgid "My Issues" +msgstr "我的问题" + +#: IDF/gettexttemplates/idf/issues/base.html.php:6 +msgid "My watch list" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/base.html.php:7 +#: IDF/gettexttemplates/idf/issues/by-label.html.php:6 +#: IDF/gettexttemplates/idf/issues/index.html.php:5 +#: IDF/gettexttemplates/idf/issues/project-watchlist.html.php:5 +#: IDF/gettexttemplates/idf/issues/search.html.php:8 +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:5 +msgid "New Issue" +msgstr "新问题" + +#: IDF/gettexttemplates/idf/issues/base.html.php:8 +#: IDF/gettexttemplates/idf/wiki/base.html.php:9 +msgid "Search" +msgstr "搜索" + +#: IDF/gettexttemplates/idf/issues/base.html.php:9 +msgid "Back to the issue" +msgstr "返回问题" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:3 +#, php-format +msgid "" +"

Open issues: %%open%%

\n" +"

Closed issues: %%closed%%

\n" +msgstr "" +"

开放的问题: %%open%%

\n" +"

已关闭的问题: %%closed%%\n" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:7 +msgid "Label:" +msgstr "标签:" + +#: IDF/gettexttemplates/idf/issues/by-label.html.php:8 +msgid "Completion:" +msgstr "完成率:" + +#: IDF/gettexttemplates/idf/issues/create.html.php:3 +msgid "" +"

When you submit the issue do not forget to provide the following " +"information:

\n" +"
    \n" +"
  • The steps to reproduce the problem.
  • \n" +"
  • The version of the software and your operating system.
  • \n" +"
  • Any information that can help the developers to solve the issue.
  • \n" +"
  • Do not provide any password or confidential information!
  • \n" +"
" +msgstr "" +"

提交的问题是,不要忘记提供以下资料:

\n" +"
    \n" +"
  • 如何发现此问题,怎么操作可以遇到此问题
  • \n" +"
  • 你使用的软件版本和操作系统版本
  • \n" +"
  • 任何可以帮助开发人员解决问题的信息
  • \n" +"
" + +#: IDF/gettexttemplates/idf/issues/create.html.php:10 +msgid "The form contains some errors. Please correct them to submit the issue." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/create.html.php:11 +#: IDF/gettexttemplates/idf/issues/create.html.php:13 +#: IDF/gettexttemplates/idf/issues/view.html.php:24 +#: IDF/gettexttemplates/idf/issues/view.html.php:26 +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:5 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:5 +msgid "Preview" +msgstr "预览" + +#: IDF/gettexttemplates/idf/issues/create.html.php:12 +msgid "Submit Issue" +msgstr "提交问题" + +#: IDF/gettexttemplates/idf/issues/create.html.php:15 +#: IDF/gettexttemplates/idf/issues/view.html.php:34 +msgid "Attach file" +msgstr "附件" + +#: IDF/gettexttemplates/idf/issues/create.html.php:16 +#: IDF/gettexttemplates/idf/issues/create.html.php:17 +#: IDF/gettexttemplates/idf/issues/view.html.php:35 +#: IDF/gettexttemplates/idf/issues/view.html.php:36 +msgid "Attach another file" +msgstr "其它附件" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:3 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:3 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:13 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:12 +#: IDF/gettexttemplates/idf/issues/view.html.php:18 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:3 +#: IDF/gettexttemplates/idf/review/view.html.php:38 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:11 +#: IDF/IssueComment.php:151 +msgid "Summary:" +msgstr "摘要:" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:4 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:4 +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:8 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:14 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:13 +#: IDF/gettexttemplates/idf/issues/view.html.php:19 +#: IDF/gettexttemplates/idf/issues/view.html.php:30 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:4 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/view.html.php:39 IDF/IssueComment.php:153 +msgid "Status:" +msgstr "状态" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:5 +#: IDF/gettexttemplates/idf/issues/feedfragment.xml~.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:15 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:14 +#: IDF/gettexttemplates/idf/issues/view.html.php:20 +#: IDF/gettexttemplates/idf/issues/view.html.php:31 +#: IDF/gettexttemplates/idf/review/feedfragment.xml.php:5 +#: IDF/IssueComment.php:155 +msgid "Owner:" +msgstr "所有者" + +#: IDF/gettexttemplates/idf/issues/feedfragment.xml.php:7 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:17 +#: IDF/gettexttemplates/idf/issues/view.html.php:22 IDF/IssueComment.php:159 +msgid "Relations:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/forge-watchlist.html.php:3 +#: IDF/gettexttemplates/idf/issues/index.html.php:3 +#: IDF/gettexttemplates/idf/issues/project-watchlist.html.php:3 +#, php-format +msgid "" +"

Open issues: %%open%%

\n" +"

Closed issues: %%closed%%

" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:3 +#, fuzzy +msgid "A new issue has been created and assigned to you:" +msgstr "有一个新问题需要你来处理:" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:4 +#, fuzzy +msgid "A new issue has been created:" +msgstr "有一个新问题需要你来处理:" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:9 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:8 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:11 +msgid "Reported by:" +msgstr "报告人:" + +#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:12 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:19 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:17 +msgid "Issue:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:3 +#, fuzzy +msgid "The following issue you are owning has been updated:" +msgstr "你关注的问题更新了:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:4 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:3 +msgid "The following issue has been updated:" +msgstr "你关注的问题更新了:" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:5 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:4 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:4 +#, php-format +msgid "By %%who%%, %%c.creation_dtime%%:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:10 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:9 +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:8 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:12 +msgid "URL:" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt.php:12 +#: IDF/gettexttemplates/idf/issues/issue-updated-email.txt~.php:11 +msgid "Comments (last first):" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/search.html.php:3 +#, php-format +msgid "" +"\n" +"

Found open issues: %%open%%

\n" +"

Found closed issues: %%closed" +"%%

" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/search.html.php:6 +#, php-format +msgid "" +"

Label:\n" +"%%tag.class%%:" +"%%tag.name%%

" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:3 +msgid "View all open issues." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:4 +#, fuzzy +msgid "Create an issue." +msgstr "添加用户" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:5 +#, php-format +msgid "" +"The issue tracker is empty.
Create your " +"first issue." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:6 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:4 +#, php-format +msgid "Unresolved: By %%key%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:7 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:5 +msgid "Status Summary" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html.php:8 +#: IDF/gettexttemplates/idf/issues/summary.html~.php:6 +msgid "Unresolved: By Assignee" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/summary.html~.php:3 +#, php-format +msgid "" +"The issue tracker is empty.
You can create your first issue here." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:3 +#, php-format +msgid "" +"See the %%nb_submit_closed%% closed." +msgid_plural "" +"See the %%nb_submit_closed%% closed." +msgstr[0] "" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:4 +#, php-format +msgid "" +"See the %%nb_owner_closed%% closed." +msgid_plural "" +"See the %%nb_owner_closed%% closed." +msgstr[0] "" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:6 +#: IDF/gettexttemplates/idf/user/dashboard.html.php:7 +msgid "Submitted issues:" +msgstr "发布的问题:" + +#: IDF/gettexttemplates/idf/issues/userIssues.html.php:7 +#: IDF/gettexttemplates/idf/user/dashboard.html.php:6 +msgid "Working issues:" +msgstr "处理中的问题:" + +#: IDF/gettexttemplates/idf/issues/view.html.php:3 +#, php-format +msgid "Reported by %%submitter%%, %%c.creation_dtime%%" +msgstr "由 %%submitter%%, 报告于 %%c.creation_dtime%%" + +#: IDF/gettexttemplates/idf/issues/view.html.php:4 +#: IDF/gettexttemplates/idf/review/view.html.php:22 +#, php-format +msgid "" +"Comment %%i%% by %%submitter%%, %%c.creation_dtime%%" +msgstr "" +"评论 %%i%% 由 %%submitter%%, 发表于 %%c." +"creation_dtime%%" + +#: IDF/gettexttemplates/idf/issues/view.html.php:5 +#, php-format +msgid "Sign in to reply to this comment." +msgstr "登录 后回复此评论" + +#: IDF/gettexttemplates/idf/issues/view.html.php:6 +msgid "" +"This issue is marked as closed, add a comment only if you think this issue " +"is still valid and more work is needed to fully fix it." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:8 +#, php-format +msgid "%%interested%% person" +msgid_plural "%%interested%% persons" +msgstr[0] "%%interested%% 人" + +#: IDF/gettexttemplates/idf/issues/view.html.php:9 +#, php-format +msgid "This issue %%verb%%" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:10 +msgid "Remove this issue from your watch list" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:11 +msgid "Add this issue to your watch list" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:12 +msgid "View the previous closed issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:13 +msgid "View the previous open issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:14 +msgid "View the next closed issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:15 +msgid "View the next open issue" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:16 +msgid "download" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:17 +msgid "view" +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:23 +msgid "The form contains some errors. Please correct them to change the issue." +msgstr "" + +#: IDF/gettexttemplates/idf/issues/view.html.php:25 +msgid "Submit Changes" +msgstr "提交修改" + +#: IDF/gettexttemplates/idf/issues/view.html.php:32 +msgid "Followed by:" +msgstr "关注:" + +#: IDF/gettexttemplates/idf/listProjects.html.php:3 +#, fuzzy, php-format +msgid "1 project" +msgid_plural "%%label.project_count%% projects" +msgstr[0] "项目" + +#: IDF/gettexttemplates/idf/listProjects.html.php:4 +#, php-format +msgid "Remove filter for %%tag%%" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:5 +msgid "No projects managed with InDefero were found." +msgstr "没有合适项目" + +#: IDF/gettexttemplates/idf/listProjects.html.php:7 +msgid "Filter projects by label" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:8 +#, fuzzy +msgid "No projects with labels found." +msgstr "没有项目" + +#: IDF/gettexttemplates/idf/listProjects.html.php:9 +msgid "Order" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:10 +#, fuzzy +msgid "By name" +msgstr "名称" + +#: IDF/gettexttemplates/idf/listProjects.html.php:11 +msgid "By activity" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:12 +msgid "Filtered project stats" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:13 +msgid "Members:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:14 +msgid "Issues:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:15 +msgid "Commits:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:16 +msgid "Documentations:" +msgstr "" + +#: IDF/gettexttemplates/idf/listProjects.html.php:18 +msgid "Code reviews:" +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:3 +#, fuzzy, php-format +msgid "" +"You can create an account if you don't have one yet." +msgstr "你可以在描述中使用 Markdown 语法" + +#: IDF/gettexttemplates/idf/login_form.html.php:4 +msgid "What is your account information?" +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:5 +msgid "My login is" +msgstr "账号" + +#: IDF/gettexttemplates/idf/login_form.html.php:6 +msgid "My password is" +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:7 +msgid "Sign in" +msgstr "登录" + +#: IDF/gettexttemplates/idf/login_form.html.php:8 +msgid "I lost my password!" +msgstr "忘记密码!" + +#: IDF/gettexttemplates/idf/login_form.html.php:9 +msgid "Welcome." +msgstr "" + +#: IDF/gettexttemplates/idf/login_form.html.php:10 +msgid "It takes less than a minute to create your account." +msgstr "" + +#: IDF/gettexttemplates/idf/main-menu.html.php:3 +#, php-format +msgid "" +"Welcome, %%user%%." +msgstr "" +"欢迎,%%user%%" + +#: IDF/gettexttemplates/idf/main-menu.html.php:4 +msgid "Sign Out" +msgstr "退出" + +#: IDF/gettexttemplates/idf/main-menu.html.php:5 +msgid "Sign in or create your account" +msgstr "登录或创建新用户" + +#: IDF/gettexttemplates/idf/main-menu.html.php:10 IDF/Views/Admin.php:40 +msgid "Forge Management" +msgstr "系统管理" + +#: IDF/gettexttemplates/idf/main-menu.html.php:11 +msgid "Help and accessibility features" +msgstr "帮助和辅助功能" + +#: IDF/gettexttemplates/idf/main-menu.html.php:12 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:14 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:14 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:15 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:13 +msgid "Help" +msgstr "帮助" + +#: IDF/gettexttemplates/idf/project/home.html.php:3 +#: IDF/gettexttemplates/idf/project/timeline.html.php:4 IDF/Views.php:46 +msgid "Welcome" +msgstr "欢迎" + +#: IDF/gettexttemplates/idf/project/home.html.php:4 +#: IDF/gettexttemplates/idf/project/timeline.html.php:5 +msgid "Latest Updates" +msgstr "项目更新" + +#: IDF/gettexttemplates/idf/project/home.html.php:5 +msgid "Featured Downloads" +msgstr "特色下载" + +#: IDF/gettexttemplates/idf/project/home.html.php:6 +#, fuzzy +msgid "Show more featured downloads" +msgstr "特色下载" + +#: IDF/gettexttemplates/idf/project/home.html.php:7 +#: IDF/gettexttemplates/idf/project/home.html.php:10 +msgid "show more..." +msgstr "显示更多..." + +#: IDF/gettexttemplates/idf/project/home.html.php:8 +msgid "Featured Documentation" +msgstr "" + +#: IDF/gettexttemplates/idf/project/home.html.php:9 +msgid "Show more featured documentation" +msgstr "" + +#: IDF/gettexttemplates/idf/project/home.html.php:11 +msgid "Development Team" +msgstr "开发团队" + +#: IDF/gettexttemplates/idf/project/home.html.php:12 +msgid "Admins" +msgstr "管理员" + +#: IDF/gettexttemplates/idf/project/home.html.php:13 +msgid "Happy Crew" +msgstr "成员" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:3 +msgid "Latest updates" +msgstr "最近更新" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:6 +#: IDF/Views/Project.php:90 +msgid "All Updates" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:7 +msgid "Filter by type" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:8 +msgid "Subscribe to this timeline" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:9 +msgid "RSS" +msgstr "" + +#: IDF/gettexttemplates/idf/project/timeline.html.php:10 +msgid "Atom feed" +msgstr "" + +#: IDF/gettexttemplates/idf/project-list.html.php:3 +msgid "Project activity: %%activity%%%" +msgstr "" + +#: IDF/gettexttemplates/idf/project-list.html.php:9 +msgid "n/a" +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation-email.txt.php:3 +#, php-format +msgid "" +"Hello,\n" +"\n" +"You have requested the creation of an account to\n" +"participate in the life of a software project.\n" +"\n" +"To confirm the account please follow this link:\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following confirmation key:\n" +"\n" +"%%key%%\n" +"\n" +"If you are not interested any longer in taking\n" +"part in the life of the software project or if\n" +"you can't remember having requested the creation\n" +"of an account, please excuse us and simply ignore\n" +"this email. \n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:3 +#: IDF/gettexttemplates/idf/user/myaccount.html.php:3 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:3 +msgid "Oops, please check the form for errors." +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:5 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:5 +msgid "Email:" +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:6 +msgid "Enable Your Account" +msgstr "" + +#: IDF/gettexttemplates/idf/register/confirmation.html.php:8 +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:8 +msgid "" +"This is the last step, but just be sure to have the cookies enabled to log in afterwards." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:3 +#, fuzzy +msgid "" +"Read the terms and conditions – " +"basically \"Please be nice, we respect you\"." +msgstr "" +"阅读 注册协议 – jerry " +"\"请善用此系统\"." + +#: IDF/gettexttemplates/idf/register/index.html.php:4 +#, php-format +msgid "" +"If you have just forgotten your login information, then there is no need to " +"create a new account. You can just recover your login " +"name and password." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:5 +#, php-format +msgid "" +"With your account, you will able to participate in the life of all the " +"projects hosted here. Participating in a software project must be fun, so if " +"you have troubles, you can let us know about your issues " +"at anytime!" +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:6 +msgid "Oops, please check the provided login and email address to register." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:7 IDF/Views.php:137 +msgid "Create Your Account" +msgstr "注册" + +#: IDF/gettexttemplates/idf/register/index.html.php:9 +msgid "" +"Be sure to provide a valid email address, as we are sending a validation " +"link by email." +msgstr "" + +#: IDF/gettexttemplates/idf/register/index.html.php:10 +msgid "Did you know?" +msgstr "你知道吗?" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:3 +#: IDF/gettexttemplates/idf/user/changeemail.html.php:3 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:3 +msgid "Oops, we found an error in the form." +msgstr "" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:4 +msgid "Confirm Your Account" +msgstr "确认你的账户" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:7 +msgid "" +"Use your email software to read your emails and open your confirmation " +"email. Either click directly on the confirmation link or copy/paste the " +"confirmation key in the box and submit the form." +msgstr "" + +#: IDF/gettexttemplates/idf/register/inputkey.html.php:8 +msgid "" +"Just after providing the confirmation key, you will be able to set your " +"password and start using this website fully." +msgstr "" + +#: IDF/gettexttemplates/idf/review/base-full.html.php:3 +#: IDF/gettexttemplates/idf/review/base.html.php:3 +msgid "Open Reviews" +msgstr "开放的审核" + +#: IDF/gettexttemplates/idf/review/base.html.php:4 +#: IDF/gettexttemplates/idf/review/create.html.php:11 +#: IDF/gettexttemplates/idf/review/index.html.php:3 IDF/Views/Review.php:83 +msgid "Start Code Review" +msgstr "添加代码审核" + +#: IDF/gettexttemplates/idf/review/create.html.php:3 +msgid "" +"

To start a code review, you need to provide:

\n" +"
    \n" +"
  • A commit or revision of the current code in the repository from which " +"you started your work.
  • \n" +"
  • A patch describing your changes with respect to the reference commit.\n" +"
  • Check your patch does not provide any password or confidential " +"information!
  • \n" +"
" +msgstr "" + +#: IDF/gettexttemplates/idf/review/create.html.php:9 +msgid "" +"The form contains some errors. Please correct them to submit the code review." +msgstr "" + +#: IDF/gettexttemplates/idf/review/create.html.php:10 +msgid "" +"Select the commit against which you created your patch to be sure it applies " +"correctly." +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:3 +msgid "The following review has been created:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-created-email.txt.php:10 +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:16 +msgid "Review:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:3 +msgid "The following review has been updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:5 +#, php-format +msgid "" +"By %%who%%, %%c.creation_dtime%%, on file:\n" +"%%c.cfile%%\n" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:14 +msgid "General comments (last first):" +msgstr "" + +#: IDF/gettexttemplates/idf/review/review-updated-email.txt.php:15 +msgid "Detailed file comments (last first):" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:3 +msgid "" +"Code review is a process in which\n" +"after or before changes are commited into the code repository,\n" +"different people discuss the code changes. The goal is\n" +"to improve the quality of the code and the\n" +"contributions, as such, you must be pragmatic when writing\n" +"your review. Correctly mention the line numbers (in the old or in the\n" +"new file) and try to keep a good balance between seriousness and fun.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:11 +msgid "" +"\n" +"Proposing code for review is intimidating, you know\n" +"you will receive critics, so please, as a reviewer, keep this\n" +"process fun, use it to help your contributor learn your\n" +"coding standards and the structure of the code and make them want\n" +"to propose more contributions.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:18 +#: IDF/gettexttemplates/idf/source/commit.html.php:3 +#: IDF/gettexttemplates/idf/source/commit.html~.php:3 +#, php-format +msgid "%%ndiff%% diff" +msgid_plural "%%ndiff%% diffs" +msgstr[0] "" + +#: IDF/gettexttemplates/idf/review/view.html.php:19 +#, php-format +msgid "%%nc%% comment" +msgid_plural "%%nc%% comments" +msgstr[0] "" + +#: IDF/gettexttemplates/idf/review/view.html.php:20 +#, php-format +msgid "" +"Comment %%i%% by %%who%%, " +"%%c.creation_dtime%%" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:21 +#, php-format +msgid "Your comments on the changes in file %%file%%:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:23 +#, php-format +msgid "Sign in to participate in the review." +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:24 +msgid "" +"The form contains some errors. Please correct them to submit your review." +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:25 +msgid "How to Participate in a Code Review" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:28 +#: IDF/gettexttemplates/idf/source/commit.html.php:5 +#: IDF/gettexttemplates/idf/source/commit.html~.php:5 +msgid "Author:" +msgstr "作者:" + +#: IDF/gettexttemplates/idf/review/view.html.php:29 +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:5 +#: IDF/gettexttemplates/idf/source/commit.html.php:7 +#: IDF/gettexttemplates/idf/source/commit.html~.php:7 +msgid "Commit:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:30 +#: IDF/gettexttemplates/idf/source/commit.html.php:8 +#: IDF/gettexttemplates/idf/source/commit.html~.php:8 +msgid "View corresponding source tree" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:32 +msgid "Reviewers:" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:33 +msgid "No reviewers at the moment." +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:34 +msgid "Files:" +msgstr "文件:" + +#: IDF/gettexttemplates/idf/review/view.html.php:36 +#: IDF/gettexttemplates/idf/source/commit.html.php:24 +#: IDF/gettexttemplates/idf/source/commit.html~.php:23 +msgid "Download the corresponding diff file" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:37 +msgid "General Comments" +msgstr "" + +#: IDF/gettexttemplates/idf/review/view.html.php:40 +msgid "Submit Code Review" +msgstr "" + +#: IDF/gettexttemplates/idf/source/base.html.php:3 +msgid "Source Tree" +msgstr "源码" + +#: IDF/gettexttemplates/idf/source/base.html.php:4 +msgid "Change Log" +msgstr "修改日志" + +#: IDF/gettexttemplates/idf/source/base.html.php:6 +msgid "How To Get The Code" +msgstr "获取代码" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:3 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:8 +#: IDF/Views/Project.php:190 +msgid "Age" +msgstr "时间" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:4 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:8 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:10 +msgid "Message" +msgstr "消息" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:5 +msgid "Parent:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:6 +#: IDF/gettexttemplates/idf/source/commit.html.php:10 +#: IDF/gettexttemplates/idf/source/commit.html~.php:10 +msgid "View corresponding commit" +msgstr "" + +#: IDF/gettexttemplates/idf/source/changelog.html.php:8 +msgid "by" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:3 +msgid "A new commit has been created:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:7 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:6 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:8 +msgid "Created by:" +msgstr "创建于:" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:8 +msgid "Created at:" +msgstr "创建于:" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:8 +msgid "Content:" +msgstr "内容:" + +#: IDF/gettexttemplates/idf/source/commit-created-email.txt.php:10 +msgid "Commit details:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:4 +#: IDF/gettexttemplates/idf/source/commit.html~.php:4 +msgid "Date:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:6 +#: IDF/gettexttemplates/idf/source/commit.html~.php:6 +msgid "Branch:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:9 +#: IDF/gettexttemplates/idf/source/commit.html~.php:9 +msgid "Parents:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:11 +#: IDF/gettexttemplates/idf/source/commit.html~.php:11 +msgid "Message:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:12 +#: IDF/gettexttemplates/idf/source/commit.html~.php:12 +#: IDF/gettexttemplates/idf/wiki/feedfragment-page.xml.php:3 +#: IDF/gettexttemplates/idf/wiki/feedfragment-resource.xml.php:3 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:10 +msgid "Changes:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:13 +#: IDF/gettexttemplates/idf/source/commit.html~.php:13 +msgid "deleted" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:14 +#: IDF/gettexttemplates/idf/source/commit.html.php:18 +#: IDF/gettexttemplates/idf/source/commit.html~.php:14 +#: IDF/gettexttemplates/idf/source/commit.html~.php:17 +msgid "full" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:15 +#: IDF/gettexttemplates/idf/source/commit.html~.php:15 +msgid "renamed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:16 +msgid "copied" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:17 +#: IDF/gettexttemplates/idf/source/commit.html~.php:16 +msgid "added" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:19 +#: IDF/gettexttemplates/idf/source/commit.html~.php:18 +msgid "modified" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:20 +msgid "properties changed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:21 +#: IDF/gettexttemplates/idf/source/commit.html~.php:20 +msgid "removed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html.php:22 +#: IDF/gettexttemplates/idf/source/commit.html~.php:21 +msgid "File differences" +msgstr "" + +#: IDF/gettexttemplates/idf/source/commit.html~.php:19 +msgid "properies changed" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:3 +#, php-format +msgid "" +"The revision identifier %%commit%% is ambiguous and can be\n" +"expanded to multiple valid revisions - please choose one:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:5 +msgid "Title" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:6 +msgid "Author" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:7 +msgid "Date" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:8 +msgid "Branch" +msgstr "" + +#: IDF/gettexttemplates/idf/source/disambiguate_revision.html.php:9 +msgid "Revision" +msgstr "" + +#: IDF/gettexttemplates/idf/source/feedfragment.xml.php:3 +#, php-format +msgid "%%cproject.name%%: Commit %%c.scm_id%%" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:3 +msgid "Branches" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:4 +msgid "filter branches" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:5 +msgid "Tags" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:6 +#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:6 +msgid "filter tags" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/file.html.php:3 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:3 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:4 +#, php-format +msgid "" +"Source at commit %%commit%% created " +"%%cobject.date%%." +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/file.html.php:4 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:4 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:4 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:5 +#, php-format +msgid "By %%cobject.author%%, %%cobject.title%%" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/file.html.php:5 +#: IDF/gettexttemplates/idf/source/git/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/file.html.php:5 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:5 +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:6 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:6 +msgid "Root" +msgstr "Root" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the git software to manage the source\n" +"code." +msgstr " %%project%% 项目使用 git 管理源代码" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:6 +#, php-format +msgid "" +"You may need to provide your SSH key. The " +"synchronization of your SSH key can take a couple of minutes. You can learn " +"more about SSH key authentication." +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:6 +msgid "To make a first commit in the repository, perform the following steps:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:8 +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:7 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:7 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:7 +#, php-format +msgid "Find here more details on how to access %%project%% source code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:9 +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:8 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:8 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:8 +msgid "Command-Line Access" +msgstr "获取代码" + +#: IDF/gettexttemplates/idf/source/git/help.html.php:10 +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:9 +msgid "First Commit" +msgstr "" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:9 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:11 +#: IDF/Views/Download.php:66 IDF/Views/Download.php:348 +msgid "Size" +msgstr "大小" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:10 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:11 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:12 +msgid ":" +msgstr ":" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:12 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:13 +msgid "Download this version" +msgstr "下载这个版本" + +#: IDF/gettexttemplates/idf/source/git/tree.html.php:13 +#: IDF/gettexttemplates/idf/source/mercurial/tree.html.php:13 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:14 +msgid "or" +msgstr "或" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:3 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:3 +#, php-format +msgid "" +"The branch or revision %%commit%% is not valid or does not exist\n" +"in this repository." +msgstr "" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:5 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:5 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:5 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:5 +msgid "The following list shows all available branches:" +msgstr "" + +#: IDF/gettexttemplates/idf/source/invalid_revision.html.php:6 +#: IDF/gettexttemplates/idf/source/invalid_revision.html~.php:6 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:6 +#, php-format +msgid "" +"If this is a new repository, the reason for this error\n" +"could be that you have not committed and / or pushed any change so far.\n" +"In this case please take a look at the Help page\n" +"how to access your repository." +msgstr "" + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the Mercurial software to manage the source\n" +"code." +msgstr "%%project%% 项目使用 Mercurial 管理源代码" + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:6 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:6 +#, php-format +msgid "" +"To get write access to the repository, you need to use your username and " +"your extra password." +msgstr " " + +#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/help.html.php:9 +msgid "Write Access Authentication" +msgstr "提交代码认证" + +#: IDF/gettexttemplates/idf/source/mtn/file.html.php:3 +#: IDF/gettexttemplates/idf/source/mtn/tree.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:3 +#, php-format +msgid "Property %%prop%% set to %%val%%" +msgstr "" + +#: IDF/gettexttemplates/idf/source/mtn/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the monotone software to manage the source\n" +"code." +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/changelog.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/commit.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/commit.html~.php:3 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:9 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:14 +msgid "Revision:" +msgstr "版本:" + +#: IDF/gettexttemplates/idf/source/svn/changelog.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/commit.html.php:4 +#: IDF/gettexttemplates/idf/source/svn/commit.html~.php:4 +#: IDF/gettexttemplates/idf/source/svn/file.html.php:10 +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:15 +msgid "Switch" +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/help.html.php:3 +#, php-format +msgid "" +"The team behind %%project%% is using\n" +"the subversion software to manage the source\n" +"code." +msgstr "%%project%% 项目使用 subversion 管理源代码" + +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html.php:3 +#: IDF/gettexttemplates/idf/source/svn/invalid_revision.html~.php:3 +#, php-format +msgid "" +"The revision %%commit%% is not valid or does not exist\n" +"in this repository." +msgstr "" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:9 +msgid "Rev" +msgstr "版本" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:16 +msgid "Branches:" +msgstr "分支" + +#: IDF/gettexttemplates/idf/source/svn/tree.html.php:17 +msgid "Tags:" +msgstr "标签:" + +#: IDF/gettexttemplates/idf/user/changeemail-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"To confirm that you want %%email%%\n" +"to be your new email address, just follow this link:\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following verification key:\n" +"\n" +"%%key%%\n" +"\n" +"If you do not want to change your email address, \n" +"just ignore this message.\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/user/changeemail.html.php:4 +msgid "Confirm Your New Email Address" +msgstr "" + +#: IDF/gettexttemplates/idf/user/changeemail.html.php:7 +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:7 +msgid "" +"Use your email software to read your emails and open your verification " +"email. Either click directly on the verification link or copy/paste the " +"verification key in the box and submit the form." +msgstr "" + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:3 +#, php-format +msgid "Update your account." +msgstr "更新你的账户" + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:4 +#, php-format +msgid "See your public profile." +msgstr "查看你的公开资料" + +#: IDF/gettexttemplates/idf/user/dashboard.html.php:5 +#, php-format +msgid "See your forge issue watch list." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:6 +msgid "Key Management" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:7 +msgid "Secondary Emails" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:8 +msgid "Extra password" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:9 +msgid "" +"This password is used to access some of the external systems managed by our " +"infrastructure. It will be regenerated if you change your password." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:10 +msgid "API key" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:11 +msgid "" +"Your API key will be regenerated automatically if you change your password." +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:12 +msgid "Update Your Account" +msgstr "更新" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:14 +msgid "Your Current Public Keys" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:15 +msgid "Delete this key" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:16 +msgid "Your additional email addresses" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:17 +msgid "Delete this address" +msgstr "" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:18 +msgid "" +"If possible, use your real name. By using your real name, people will have " +"more trust in your comments and remarks." +msgstr "如果可以,请使用你的真名。" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:19 +msgid "" +"The extra password is used to access some of the external systems and the " +"API key is used to interact with this website using a program." +msgstr "扩展密码用于访问外部系统(如svn)和系统API" + +#: IDF/gettexttemplates/idf/user/myaccount.html.php:20 +msgid "Show API key and extra password" +msgstr "显示API key和扩展密码" + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:3 +msgid "" +"Oops, please check the provided login or email address to recover your " +"password." +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:4 +msgid "Recover My Password" +msgstr "恢复密码" + +#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:6 +msgid "" +"Provide either your login or email address, if a corresponding user is found " +"in the database, we will send you an email with the details on how to reset " +"your password." +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-email.txt.php:3 +#, php-format +msgid "" +"Hello %%user%%,\n" +"\n" +"You lost your password and wanted to recover it.\n" +"To provide a new password for your account, you\n" +"just have to follow the provided link. You will\n" +"get a simple form to provide a new password.\n" +"\n" +"%%url%%\n" +"\n" +"Alternatively, go to this page:\n" +"\n" +"%%urlik%%\n" +"\n" +"and provide the following verification key:\n" +"\n" +"%%key%%\n" +"\n" +"If you are not the one who requested to reset\n" +"your password, simply ignore this email, your\n" +"password will not be changed.\n" +"\n" +"Yours faithfully,\n" +"The development team.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:4 +msgid "Recover Your Password" +msgstr "找回密码" + +#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:8 +msgid "" +"Just after providing the confirmation key, you will be able to reset your " +"password and use this website fully." +msgstr "" + +#: IDF/gettexttemplates/idf/user/passrecovery.html.php:6 +msgid "Reset Your Password" +msgstr "重置密码" + +#: IDF/gettexttemplates/idf/user/public.html.php:3 +#, php-format +msgid "You are looking at the public profile of %%member%%." +msgstr "你正在查看 %%member%% 的公开资料" + +#: IDF/gettexttemplates/idf/user/public.html.php:5 +msgid "Twitter:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:6 +msgid "Public Email:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:7 +msgid "Website:" +msgstr "" + +#: IDF/gettexttemplates/idf/user/public.html.php:8 +msgid "Last time seen:" +msgstr "最近登录" + +#: IDF/gettexttemplates/idf/user/public.html.php:9 +msgid "Member since:" +msgstr "注册时间" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:3 +msgid "List Pages" +msgstr "页面列表" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:4 +#, fuzzy +msgid "List Resources" +msgstr "%s 源代码配置" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:5 +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:4 +#: IDF/gettexttemplates/idf/wiki/search.html.php:3 IDF/Views/Wiki.php:211 +msgid "New Page" +msgstr "新页面" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:6 +#: IDF/gettexttemplates/idf/wiki/listResources.html.php:3 +#: IDF/Views/Wiki.php:256 +#, fuzzy +msgid "New Resource" +msgstr "新问题" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:7 +msgid "Update This Page" +msgstr "更新此页面" + +#: IDF/gettexttemplates/idf/wiki/base.html.php:8 +#, fuzzy +msgid "Update This Resource" +msgstr "更新此页面" + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:3 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:3 +msgid "Preview of the Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:7 +msgid "The form contains some errors. Please correct them to create the page." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createPage.html.php:6 +msgid "Create Page" +msgstr "创建页面" + +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:3 +msgid "" +"\n" +"Wiki resources are later addressed in wiki pages by their title, so ensure " +"that you\n" +"give your resource a unique and an easy to remember name.\n" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/createResource.html.php:8 +#, fuzzy +msgid "Create Resource" +msgstr "添加用户" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:3 +msgid "" +"If you delete this documentation page, it will be removed from the database " +"with all the associated revisions and you will not be able to " +"recover it." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:6 +msgid "Delete Page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePage.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:14 +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:15 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:15 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:17 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:18 +msgid "Old Revisions" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:3 +#, php-format +msgid "" +"You are looking at an old revision (%%oldrev.summary%%) of the " +"page \n" +"%%page.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:6 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:5 +msgid "" +"If you delete this old revision, it will be removed from the database and " +"you will not be able to recover it." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deletePageRev.html.php:9 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:8 +msgid "Delete Revision" +msgstr "删除版本" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:3 +msgid "" +"If you delete this documentation resource, it will be removed from the " +"database with all the associated revisions \n" +"and you will not be able to recover it. Any documentation " +"pages that reference this resource,\n" +"will no longer be able to render it, but won't be deleted." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:8 +#, fuzzy +msgid "Delete Resource" +msgstr "删除版本" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:10 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:10 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:8 +#, fuzzy +msgid "File size" +msgstr "文件大小" + +#: IDF/gettexttemplates/idf/wiki/deleteResource.html.php:11 +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:9 +#: IDF/Views/Wiki.php:101 +#, fuzzy +msgid "MIME type" +msgstr "类型" + +#: IDF/gettexttemplates/idf/wiki/deleteResourceRev.html.php:3 +#, php-format +msgid "" +"You are looking at an old revision (%%oldrev.summary%%) of the " +"resource \n" +"%%resource.title%%. This revision was created by " +"%%submitter%%." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/edit-info.html.php:3 +#, php-format +msgid "" +"\n" +"

Instructions:

\n" +"

The content of the page can use the Markdown syntax with the Extra extension.

\n" +"

Website addresses are automatically linked and you can link to another " +"page in the documentation using double square brackets like that " +"[[AnotherPage]].

\n" +"

If you want to embed uploaded resources, use the [[!ResourceName]] syntax for that. This is described more in detail in the FAQ.

\n" +"

To directly include a file content from the repository, embrace its path " +"with triple square brackets: [[[my/file.txt]]].

\n" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/feedfragment-resource.xml.php:4 +msgid "Initial creation" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:3 +#, php-format +msgid "See the deprecated pages." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/listPages.html.php:5 +msgid "Number of pages:" +msgstr "文档数目:" + +#: IDF/gettexttemplates/idf/wiki/listResources.html.php:4 +#, fuzzy +msgid "Number of resources:" +msgstr "用户数量:" + +#: IDF/gettexttemplates/idf/wiki/search.html.php:4 +msgid "Pages found:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:4 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:3 +msgid "The form contains some errors. Please correct them to update the page." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:6 +msgid "Update Page" +msgstr "更新页面" + +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:8 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:10 +#: IDF/gettexttemplates/idf/wiki/updatePage.html.php:11 +msgid "Delete this page" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:4 +#, fuzzy +msgid "Update Resource" +msgstr "更新用户" + +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:6 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:8 +#: IDF/gettexttemplates/idf/wiki/updateResource.html.php:9 +#, fuzzy +msgid "Delete this resource" +msgstr "删除此项目" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:3 +msgid "" +"Attention! This page is marked as deprecated, \n" +"use it as reference only if you are sure you need these specific information." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:5 +#, php-format +msgid "" +"You are looking at an old revision of the page \n" +"%%page.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:10 +msgid "Table of Content" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewPage.html.php:13 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:11 +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:13 +msgid "Delete this revision" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:3 +#, php-format +msgid "" +"You are looking at an old revision of the resource \n" +"%%resource.title%%. This revision was created\n" +"by %%submitter%%." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:14 +#, fuzzy +msgid "Page Usage" +msgstr "页面名称" + +#: IDF/gettexttemplates/idf/wiki/viewResource.html.php:15 +msgid "This resource is not used on any pages yet." +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:3 +msgid "A new documentation page has been created:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-created-email.txt.php:9 +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:14 +msgid "Documentation page:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:3 +msgid "The following documentation page has been updated:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:7 +msgid "Updated by:" +msgstr "" + +#: IDF/gettexttemplates/idf/wiki/wiki-updated-email.txt.php:13 +msgid "New content:" +msgstr "" + +#: IDF/Issue.php:76 +msgid "owner" +msgstr "所有者" + +#: IDF/Issue.php:84 IDF/Wiki/Page.php:86 +msgid "interested users" +msgstr "" + +#: IDF/Issue.php:85 +msgid "" +"Interested users will get an email notification when the issue is changed." +msgstr "" + +#: IDF/Issue.php:92 IDF/Project.php:94 IDF/Review.php:95 IDF/Upload.php:99 +#: IDF/Wiki/Page.php:94 +msgid "labels" +msgstr "标签" + +#: IDF/Issue.php:111 IDF/IssueFile.php:102 IDF/Review.php:114 +#: IDF/Upload.php:118 IDF/Wiki/Page.php:106 IDF/Wiki/Resource.php:101 +msgid "modification date" +msgstr "修改日期" + +#: IDF/Issue.php:212 IDF/IssueComment.php:143 +#, php-format +msgid "" +"Issue %3$d, %4$s" +msgstr "问题 %3$d, %4$s" + +#: IDF/Issue.php:214 +#, fuzzy, php-format +msgid "Creation of issue %3$d, by %4$s" +msgstr "评论 issue %d, 由 %s" + +#: IDF/Issue.php:224 +#, fuzzy, php-format +msgid "%1$s: Issue %2$d created - %3$s" +msgstr "%s: Issue %d created - %s" + +#: IDF/Issue.php:307 +#, php-format +msgid "Issue %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Issue.php:311 +#, php-format +msgid "Updated Issue %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/IssueComment.php:51 IDF/IssueRelation.php:47 +msgid "issue" +msgstr "问题" + +#: IDF/IssueComment.php:58 IDF/IssueFile.php:49 IDF/Review/Comment.php:62 +#: IDF/Review/FileComment.php:49 IDF/Review/FileComment.php:69 +msgid "comment" +msgstr "评论" + +#: IDF/IssueComment.php:72 IDF/Review/Comment.php:75 IDF/Upload.php:63 +#: IDF/Wiki/PageRevision.php:85 +msgid "changes" +msgstr "修改" + +#: IDF/IssueComment.php:73 +msgid "Serialized array of the changes in the issue." +msgstr "" + +#: IDF/IssueComment.php:180 +#, fuzzy, php-format +msgid "Comment on issue %3$d, by %4$s" +msgstr "评论 issue %d, 由 %s" + +#: IDF/IssueComment.php:191 +#, php-format +msgid "%1$s: Comment on issue %2$d - %3$s" +msgstr "" + +#: IDF/IssueFile.php:64 +msgid "file name" +msgstr "文件名" + +#: IDF/IssueFile.php:70 +msgid "the file" +msgstr "文件" + +#: IDF/IssueFile.php:76 +msgid "file size" +msgstr "文件大小" + +#: IDF/IssueFile.php:84 +msgid "type" +msgstr "类型" + +#: IDF/IssueFile.php:86 +msgid "Image" +msgstr "图片" + +#: IDF/IssueFile.php:87 +msgid "Other" +msgstr "其它" + +#: IDF/IssueRelation.php:54 +msgid "verb" +msgstr "" + +#: IDF/IssueRelation.php:61 +msgid "other issue" +msgstr "" + +#: IDF/Key.php:55 +msgid "public key" +msgstr "" + +#: IDF/Key.php:90 +msgid "Invalid or unknown key data detected." +msgstr "" + +#: IDF/Plugin/SyncMercurial.php:78 IDF/Plugin/SyncSvn.php:81 +#, php-format +msgid "The repository %s already exists." +msgstr "" + +#: IDF/Plugin/SyncMercurial.php:142 +#, php-format +msgid "%s does not exist or is not writable." +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:107 IDF/Plugin/SyncMonotone.php:492 +msgid "\"mtn_repositories\" must be defined in your configuration file" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:114 IDF/Plugin/SyncMonotone.php:482 +msgid "\"mtn_usher_conf\" does not exist or is not writable" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:121 +#, php-format +msgid "Could not find mtn-post-push script \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:155 +#, php-format +msgid "The configuration file \"%s\" is missing" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:164 +#, php-format +msgid "The project path \"%s\" already exists" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:170 +#, php-format +msgid "The project path \"%s\" could not be created" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:208 +#, php-format +msgid "The key directory \"%s\" could not be created" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:227 +#, php-format +msgid "Could not parse key information: %s" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:265 +#, php-format +msgid "Could not create configuration directory \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:275 +#, php-format +msgid "Could not create symlink for configuration file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:293 +#, php-format +msgid "Could not write configuration file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:309 IDF/Plugin/SyncMonotone.php:525 +#, php-format +msgid "Could not parse usher configuration in \"%1$s\": %2$s" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:320 +#, php-format +msgid "usher configuration already contains a server entry named \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:345 IDF/Plugin/SyncMonotone.php:546 +#, php-format +msgid "Could not write usher configuration file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:395 +#, php-format +msgid "Could not write write-permissions file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:420 +#, php-format +msgid "Could not write read-permissions file \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:438 +#, php-format +msgid "Could not remove symlink \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:446 +#, php-format +msgid "Could not create symlink \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:500 +#, php-format +msgid "One or more paths underneath %s could not be deleted" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:512 +#, php-format +msgid "Could not delete client private key \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:599 IDF/Plugin/SyncMonotone.php:718 +#, php-format +msgid "Could not parse read-permissions for project \"%1$s\": %2$s" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:643 IDF/Plugin/SyncMonotone.php:741 +#, php-format +msgid "Could not write read-permissions for project \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:657 IDF/Plugin/SyncMonotone.php:760 +#, php-format +msgid "Could not write write-permissions file for project \"%s\"" +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:813 +msgid "\"mtn_repositories\" must be defined in your configuration file." +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:820 +#, php-format +msgid "The project path %s does not exists." +msgstr "" + +#: IDF/Plugin/SyncMonotone.php:838 +#, php-format +msgid "The command \"%s\" could not be executed." +msgstr "" + +#: IDF/Project.php:62 IDF/Tag.php:66 +msgid "name" +msgstr "名称" + +#: IDF/Project.php:69 +msgid "short name" +msgstr "短名称" + +#: IDF/Project.php:70 +msgid "" +"Used in the URL to access the project, must be short with only letters and " +"numbers." +msgstr "" + +#: IDF/Project.php:78 +msgid "short description" +msgstr "简要说明" + +#: IDF/Project.php:86 IDF/Review/Patch.php:74 +msgid "description" +msgstr "说明" + +#: IDF/Project.php:87 +msgid "The description can be extended using the Markdown syntax." +msgstr "" + +#: IDF/Project.php:100 +msgid "private" +msgstr "私有" + +#: IDF/Project.php:108 +msgid "current project activity" +msgstr "" + +#: IDF/Project.php:159 +#, php-format +msgid "Project \"%s\" not found." +msgstr "" + +#: IDF/ProjectActivity.php:56 +#, fuzzy +msgid "date" +msgstr "更新:" + +#: IDF/Review/Comment.php:55 IDF/Review/Patch.php:80 +msgid "patch" +msgstr "补丁" + +#: IDF/Review/Comment.php:83 +msgid "vote" +msgstr "" + +#: IDF/Review/Comment.php:139 IDF/Review/Patch.php:151 +#, php-format +msgid "" +"Review %3$d, %4$s" +msgstr "" + +#: IDF/Review/Comment.php:141 +#, fuzzy, php-format +msgid "Update of review %3$d, by %4$s" +msgstr "问题 %3$d, %4$s" + +#: IDF/Review/Comment.php:151 +#, php-format +msgid "%1$s: Updated review %2$d - %3$s" +msgstr "" + +#: IDF/Review/Comment.php:222 +#, php-format +msgid "Updated Code Review %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Review/Patch.php:52 +msgid "review" +msgstr "" + +#: IDF/Review/Patch.php:67 +msgid "commit" +msgstr "" + +#: IDF/Review/Patch.php:153 +#, fuzzy, php-format +msgid "Creation of review %3$d, by %4$s" +msgstr "评论 issue %d, 由 %s" + +#: IDF/Review/Patch.php:163 +#, php-format +msgid "%1$s: Creation of Review %2$d - %3$s" +msgstr "" + +#: IDF/Review/Patch.php:208 +#, php-format +msgid "New Code Review %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Scm/Git.php:309 IDF/Scm/Mercurial.php:199 +#, php-format +msgid "Folder %1$s not found in commit %2$s." +msgstr "" + +#: IDF/Scm/Git.php:433 IDF/Scm/Mercurial.php:216 +#, php-format +msgid "Not a valid tree: %s." +msgstr "" + +#: IDF/Scm/Monotone/Stdio.php:81 +msgid "Monotone client key name or hash not in project conf." +msgstr "" + +#: IDF/Scm/Monotone/Stdio.php:89 +#, php-format +msgid "The key directory %s could not be created." +msgstr "" + +#: IDF/Scm/Monotone/Stdio.php:100 +#, php-format +msgid "Could not write client key \"%s\"" +msgstr "" + +#: IDF/Search/Occ.php:33 +msgid "occurrence" +msgstr "" + +#: IDF/Search/Occ.php:49 +msgid "word" +msgstr "" + +#: IDF/Search/Occ.php:75 +msgid "occurrences" +msgstr "" + +#: IDF/Search/Occ.php:81 +msgid "ponderated occurrence" +msgstr "" + +#: IDF/Tag.php:59 +msgid "tag class" +msgstr "" + +#: IDF/Tag.php:60 +msgid "The class of the tag." +msgstr "" + +#: IDF/Tag.php:73 +msgid "lcname" +msgstr "" + +#: IDF/Tag.php:74 +msgid "Lower case version of the name for fast searching." +msgstr "" + +#: IDF/Template/Markdown.php:84 +msgid "Create this documentation page" +msgstr "" + +#: IDF/Template/Markdown.php:97 +msgid "You are not allowed to access the wiki." +msgstr "" + +#: IDF/Template/Markdown.php:106 +#, fuzzy +msgid "The wiki resource has not been found." +msgstr "项目更新成功" + +#: IDF/Template/Markdown.php:113 +msgid "The wiki resource has not been found. Create it!" +msgstr "" + +#: IDF/Template/Markdown.php:146 +msgid "This revision of the resource is no longer available." +msgstr "" + +#: IDF/Template/ShowUser.php:51 +msgid "Anonymous" +msgstr "匿名" + +#: IDF/Template/ShowUser.php:54 +msgid "Me" +msgstr "" + +#: IDF/Timeline/Paginator.php:49 +msgid "Today" +msgstr "今天" + +#: IDF/Upload.php:70 +msgid "file" +msgstr "文件" + +#: IDF/Upload.php:71 +msgid "The path is relative to the upload path." +msgstr "" + +#: IDF/Upload.php:78 IDF/Wiki/ResourceRevision.php:71 +msgid "file size in bytes" +msgstr "" + +#: IDF/Upload.php:84 +msgid "MD5" +msgstr "" + +#: IDF/Upload.php:106 +msgid "number of downloads" +msgstr "下载数量" + +#: IDF/Upload.php:201 +#, php-format +msgid "Download %2$d, %3$s" +msgstr "" + +#: IDF/Upload.php:204 +#, php-format +msgid "Addition of download %2$d, by %3$s" +msgstr "" + +#: IDF/Upload.php:214 +#, php-format +msgid "%1$s: Download %2$d added - %3$s" +msgstr "" + +#: IDF/Upload.php:301 +#, fuzzy, php-format +msgid "New download - %1$s (%2$s)" +msgstr "上传 - %s (%s)" + +#: IDF/Upload.php:305 +#, fuzzy, php-format +msgid "Updated download - %1$s (%2$s)" +msgstr "上传 - %s (%s)" + +#: IDF/Views/Admin.php:47 +#, fuzzy +msgid "The forge configuration has been saved." +msgstr "下载配置保存成功" + +#: IDF/Views/Admin.php:80 +msgid "This table shows the projects in the forge." +msgstr "" + +#: IDF/Views/Admin.php:85 +msgid "Short Name" +msgstr "短名称" + +#: IDF/Views/Admin.php:87 +msgid "Repository Size" +msgstr "仓库大小" + +#: IDF/Views/Admin.php:93 +msgid "No projects were found." +msgstr "没有项目" + +#: IDF/Views/Admin.php:116 +#, fuzzy +msgid "The label configuration has been saved." +msgstr "下载配置保存成功" + +#: IDF/Views/Admin.php:147 IDF/Views/Admin.php:314 IDF/Views/Wiki.php:484 +#: IDF/Views/Wiki.php:536 +#, php-format +msgid "Update %s" +msgstr "更新 %s" + +#: IDF/Views/Admin.php:155 IDF/Views/Project.php:304 +msgid "The project has been updated." +msgstr "项目更新成功" + +#: IDF/Views/Admin.php:192 +msgid "The project has been created." +msgstr "项目创建成功" + +#: IDF/Views/Admin.php:223 +#, php-format +msgid "Delete %s Project" +msgstr "删除 %s 项目" + +#: IDF/Views/Admin.php:230 +msgid "The project has been deleted." +msgstr "项目删除成功" + +#: IDF/Views/Admin.php:260 +msgid "Not Validated User List" +msgstr "未验证的用户" + +#: IDF/Views/Admin.php:268 +msgid "This table shows the users in the forge." +msgstr "" + +#: IDF/Views/Admin.php:272 +msgid "login" +msgstr "登录" + +#: IDF/Views/Admin.php:275 +msgid "Admin" +msgstr "管理员" + +#: IDF/Views/Admin.php:277 +msgid "Last Login" +msgstr "最后登录" + +#: IDF/Views/Admin.php:284 +msgid "No users were found." +msgstr "没有合适用户" + +#: IDF/Views/Admin.php:321 +msgid "You do not have the rights to update this user." +msgstr "" + +#: IDF/Views/Admin.php:339 +msgid "The user has been updated." +msgstr "" + +#: IDF/Views/Admin.php:372 +#, php-format +msgid "The user %s has been created." +msgstr "" + +#: IDF/Views/Admin.php:379 +msgid "Add User" +msgstr "添加用户" + +#: IDF/Views/Admin.php:395 +msgid "Usher management" +msgstr "" + +#: IDF/Views/Admin.php:432 +msgid "Usher configuration has been reloaded" +msgstr "" + +#: IDF/Views/Admin.php:436 +msgid "Usher has been shut down" +msgstr "" + +#: IDF/Views/Admin.php:441 +msgid "Usher has been started up" +msgstr "" + +#: IDF/Views/Admin.php:479 +#, php-format +msgid "The server \"%s\" has been started" +msgstr "" + +#: IDF/Views/Admin.php:483 +#, php-format +msgid "The server \"%s\" has been stopped" +msgstr "" + +#: IDF/Views/Admin.php:488 +#, php-format +msgid "The server \"%s\" has been killed" +msgstr "" + +#: IDF/Views/Admin.php:508 +#, php-format +msgid "Open connections for \"%s\"" +msgstr "" + +#: IDF/Views/Admin.php:513 +#, php-format +msgid "no connections for server \"%s\"" +msgstr "" + +#: IDF/Views/Admin.php:534 +msgid "Yes" +msgstr "是" + +#: IDF/Views/Admin.php:534 +msgid "No" +msgstr "不" + +#: IDF/Views/Download.php:45 +#, php-format +msgid "%s Downloads" +msgstr "%s 下载" + +#: IDF/Views/Download.php:51 +msgid "This table shows the files to download." +msgstr "" + +#: IDF/Views/Download.php:67 IDF/Views/Download.php:349 +msgid "Uploaded" +msgstr "上传时间" + +#: IDF/Views/Download.php:71 IDF/Views/Download.php:353 +msgid "No downloads were found." +msgstr "没有下载" + +#: IDF/Views/Download.php:94 +#, php-format +msgid "Download %s" +msgstr "下载 %s" + +#: IDF/Views/Download.php:111 +#, php-format +msgid "The file %2$s has been updated." +msgstr "" + +#: IDF/Views/Download.php:144 +#, php-format +msgid "Delete Download %s" +msgstr "删除下载 %s" + +#: IDF/Views/Download.php:177 +msgid "The file has been deleted." +msgstr "" + +#: IDF/Views/Download.php:244 +#, php-format +msgid "The file has been uploaded." +msgstr "" + +#: IDF/Views/Download.php:271 +#, fuzzy +msgid "New Downloads from Archive" +msgstr "上传" + +#: IDF/Views/Download.php:278 +#, fuzzy +msgid "The archive has been uploaded and processed." +msgstr "项目更新成功" + +#: IDF/Views/Download.php:331 +#, php-format +msgid "%1$s Downloads with Label %2$s" +msgstr "" + +#: IDF/Views/Download.php:341 +#, php-format +msgid "This table shows the downloads with label %s." +msgstr "" + +#: IDF/Views/Issue.php:41 +#, php-format +msgid "%s Open Issues" +msgstr "%s 开放的问题" + +#: IDF/Views/Issue.php:51 IDF/Views/Issue.php:382 IDF/Views/User.php:75 +msgid "This table shows the open issues." +msgstr "" + +#: IDF/Views/Issue.php:61 IDF/Views/Issue.php:220 IDF/Views/Issue.php:301 +#: IDF/Views/Issue.php:390 IDF/Views/Issue.php:542 IDF/Views/Issue.php:765 +#: IDF/Views/Issue.php:824 IDF/Views/Review.php:57 IDF/Views/User.php:81 +msgid "Id" +msgstr "编号" + +#: IDF/Views/Issue.php:64 IDF/Views/Issue.php:223 IDF/Views/Issue.php:305 +#: IDF/Views/Issue.php:393 IDF/Views/Issue.php:545 IDF/Views/Issue.php:768 +#: IDF/Views/Issue.php:827 IDF/Views/Review.php:60 IDF/Views/User.php:85 +msgid "Last Updated" +msgstr "最后更新" + +#: IDF/Views/Issue.php:68 IDF/Views/Issue.php:227 IDF/Views/Issue.php:309 +#: IDF/Views/Issue.php:397 IDF/Views/Issue.php:549 IDF/Views/Issue.php:772 +#: IDF/Views/Issue.php:831 +msgid "No issues were found." +msgstr "没有问题" + +#: IDF/Views/Issue.php:113 +msgid "Not assigned" +msgstr "" + +#: IDF/Views/Issue.php:149 +#, php-format +msgid "Summary of tracked issues in %s." +msgstr "" + +#: IDF/Views/Issue.php:194 +#, php-format +msgid "Watch List: Closed Issues for %s" +msgstr "" + +#: IDF/Views/Issue.php:195 +#, php-format +msgid "This table shows the closed issues in your watch list for %s project." +msgstr "" + +#: IDF/Views/Issue.php:200 +#, php-format +msgid "Watch List: Open Issues for %s" +msgstr "" + +#: IDF/Views/Issue.php:201 +#, php-format +msgid "This table shows the open issues in your watch list for %s project." +msgstr "" + +#: IDF/Views/Issue.php:277 +msgid "Watch List: Closed Issues" +msgstr "" + +#: IDF/Views/Issue.php:278 +msgid "This table shows the closed issues in your watch list." +msgstr "" + +#: IDF/Views/Issue.php:283 +msgid "Watch List: Open Issues" +msgstr "" + +#: IDF/Views/Issue.php:284 +msgid "This table shows the open issues in your watch list." +msgstr "" + +#: IDF/Views/Issue.php:303 IDF/Views/User.php:82 +msgid "Project" +msgstr "项目" + +#: IDF/Views/Issue.php:344 +#, fuzzy, php-format +msgid "%1$s %2$s Submitted %3$s Issues" +msgstr "发布的问题:" + +#: IDF/Views/Issue.php:348 +#, php-format +msgid "%1$s %2$s Closed Submitted %3$s Issues" +msgstr "" + +#: IDF/Views/Issue.php:352 +#, php-format +msgid "%1$s %2$s Closed Working %3$s Issues" +msgstr "" + +#: IDF/Views/Issue.php:356 +#, php-format +msgid "%1$s %2$s Working %3$s Issues" +msgstr "" + +#: IDF/Views/Issue.php:417 +msgid "Submit a new issue" +msgstr "提交新问题" + +#: IDF/Views/Issue.php:433 +#, php-format +msgid "Issue %2$d has been created." +msgstr "" + +#: IDF/Views/Issue.php:490 +#, php-format +msgid "Search issues - %s" +msgstr "" + +#: IDF/Views/Issue.php:492 +#, php-format +msgid "Search closed issues - %s" +msgstr "" + +#: IDF/Views/Issue.php:539 +msgid "This table shows the found issues." +msgstr "" + +#: IDF/Views/Issue.php:604 +#, fuzzy, php-format +msgid "Issue %2$d: %3$s" +msgstr "问题 %d: %s" + +#: IDF/Views/Issue.php:628 +#, php-format +msgid "Issue %2$d has been updated." +msgstr "" + +#: IDF/Views/Issue.php:718 +#, php-format +msgid "View %s" +msgstr "查看 %s" + +#: IDF/Views/Issue.php:745 +#, php-format +msgid "%s Closed Issues" +msgstr "" + +#: IDF/Views/Issue.php:755 +msgid "This table shows the closed issues." +msgstr "" + +#: IDF/Views/Issue.php:798 +#, php-format +msgid "%1$s Issues with Label %2$s" +msgstr "" + +#: IDF/Views/Issue.php:801 +#, php-format +msgid "%1$s Closed Issues with Label %2$s" +msgstr "" + +#: IDF/Views/Issue.php:814 +#, php-format +msgid "This table shows the issues with label %s." +msgstr "" + +#: IDF/Views/Issue.php:937 +msgid "The issue has been removed from your watch list." +msgstr "" + +#: IDF/Views/Issue.php:940 +msgid "The issue has been added to your watch list." +msgstr "" + +#: IDF/Views/Issue.php:1037 +msgid "On your watch list." +msgstr "" + +#: IDF/Views/Project.php:95 +msgid "Issues and Comments" +msgstr "" + +#: IDF/Views/Project.php:99 +msgid "Documents" +msgstr "" + +#: IDF/Views/Project.php:101 +msgid "Reviews and Patches" +msgstr "" + +#: IDF/Views/Project.php:180 +msgid "This table shows the project updates." +msgstr "" + +#: IDF/Views/Project.php:191 +msgid "Change" +msgstr "更改" + +#: IDF/Views/Project.php:195 +msgid "No changes were found." +msgstr "没有修改信息" + +#: IDF/Views/Project.php:296 +#, php-format +msgid "%s Project Summary" +msgstr "%s 项目摘要" + +#: IDF/Views/Project.php:335 +#, php-format +msgid "%s Issue Tracking Configuration" +msgstr "%s 问题跟踪配置" + +#: IDF/Views/Project.php:344 +msgid "The issue tracking configuration has been saved." +msgstr "问题跟踪配置保存成功" + +#: IDF/Views/Project.php:381 +#, php-format +msgid "%s Downloads Configuration" +msgstr "%s 下载配置" + +#: IDF/Views/Project.php:393 +msgid "The downloads configuration has been saved." +msgstr "下载配置保存成功" + +#: IDF/Views/Project.php:428 +#, php-format +msgid "%s Documentation Configuration" +msgstr "%s 文档配置" + +#: IDF/Views/Project.php:437 +msgid "The documentation configuration has been saved." +msgstr "文档配置保存成功" + +#: IDF/Views/Project.php:471 +#, php-format +msgid "%s Project Members" +msgstr "%s 项目成员" + +#: IDF/Views/Project.php:480 +msgid "The project membership has been saved." +msgstr "项目成员保存成功" + +#: IDF/Views/Project.php:503 +#, php-format +msgid "%s Tabs Access Rights" +msgstr "%s 访问权限" + +#: IDF/Views/Project.php:517 +#, fuzzy +msgid "" +"The project tabs access rights and notification settings have been saved." +msgstr "项目访问权限保存成功" + +#: IDF/Views/Project.php:566 +#, php-format +msgid "%s Source" +msgstr "%s 源代码配置" + +#: IDF/Views/Project.php:580 +msgid "The project source configuration has been saved." +msgstr "" + +#: IDF/Views/Review.php:41 +#, php-format +msgid "%s Code Reviews" +msgstr "%s 代码审核" + +#: IDF/Views/Review.php:48 +msgid "This table shows the latest reviews." +msgstr "" + +#: IDF/Views/Review.php:64 +msgid "No reviews were found." +msgstr "没有审核" + +#: IDF/Views/Review.php:94 +#, php-format +msgid "The code review %2$d has been created." +msgstr "" + +#: IDF/Views/Review.php:140 +#, fuzzy, php-format +msgid "Review %2$d: %3$s" +msgstr "问题 %d: %s" + +#: IDF/Views/Review.php:160 +#, php-format +msgid "Your code review %2$d has been published." +msgstr "" + +#: IDF/Views/Source.php:40 +#, php-format +msgid "%s Source Help" +msgstr "%s 源代码帮助" + +#: IDF/Views/Source.php:58 +#, php-format +msgid "%s Invalid Revision" +msgstr "" + +#: IDF/Views/Source.php:82 +#, php-format +msgid "%s Ambiguous Revision" +msgstr "" + +#: IDF/Views/Source.php:107 +#, php-format +msgid "%1$s %2$s Change Log" +msgstr "%1$s %2$s 修改日志" + +#: IDF/Views/Source.php:153 IDF/Views/Source.php:234 IDF/Views/Source.php:362 +#, php-format +msgid "%1$s %2$s Source Tree" +msgstr "%1$s %2$s 源码树" + +#: IDF/Views/Source.php:310 +#, php-format +msgid "%s Commit Details" +msgstr "" + +#: IDF/Views/Source.php:311 +#, php-format +msgid "%1$s Commit Details - %2$s" +msgstr "" + +#: IDF/Views/User.php:59 +msgid "Your Dashboard - Working Issues" +msgstr "你的任务" + +#: IDF/Views/User.php:62 +msgid "Your Dashboard - Submitted Issues" +msgstr "" + +#: IDF/Views/User.php:89 +msgid "No issues are assigned to you, yeah!" +msgstr "太棒了,没有签给你的问题!" + +#: IDF/Views/User.php:89 +msgid "All the issues you submitted are fixed, yeah!" +msgstr "" + +#: IDF/Views/User.php:121 +msgid "Your personal information has been updated." +msgstr "你的个人资料更新成功" + +#: IDF/Views/User.php:133 +msgid "Your Account" +msgstr "账户" + +#: IDF/Views/User.php:157 +msgid "The public key has been deleted." +msgstr "" + +#: IDF/Views/User.php:177 +msgid "The address has been deleted." +msgstr "" + +#: IDF/Views/User.php:200 +msgid "Confirm The Email Change" +msgstr "" + +#: IDF/Views/User.php:232 +#, php-format +msgid "Your new email address \"%s\" has been validated. Thank you!" +msgstr "" + +#: IDF/Views/Wiki.php:41 +#, php-format +msgid "%s Documentation" +msgstr "%s 文档" + +#: IDF/Views/Wiki.php:48 +msgid "This table shows the documentation pages." +msgstr "" + +#: IDF/Views/Wiki.php:61 IDF/Views/Wiki.php:144 IDF/Views/Wiki.php:185 +msgid "Page Title" +msgstr "标题" + +#: IDF/Views/Wiki.php:63 IDF/Views/Wiki.php:103 IDF/Views/Wiki.php:146 +#: IDF/Views/Wiki.php:187 +msgid "Updated" +msgstr "" + +#: IDF/Views/Wiki.php:67 IDF/Views/Wiki.php:191 +msgid "No documentation pages were found." +msgstr "没有文档" + +#: IDF/Views/Wiki.php:88 +#, fuzzy, php-format +msgid "%s Documentation Resources" +msgstr "%s 文档" + +#: IDF/Views/Wiki.php:94 +msgid "This table shows the resources that can be used on documentation pages." +msgstr "" + +#: IDF/Views/Wiki.php:100 +#, fuzzy +msgid "Resource Title" +msgstr "源码" + +#: IDF/Views/Wiki.php:107 +#, fuzzy +msgid "No resources were found." +msgstr "没有问题" + +#: IDF/Views/Wiki.php:128 +#, php-format +msgid "Documentation Search - %s" +msgstr "" + +#: IDF/Views/Wiki.php:139 +msgid "This table shows the pages found." +msgstr "" + +#: IDF/Views/Wiki.php:150 +msgid "No pages were found." +msgstr "" + +#: IDF/Views/Wiki.php:169 +#, php-format +msgid "%1$s Documentation Pages with Label %2$s" +msgstr "" + +#: IDF/Views/Wiki.php:179 +#, php-format +msgid "This table shows the documentation pages with label %s." +msgstr "" + +#: IDF/Views/Wiki.php:222 +#, fuzzy, php-format +msgid "The page %2$s has been created." +msgstr "项目创建成功" + +#: IDF/Views/Wiki.php:265 +#, fuzzy, php-format +msgid "The resource %2$s has been created." +msgstr "项目创建成功" + +#: IDF/Views/Wiki.php:409 IDF/Views/Wiki.php:448 +msgid "The old revision has been deleted." +msgstr "" + +#: IDF/Views/Wiki.php:415 IDF/Views/Wiki.php:454 +#, php-format +msgid "Delete Old Revision of %s" +msgstr "" + +#: IDF/Views/Wiki.php:496 +#, fuzzy, php-format +msgid "The page %2$s has been updated." +msgstr "项目更新成功" + +#: IDF/Views/Wiki.php:548 +#, fuzzy, php-format +msgid "The resource %2$s has been updated." +msgstr "项目更新成功" + +#: IDF/Views/Wiki.php:583 +msgid "The documentation page has been deleted." +msgstr "" + +#: IDF/Views/Wiki.php:591 +#, php-format +msgid "Delete Page %s" +msgstr "" + +#: IDF/Views/Wiki.php:623 +#, fuzzy +msgid "The documentation resource has been deleted." +msgstr "文档配置保存成功" + +#: IDF/Views/Wiki.php:631 +#, fuzzy, php-format +msgid "Delete Resource %s" +msgstr "删除版本" + +#: IDF/Views.php:173 IDF/Views.php:199 +msgid "Confirm Your Account Creation" +msgstr "" + +#: IDF/Views.php:219 +msgid "Welcome! You can now participate in the life of your project of choice." +msgstr "" + +#: IDF/Views.php:245 IDF/Views.php:269 IDF/Views.php:310 +msgid "Password Recovery" +msgstr "找回密码" + +#: IDF/Views.php:289 +msgid "" +"Welcome back! Next time, you can use your broswer options to remember the " +"password." +msgstr "欢迎回来!接下来,你可以使用浏览器记住你的密码" + +#: IDF/Views.php:331 +msgid "Here to Help You!" +msgstr "希望这些能帮到你" + +#: IDF/Views.php:347 +msgid "InDefero Upload Archive Format" +msgstr "" + +#: IDF/Views.php:363 +msgid "InDefero API (Application Programming Interface)" +msgstr "" + +#: IDF/Wiki/Page.php:62 IDF/Wiki/Resource.php:64 +msgid "title" +msgstr "标题" + +#: IDF/Wiki/Page.php:63 +msgid "" +"The title of the page must only contain letters, digits or the dash " +"character. For example: My-new-Wiki-Page." +msgstr "" + +#: IDF/Wiki/Page.php:71 +msgid "A one line description of the page content." +msgstr "" + +#: IDF/Wiki/Page.php:196 IDF/Wiki/PageRevision.php:196 +#, php-format +msgid "%2$s, %3$s" +msgstr "" + +#: IDF/Wiki/Page.php:198 +#, php-format +msgid "Creation of page %2$s, by %3$s" +msgstr "" + +#: IDF/Wiki/Page.php:208 +#, php-format +msgid "%1$s: Documentation page %2$s added - %3$s" +msgstr "" + +#: IDF/Wiki/PageRevision.php:48 +msgid "page" +msgstr "" + +#: IDF/Wiki/PageRevision.php:66 IDF/Wiki/ResourceRevision.php:64 +msgid "A one line description of the changes." +msgstr "" + +#: IDF/Wiki/PageRevision.php:72 +msgid "content" +msgstr "" + +#: IDF/Wiki/PageRevision.php:218 IDF/Wiki/ResourceRevision.php:311 +#, fuzzy, php-format +msgid "Change of %2$s, by %3$s" +msgstr "问题 %d: %s" + +#: IDF/Wiki/PageRevision.php:231 +#, php-format +msgid "%1$s: Documentation page %2$s updated - %3$s" +msgstr "" + +#: IDF/Wiki/PageRevision.php:293 +#, php-format +msgid "New Documentation Page %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Wiki/PageRevision.php:297 +#, php-format +msgid "Documentation Page Changed %1$s - %2$s (%3$s)" +msgstr "" + +#: IDF/Wiki/Resource.php:65 +msgid "" +"The title of the resource must only contain letters, digits, dots or the " +"dash character. For example: my-resource.png." +msgstr "" + +#: IDF/Wiki/Resource.php:72 +msgid "MIME media type" +msgstr "" + +#: IDF/Wiki/Resource.php:73 +msgid "The MIME media type of the resource." +msgstr "" + +#: IDF/Wiki/Resource.php:81 +#, fuzzy +msgid "A one line description of the resource." +msgstr "项目简单描述" + +#: IDF/Wiki/Resource.php:176 IDF/Wiki/ResourceRevision.php:308 +#, fuzzy, php-format +msgid "%2$s, %3$s" +msgstr "问题 %3$d, %4$s" + +#: IDF/Wiki/Resource.php:178 +#, fuzzy, php-format +msgid "Creation of resource %2$s, by %3$s" +msgstr "评论 issue %d, 由 %s" + +#: IDF/Wiki/Resource.php:188 +#, php-format +msgid "%1$s: Documentation resource %2$s added - %3$s" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:47 +#, fuzzy +msgid "resource" +msgstr "源代码" + +#: IDF/Wiki/ResourceRevision.php:78 +msgid "File extension" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:79 +msgid "The file extension of the uploaded resource." +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:94 +msgid "page usage" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:116 +#, php-format +msgid "id %d: %s" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:263 +#, fuzzy, php-format +msgid "Download (%s)" +msgstr "下载 %s" + +#: IDF/Wiki/ResourceRevision.php:270 +msgid "View resource details" +msgstr "" + +#: IDF/Wiki/ResourceRevision.php:324 +#, php-format +msgid "%1$s: Documentation resource %2$s updated - %3$s" +msgstr "" + +#~ msgid "Your mail" +#~ msgstr "你的Email" diff --git a/indefero/src/IDF/relations.php b/indefero/src/IDF/relations.php new file mode 100644 index 0000000..b8ae4e3 --- /dev/null +++ b/indefero/src/IDF/relations.php @@ -0,0 +1,123 @@ + array('IDF_Project')); +$m['IDF_Tag'] = array('relate_to' => array('IDF_Project'), + 'relate_to_many' => array('IDF_Project')); +$m['IDF_Issue'] = array('relate_to' => array('IDF_Project', 'Pluf_User', 'IDF_Tag'), + 'relate_to_many' => array('IDF_Tag', 'Pluf_User')); +$m['IDF_IssueComment'] = array('relate_to' => array('IDF_Issue', 'Pluf_User')); +$m['IDF_IssueFile'] = array('relate_to' => array('IDF_IssueComment', 'Pluf_User')); +$m['IDF_Upload'] = array('relate_to' => array('IDF_Project', 'Pluf_User'), + 'relate_to_many' => array('IDF_Tag')); +$m['IDF_Search_Occ'] = array('relate_to' => array('IDF_Project'),); +$m['IDF_Wiki_Page'] = array('relate_to' => array('IDF_Project', 'Pluf_User'), + 'relate_to_many' => array('IDF_Tag', 'Pluf_User')); +$m['IDF_Wiki_PageRevision'] = array('relate_to' => array('IDF_Wiki_Page', 'Pluf_User')); +$m['IDF_Wiki_Resource'] = array('relate_to' => array('IDF_Project', 'Pluf_User')); +$m['IDF_Wiki_ResourceRevision'] = array('relate_to' => array('IDF_Wiki_Resource', 'Pluf_User'), + 'relate_to_many' => array('IDF_PageRevision', 'Pluf_User')); +$m['IDF_Review'] = array('relate_to' => array('IDF_Project', 'Pluf_User', 'IDF_Tag'), + 'relate_to_many' => array('IDF_Tag', 'Pluf_User')); +$m['IDF_Review_Patch'] = array('relate_to' => array('IDF_Review', 'Pluf_User')); +$m['IDF_Review_Comment'] = array('relate_to' => array('IDF_Review_Patch', 'Pluf_User')); +$m['IDF_Review_FileComment'] = array('relate_to' => array('IDF_Review_Comment', 'Pluf_User')); +$m['IDF_Key'] = array('relate_to' => array('Pluf_User')); +$m['IDF_Conf'] = array('relate_to' => array('IDF_Project')); +$m['IDF_Commit'] = array('relate_to' => array('IDF_Project', 'Pluf_User')); +$m['IDF_Scm_Cache_Git'] = array('relate_to' => array('IDF_Project')); + +$m['IDF_UserData'] = array('relate_to' => array('Pluf_User')); +$m['IDF_EmailAddress'] = array('relate_to' => array('Pluf_User')); +$m['IDF_IssueRelation'] = array('relate_to' => array('IDF_Issue', 'Pluf_User')); + +Pluf_Signal::connect('Pluf_Template_Compiler::construct_template_tags_modifiers', + array('IDF_Middleware', 'updateTemplateTagsModifiers')); + +# -- Standard plugins, they will run only if configured -- +# +# Subversion synchronization +Pluf_Signal::connect('IDF_Project::membershipsUpdated', + array('IDF_Plugin_SyncSvn', 'entry')); +Pluf_Signal::connect('IDF_Project::created', + array('IDF_Plugin_SyncSvn', 'entry')); +Pluf_Signal::connect('Pluf_User::passwordUpdated', + array('IDF_Plugin_SyncSvn', 'entry')); +Pluf_Signal::connect('IDF_Project::preDelete', + array('IDF_Plugin_SyncSvn', 'entry')); +Pluf_Signal::connect('svnpostcommit.php::run', + array('IDF_Plugin_SyncSvn', 'entry')); + +# +# Mercurial synchronization +Pluf_Signal::connect('IDF_Project::membershipsUpdated', + array('IDF_Plugin_SyncMercurial', 'entry')); +Pluf_Signal::connect('IDF_Project::created', + array('IDF_Plugin_SyncMercurial', 'entry')); +Pluf_Signal::connect('Pluf_User::passwordUpdated', + array('IDF_Plugin_SyncMercurial', 'entry')); +Pluf_Signal::connect('hgchangegroup.php::run', + array('IDF_Plugin_SyncMercurial', 'entry')); + +# +# Git synchronization +Pluf_Signal::connect('IDF_Project::membershipsUpdated', + array('IDF_Plugin_SyncGit', 'entry')); +Pluf_Signal::connect('IDF_Key::postSave', + array('IDF_Plugin_SyncGit', 'entry')); +Pluf_Signal::connect('IDF_Project::created', + array('IDF_Plugin_SyncGit', 'entry')); +Pluf_Signal::connect('IDF_Key::preDelete', + array('IDF_Plugin_SyncGit', 'entry')); +Pluf_Signal::connect('gitpostupdate.php::run', + array('IDF_Plugin_SyncGit', 'entry')); + +# +# monotone synchronization +Pluf_Signal::connect('IDF_Project::created', + array('IDF_Plugin_SyncMonotone', 'entry')); +Pluf_Signal::connect('IDF_Project::membershipsUpdated', + array('IDF_Plugin_SyncMonotone', 'entry')); +Pluf_Signal::connect('IDF_Project::preDelete', + array('IDF_Plugin_SyncMonotone', 'entry')); +Pluf_Signal::connect('IDF_Key::postSave', + array('IDF_Plugin_SyncMonotone', 'entry')); +Pluf_Signal::connect('IDF_Key::preDelete', + array('IDF_Plugin_SyncMonotone', 'entry')); +Pluf_Signal::connect('mtnpostpush.php::run', + array('IDF_Plugin_SyncMonotone', 'entry')); + +# +# -- Processing of the webhook queue -- +Pluf_Signal::connect('queuecron.php::run', + array('IDF_Queue', 'process')); + +# +# Processing of a given webhook, the hook can be configured +# directly in the configuration file if a different solution +# is required. +Pluf_Signal::connect('IDF_Queue::processItem', + Pluf::f('idf_hook_process_item', + array('IDF_Webhook', 'process'))); +return $m; diff --git a/indefero/src/IDF/templates/idf/admin/base.html b/indefero/src/IDF/templates/idf/admin/base.html new file mode 100644 index 0000000..863df48 --- /dev/null +++ b/indefero/src/IDF/templates/idf/admin/base.html @@ -0,0 +1,13 @@ +{extends "idf/base.html"} +{block tabadmin} class="active"{/block} +{block subtabs} + +{/block} diff --git a/indefero/src/IDF/templates/idf/admin/downloads.html b/indefero/src/IDF/templates/idf/admin/downloads.html new file mode 100644 index 0000000..a614484 --- /dev/null +++ b/indefero/src/IDF/templates/idf/admin/downloads.html @@ -0,0 +1,68 @@ +{extends "idf/admin/base.html"} +{block docclass}yui-t3{assign $inDownloads = true}{/block} +{block body} +
+ + + + + + + + + + + + + + + + +
{$form.f.labels_download_predefined.labelTag}:
+{if $form.f.labels_download_predefined.errors}{$form.f.labels_download_predefined.fieldErrors}{/if} +{$form.f.labels_download_predefined|unsafe} +
{$form.f.labels_download_one_max.labelTag}:
+{if $form.f.labels_download_one_max.errors}{$form.f.labels_download_one_max.fieldErrors}{/if} +{$form.f.labels_download_one_max|unsafe} +
{$form.f.upload_webhook_url.labelTag}:
+{if $form.f.upload_webhook_url.errors}{$form.f.upload_webhook_url.fieldErrors}{/if} +{$form.f.upload_webhook_url|unsafe}
+
{trans 'Web-Hook authentication key:'} {$hookkey}
+ +
+
+{/block} +{block context} +
+{blocktrans} +

Instructions:

+

List one status value per line in desired sort-order.

+

Optionally, use an equals-sign to document the meaning of each status value.

+{/blocktrans} +
+
+ +{blocktrans}

The webhook URL setting specifies an URL to which a HTTP PUT +request is sent after a new download has been added or to which a HTTP POST +request is sent after an existing download has been updated. +If this field is empty, notifications are disabled.

+ +

Only properly-escaped HTTP URLs are supported, for example:

+ +
    +
  • http://domain.com/upload
  • +
  • http://domain.com/upload?my%20param
  • +
+ +

In addition, the URL may contain the following "%" notation, which +will be replaced with specific project values for each download:

+ +
    +
  • %p - project name
  • +
  • %d - download id
  • +
+ +

For example, updating download 123 of project 'my-project' with +web hook URL http://mydomain.com/%p/%d would send a POST request to +http://mydomain.com/my-project/123.

{/blocktrans}
+{/block} diff --git a/indefero/src/IDF/templates/idf/admin/issue-tracking.html b/indefero/src/IDF/templates/idf/admin/issue-tracking.html new file mode 100644 index 0000000..0059130 --- /dev/null +++ b/indefero/src/IDF/templates/idf/admin/issue-tracking.html @@ -0,0 +1,63 @@ +{extends "idf/admin/base.html"} +{block docclass}yui-t1{assign $inIssueTracking = true}{/block} +{block body} +
+ + + + + + + + + + + + + + + + + + + + + + +
{$form.f.labels_issue_template.labelTag}:
+{if $form.f.labels_issue_template.errors}{$form.f.labels_issue_template.fieldErrors}{/if} +{$form.f.labels_issue_template|unsafe} +
{$form.f.labels_issue_open.labelTag}:
+{if $form.f.labels_issue_open.errors}{$form.f.labels_issue_open.fieldErrors}{/if} +{$form.f.labels_issue_open|unsafe} +
{$form.f.labels_issue_closed.labelTag}:
+{if $form.f.labels_issue_closed.errors}{$form.f.labels_issue_closed.fieldErrors}{/if} +{$form.f.labels_issue_closed|unsafe} +
{$form.f.labels_issue_predefined.labelTag}:
+{if $form.f.labels_issue_predefined.errors}{$form.f.labels_issue_predefined.fieldErrors}{/if} +{$form.f.labels_issue_predefined|unsafe}
+{$form.f.labels_issue_predefined.help_text} +
{$form.f.labels_issue_one_max.labelTag}:
+{if $form.f.labels_issue_one_max.errors}{$form.f.labels_issue_one_max.fieldErrors}{/if} +{$form.f.labels_issue_one_max|unsafe} +
{$form.f.issue_relations.labelTag}:
+{if $form.f.issue_relations.errors}{$form.f.issue_relations.fieldErrors}{/if} +{$form.f.issue_relations|unsafe}
+{$form.f.issue_relations.help_text} +
+ +
+
+ + +{/block} + +{block context} +
+{blocktrans} +

Instructions:

+

List one status value per line in desired sort-order.

+

Optionally, use an equals-sign to document the meaning of each status value.

+{/blocktrans} +
+{/block} diff --git a/indefero/src/IDF/templates/idf/admin/members.html b/indefero/src/IDF/templates/idf/admin/members.html new file mode 100644 index 0000000..a2835c9 --- /dev/null +++ b/indefero/src/IDF/templates/idf/admin/members.html @@ -0,0 +1,44 @@ +{extends "idf/admin/base.html"} +{block docclass}yui-t3{assign $inMembers = true}{/block} +{block body} +
+ + + + + + + + + + +
{$form.f.owners.labelTag}:
+{if $form.f.owners.errors}{$form.f.owners.fieldErrors}{/if} +{$form.f.owners|unsafe} +
{$form.f.members.labelTag}:
+{if $form.f.members.errors}{$form.f.members.fieldErrors}{/if} +{$form.f.members|unsafe} +
+ +
+
+ + +{/block} + +{block context} +
+{blocktrans} +

Instructions:

+

Specify each person by its login. Each person must have already registered with the given login.

+

Separate the logins with commas and/or new lines.

+{/blocktrans} +
+
+{blocktrans} +

Notes:

+

A project owner may make any change to this project, including removing other project owners. You need to be carefull when you give owner rights.

+

A project member will not have access to the administration area but will have more options available in the use of the project.

+{/blocktrans} +
+{/block} diff --git a/indefero/src/IDF/templates/idf/admin/source.html b/indefero/src/IDF/templates/idf/admin/source.html new file mode 100644 index 0000000..7317707 --- /dev/null +++ b/indefero/src/IDF/templates/idf/admin/source.html @@ -0,0 +1,92 @@ +{extends "idf/admin/base.html"} +{block docclass}yui-t3{assign $inSource = true}{/block} +{block body} +{if $form.errors} +
+

{trans 'The form contains some errors. Please correct them to update the source configuration.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +
+{/if} +
+ + + + + + + + +{if $repository_size != -1} + + + +{/if}{if $remote_svn} + + + + + + + +{/if} + + + + + + + + + + + + +
{trans 'Repository type:'}{$repository_type} +
{trans 'Repository access:'}{$repository_access} +
{trans 'Repository size:'}{$repository_size|size} +
{$form.f.svn_username.labelTag}:{if $form.f.svn_username.errors}{$form.f.svn_username.fieldErrors}{/if} +{$form.f.svn_username|unsafe} +
{$form.f.svn_password.labelTag}:{if $form.f.svn_password.errors}{$form.f.svn_password.fieldErrors}{/if} +{$form.f.svn_password|unsafe} +
{$form.f.webhook_url.labelTag}:{if $form.f.webhook_url.errors}{$form.f.webhook_url.fieldErrors}{/if} +{$form.f.webhook_url|unsafe}
+
{trans 'Web-Hook authentication key:'}{$hookkey} +
  + +
+
+{/block} +{block context} +
+

{blocktrans}You can find here the current repository configuration of your project.{/blocktrans}

+
+ + +
+
+ +{blocktrans}

The webhook URL setting specifies an URL to which a HTTP +{$hook_request_method} request is sent after each repository +commit. If this field is empty, notifications are disabled.

+ +

Only properly-escaped HTTP URLs are supported, for example:

+ +
    +
  • http://domain.com/commit
  • +
  • http://domain.com/commit?my%20param
  • +
+ +

In addition, the URL may contain the following "%" notation, which +will be replaced with specific project values for each commit:

+ +
    +
  • %p - project name
  • +
  • %r - revision number
  • +
+ +

For example, committing revision 123 to project 'my-project' with +post-commit URL http://mydomain.com/%p/%r would send a request to +http://mydomain.com/my-project/123.

{/blocktrans}
+{/block} diff --git a/indefero/src/IDF/templates/idf/admin/summary.html b/indefero/src/IDF/templates/idf/admin/summary.html new file mode 100644 index 0000000..16b3922 --- /dev/null +++ b/indefero/src/IDF/templates/idf/admin/summary.html @@ -0,0 +1,96 @@ +{extends "idf/admin/base.html"} +{block docclass}yui-t1{assign $inSummary = true}{/block} +{block body} +{if $form.errors} +
+

{trans 'The form contains some errors. Please correct them to update the summary.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +
+{/if} +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{if $logo} + + + + +{/if} + + + + + +
{$form.f.name.labelTag}:{if $form.f.name.errors}{$form.f.name.fieldErrors}{/if} +{$form.f.name|unsafe} +
{$form.f.shortdesc.labelTag}:{if $form.f.shortdesc.errors}{$form.f.shortdesc.fieldErrors}{/if} +{$form.f.shortdesc|unsafe}
+{$form.f.shortdesc.help_text} +
{$form.f.external_project_url.labelTag}:{if $form.f.external_project_url.errors}{$form.f.external_project_url.fieldErrors}{/if} +{$form.f.external_project_url|unsafe} +
{$form.f.description.labelTag}:{if $form.f.description.errors}{$form.f.description.fieldErrors}{/if} +{$form.f.description|unsafe} +
{$form.f.label1.labelTag}: +{if $form.f.label1.errors}{$form.f.label1.fieldErrors}{/if}{$form.f.label1|unsafe} +{if $form.f.label2.errors}{$form.f.label2.fieldErrors}{/if}{$form.f.label2|unsafe} +{if $form.f.label3.errors}{$form.f.label3.fieldErrors}{/if}{$form.f.label3|unsafe}
+{if $form.f.label4.errors}{$form.f.label4.fieldErrors}{/if}{$form.f.label4|unsafe} +{if $form.f.label5.errors}{$form.f.label5.fieldErrors}{/if}{$form.f.label5|unsafe} +{if $form.f.label6.errors}{$form.f.label6.fieldErrors}{/if}{$form.f.label6|unsafe} +
{trans 'Current logo'}: +{if $logo} +{trans 'Project logo'} +{else} +{trans 'Your project does not have a logo configured yet.'} +{/if} +
{$form.f.logo.labelTag}:{if $form.f.logo.errors}{$form.f.logo.fieldErrors}{/if} +{$form.f.logo|unsafe} +
{$form.f.logo_remove.labelTag}:{if $form.f.logo_remove.errors}{$form.f.logo_remove.fieldErrors}{/if} +{$form.f.logo_remove|unsafe} +
{$form.f.enableads.labelTag}:{if $form.f.enableads.errors}{$form.f.enableads.fieldErrors}{/if} +{$form.f.enableads|unsafe} +
  + +
+
+{include 'idf/project/js-autocomplete.html'}{/block} +{/block} + +{block context} +
+{assign $url = 'http://daringfireball.net/projects/markdown/syntax'} +{blocktrans} +

Instructions:

+

The description of the project can be improved using the Markdown syntax.

+{/blocktrans} +
+{/block} diff --git a/indefero/src/IDF/templates/idf/admin/tabs.html b/indefero/src/IDF/templates/idf/admin/tabs.html new file mode 100644 index 0000000..10ae8dc --- /dev/null +++ b/indefero/src/IDF/templates/idf/admin/tabs.html @@ -0,0 +1,161 @@ +{extends "idf/admin/base.html"} +{block docclass}yui-t3{assign $inTabs = true}{/block} +{block body} +{if $form.errors} +
+

{trans 'The form contains some errors. Please correct them to update the access rights.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +
+{/if} +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 {trans 'Access Rights'}{trans 'Notifications'}
{$form.f.downloads_access_rights.labelTag}:{if $form.f.downloads_access_rights.errors}{$form.f.downloads_access_rights.fieldErrors}{/if} +{$form.f.downloads_access_rights|unsafe} +{if $form.f.downloads_notification_email.errors}{$form.f.downloads_notification_email.fieldErrors}{/if} +{$form.f.downloads_notification_owners_enabled|unsafe} +{$form.f.downloads_notification_owners_enabled.labelTag} +{$form.f.downloads_notification_members_enabled|unsafe} +{$form.f.downloads_notification_members_enabled.labelTag} +{$form.f.downloads_notification_email_enabled|unsafe} +{$form.f.downloads_notification_email_enabled.labelTag} +{$form.f.downloads_notification_email|unsafe} +
{$form.f.wiki_access_rights.labelTag}:{if $form.f.wiki_access_rights.errors}{$form.f.wiki_access_rights.fieldErrors}{/if} +{$form.f.wiki_access_rights|unsafe} +{if $form.f.wiki_notification_email.errors}{$form.f.wiki_notification_email.fieldErrors}{/if} +{$form.f.wiki_notification_owners_enabled|unsafe} +{$form.f.wiki_notification_owners_enabled.labelTag} +{$form.f.wiki_notification_members_enabled|unsafe} +{$form.f.wiki_notification_members_enabled.labelTag} +{$form.f.wiki_notification_email_enabled|unsafe} +{$form.f.wiki_notification_email_enabled.labelTag} +{$form.f.wiki_notification_email|unsafe} +
{$form.f.issues_access_rights.labelTag}:{if $form.f.issues_access_rights.errors}{$form.f.issues_access_rights.fieldErrors}{/if} +{$form.f.issues_access_rights|unsafe} +{if $form.f.issues_notification_email.errors}{$form.f.issues_notification_email.fieldErrors}{/if} +{$form.f.issues_notification_owners_enabled|unsafe} +{$form.f.issues_notification_owners_enabled.labelTag} +{$form.f.issues_notification_members_enabled|unsafe} +{$form.f.issues_notification_members_enabled.labelTag} +{$form.f.issues_notification_email_enabled|unsafe} +{$form.f.issues_notification_email_enabled.labelTag} +{$form.f.issues_notification_email|unsafe} +
{$form.f.source_access_rights.labelTag}:{if $form.f.source_access_rights.errors}{$form.f.source_access_rights.fieldErrors}{/if} +{$form.f.source_access_rights|unsafe} +{if $form.f.source_notification_email.errors}{$form.f.source_notification_email.fieldErrors}{/if} +{$form.f.source_notification_owners_enabled|unsafe} +{$form.f.source_notification_owners_enabled.labelTag} +{$form.f.source_notification_members_enabled|unsafe} +{$form.f.source_notification_members_enabled.labelTag} +{$form.f.source_notification_email_enabled|unsafe} +{$form.f.source_notification_email_enabled.labelTag} +{$form.f.source_notification_email|unsafe} +
{$form.f.review_access_rights.labelTag}:{if $form.f.review_access_rights.errors}{$form.f.review_access_rights.fieldErrors}{/if} +{$form.f.review_access_rights|unsafe} +{if $form.f.review_notification_email.errors}{$form.f.review_notification_email.fieldErrors}{/if} +{$form.f.review_notification_owners_enabled|unsafe} +{$form.f.review_notification_owners_enabled.labelTag} +{$form.f.review_notification_members_enabled|unsafe} +{$form.f.review_notification_members_enabled.labelTag} +{$form.f.review_notification_email_enabled|unsafe} +{$form.f.review_notification_email_enabled.labelTag} +{$form.f.review_notification_email|unsafe} +
  +{if $form.f.private_project.errors}{$form.f.private_project.fieldErrors}{/if} +{$form.f.private_project|unsafe} +{$form.f.private_project.labelTag} +
 {$form.f.authorized_users.labelTag}:
+{if $form.f.authorized_users.errors}{$form.f.authorized_users.fieldErrors}{/if} +{$form.f.authorized_users|unsafe} +
  + +
+
+{/block} +{block context} +
+

{blocktrans}This section allows you to configure project tabs access rights and notifications.{/blocktrans}

+

{trans 'Access Rights'}

+

{blocktrans}Tab access controls whether a single user can navigate into a particular section of your project via the main menu or automatically generated object links.{/blocktrans}

+

{blocktrans}If you mark a project as private, only the project members and administrators, together with the extra authorized users you provide will have access to the project as a whole. You will still be able to define further access rights for the different tabs but the "Open to all" and "Signed in users" will default to authorized users only.{/blocktrans}

+

{blocktrans}For the extra authorized user list, specify each person by its login. Each person must have already registered with the given login. Separate the logins with commas and/or new lines.{/blocktrans}

+

{blocktrans}Only project members and admins have write access to the source. If you restrict the access to the source, anonymous access is not provided and the users must authenticate themselves with their password or SSH key.{/blocktrans}

+

{trans 'Notifications'}

+

{blocktrans}Here you can configure who should be notified about changes in a particular section. You can also configure additional addresses, like the one of a mailing list, that should be notified. (Keep in mind that you might have to register the sender address {$from_email} to let the mailing list actually accept notification emails.) Multiple email addresses must be separated through commas (',').{/blocktrans}

+
+{/block} + +{block javascript}{literal} + +{/literal}{/block} diff --git a/indefero/src/IDF/templates/idf/admin/wiki.html b/indefero/src/IDF/templates/idf/admin/wiki.html new file mode 100644 index 0000000..cd28aca --- /dev/null +++ b/indefero/src/IDF/templates/idf/admin/wiki.html @@ -0,0 +1,34 @@ +{extends "idf/admin/base.html"} +{block docclass}yui-t1{assign $inWiki = true}{/block} +{block body} +
+ + + + + + + + + + +
{$form.f.labels_wiki_predefined.labelTag}:
+{if $form.f.labels_wiki_predefined.errors}{$form.f.labels_wiki_predefined.fieldErrors}{/if} +{$form.f.labels_wiki_predefined|unsafe} +
{$form.f.labels_wiki_one_max.labelTag}:
+{if $form.f.labels_wiki_one_max.errors}{$form.f.labels_wiki_one_max.fieldErrors}{/if} +{$form.f.labels_wiki_one_max|unsafe} +
+ +
+
+{/block} +{block context} +
+{blocktrans} +

Instructions:

+

List one status value per line in desired sort-order.

+

Optionally, use an equals-sign to document the meaning of each status value.

+{/blocktrans} +
+{/block} diff --git a/indefero/src/IDF/templates/idf/base-full.html b/indefero/src/IDF/templates/idf/base-full.html new file mode 100644 index 0000000..68a4f25 --- /dev/null +++ b/indefero/src/IDF/templates/idf/base-full.html @@ -0,0 +1,89 @@ + +{* +# ***** BEGIN LICENSE BLOCK ***** +# This file is part of InDefero, an open source project management application. +# Copyright (C) 2008-2011 Céondo Ltd and contributors. +# +# InDefero is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# InDefero is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# ***** END LICENSE BLOCK ***** +*} + + + + + + + {block extraheader}{/block} + {block pagetitle}{$page_title|strip_tags}{/block}{if $project} - {$project.shortdesc}{/if} + + {appversion} + + +
+
+ {if $project}

{$project}{if $project.private}{trans 'Private project'}{/if}{$p}{assign $url = $project.external_project_url}{if $url != ''} {/if}

{/if} + {include 'idf/main-menu.html'} + + +

{block titleicon}{/block}{block title}{$page_title}{/block}

+ +
+
+
+
+
+ {if $user and $user.id}{getmsgs $user}{/if} +
{block body}{/block}
+
+
+
+
+
{block foot}{/block}
+
+{include 'idf/js-hotkeys.html'} +{block javascript}{/block} +{if $project} +{/if} + + diff --git a/indefero/src/IDF/templates/idf/base-simple.html b/indefero/src/IDF/templates/idf/base-simple.html new file mode 100644 index 0000000..e1323ad --- /dev/null +++ b/indefero/src/IDF/templates/idf/base-simple.html @@ -0,0 +1,60 @@ + +{* +# ***** BEGIN LICENSE BLOCK ***** +# This file is part of InDefero, an open source project management application. +# Copyright (C) 2008-2011 Céondo Ltd and contributors. +# +# InDefero is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# InDefero is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# ***** END LICENSE BLOCK ***** +*} + + + + + + + {block extraheader}{/block} + {block pagetitle}{$page_title|strip_tags}{/block} + + {appversion} + + +
+
+ {include 'idf/main-menu.html'} +

{block title}{$page_title}{/block}

+
+
+
+
+
+ {if $user and $user.id}{getmsgs $user}{/if} +
{block body}{/block}
+
+
+
+
{block context}{/block}
+
+
{block foot}{/block}
+
+{include 'idf/js-hotkeys.html'} +{include 'idf/list-filter.html'} +{block javascript}{/block} + + diff --git a/indefero/src/IDF/templates/idf/base.html b/indefero/src/IDF/templates/idf/base.html new file mode 100644 index 0000000..0da2c3f --- /dev/null +++ b/indefero/src/IDF/templates/idf/base.html @@ -0,0 +1,114 @@ + +{* +# ***** BEGIN LICENSE BLOCK ***** +# This file is part of InDefero, an open source project management application. +# Copyright (C) 2008-2011 Céondo Ltd and contributors. +# +# InDefero is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# InDefero is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# ***** END LICENSE BLOCK ***** +*} + + + + + + + + {block extraheader}{/block} + {block pagetitle}{$page_title|strip_tags}{/block}{if $project} - {$project.shortdesc}{/if} + + {appversion} + + + +
+
+ {if $project} +

{$project}{if $project.private}{trans 'Private project'}{/if}{$p}{assign $url = $project.external_project_url}{if $url != ''} {/if}

{/if} + {include 'idf/main-menu.html'} + + +{if $project.enableads}

+ + + +

{/if} +

{block titleicon}{/block}{block title}{$page_title}{/block}

+
+
+
+
+
+
+ {if $user and $user.id}{getmsgs $user}{/if} +
{block body}{/block}
+
+
+
+
{block context}{/block}
+
+
{block foot}{/block}
+
+{include 'idf/js-hotkeys.html'} +{include 'idf/list-filter.html'} +{block javascript}{/block} +{if $project} +{/if} + + diff --git a/indefero/src/IDF/templates/idf/downloads/base.html b/indefero/src/IDF/templates/idf/downloads/base.html new file mode 100644 index 0000000..248bf73 --- /dev/null +++ b/indefero/src/IDF/templates/idf/downloads/base.html @@ -0,0 +1,11 @@ +{extends "idf/base.html"} +{block tabdownloads} class="active"{/block} +{block subtabs} +
+{trans 'Downloads'} +{if $isOwner or $isMember} +| {trans 'New Download'} +| {trans 'Upload Archive'} +{/if} +
+{/block} diff --git a/indefero/src/IDF/templates/idf/downloads/create.html b/indefero/src/IDF/templates/idf/downloads/create.html new file mode 100644 index 0000000..c032004 --- /dev/null +++ b/indefero/src/IDF/templates/idf/downloads/create.html @@ -0,0 +1,68 @@ +{extends "idf/downloads/base.html"} +{block docclass}yui-t3{assign $inCreate=true}{/block} +{block body} +{if $form.errors} +
+

{trans 'The form contains some errors. Please correct them to submit the file.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +
+{/if} + +
+ + + + + + + + + + + + + + + + + + + + + +
{$form.f.summary.labelTag}:{if $form.f.summary.errors}{$form.f.summary.fieldErrors}{/if} +{$form.f.summary|unsafe} +
{$form.f.changelog.labelTag}:{if $form.f.changelog.errors}{$form.f.changelog.fieldErrors}{/if} +{$form.f.changelog|unsafe} +
{$form.f.file.labelTag}:{if $form.f.file.errors}{$form.f.file.fieldErrors}{/if} +{$form.f.file|unsafe} +
{$form.f.label1.labelTag}: +{if $form.f.label1.errors}{$form.f.label1.fieldErrors}{/if}{$form.f.label1|unsafe} +{if $form.f.label2.errors}{$form.f.label2.fieldErrors}{/if}{$form.f.label2|unsafe} +{if $form.f.label3.errors}{$form.f.label3.fieldErrors}{/if}{$form.f.label3|unsafe}
+{if $form.f.label4.errors}{$form.f.label4.fieldErrors}{/if}{$form.f.label4|unsafe} +{if $form.f.label5.errors}{$form.f.label5.fieldErrors}{/if}{$form.f.label5|unsafe} +{if $form.f.label6.errors}{$form.f.label6.fieldErrors}{/if}{$form.f.label6|unsafe} +
  | {trans 'Cancel'} +
+
+{/block} +{block context} +
+

{trans 'Instructions'}

+ +

{blocktrans}Each file must have a distinct name and file contents +cannot be changed, so be sure to include release numbers in each file +name.{/blocktrans}

+{assign $url = 'http://daringfireball.net/projects/markdown/syntax'} +

{blocktrans}You can use the Markdown syntax for the description.{/blocktrans}

+
+{/block} +{block javascript} + +{include 'idf/downloads/js-autocomplete.html'}{/block} + diff --git a/indefero/src/IDF/templates/idf/downloads/createFromArchive.html b/indefero/src/IDF/templates/idf/downloads/createFromArchive.html new file mode 100644 index 0000000..50db50f --- /dev/null +++ b/indefero/src/IDF/templates/idf/downloads/createFromArchive.html @@ -0,0 +1,38 @@ +{extends "idf/downloads/base.html"} +{block docclass}yui-t3{assign $inCreateFromArchive=true}{/block} +{block body} +{if $form.errors} +
+

{trans 'The form contains some errors. Please correct them to submit the archive.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +
+{/if} + +
+ + + + + + + + + +
{$form.f.archive.labelTag}:{if $form.f.archive.errors}{$form.f.archive.fieldErrors}{/if} +{$form.f.archive|unsafe} +
  | {trans 'Cancel'} +
+
+{/block} +{block context} +
+

{trans 'Instructions'}

+ +

{blocktrans}The archive must include a manifest.xml file with meta information about the +files to process inside the archive. All processed files must be unique or replace existing files explicitely.{/blocktrans}

+{aurl 'url', 'IDF_Views::faqArchiveFormat'} +

{blocktrans}You can learn more about the archive format here.{/blocktrans}

+
+{/block} diff --git a/indefero/src/IDF/templates/idf/downloads/delete.html b/indefero/src/IDF/templates/idf/downloads/delete.html new file mode 100644 index 0000000..621be7c --- /dev/null +++ b/indefero/src/IDF/templates/idf/downloads/delete.html @@ -0,0 +1,40 @@ +{extends "idf/downloads/base.html"} +{block docclass}yui-t3{assign $inDownloads=true}{/block} +{block body} + +
+{$file} - {$file.filesize|size} +
+ +

{blocktrans}Attention! If you want to delete a specific version of your software, maybe, someone is depending on this specific version to run his systems. Are you sure, you will not affect anybody when removing this file?{/blocktrans}

+ +{if !$deprecated}{aurl 'url', 'IDF_Views_Download::view', array($project.shortname, $file.id)} +

{blocktrans}Instead of deleting the file, you could mark it as deprecated.{/blocktrans}

{/if} + +
+ + + + + +
  | {trans 'Cancel'} +
+
+ +{/block} + +{block context} +{assign $submitter = $file.get_submitter()} +

{trans 'Uploaded:'} {$file.creation_dtime|dateago} {blocktrans}by {$submitter}{/blocktrans}

+{if $file.modif_dtime != $file.creation_dtime}

+{trans 'Updated:'} {$file.modif_dtime|dateago}

{/if} +

+{trans 'Downloads:'} {$file.downloads}

+{if $tags.count()} +

+{trans 'Labels:'}
+{foreach $tags as $tag}{aurl 'url', 'IDF_Views_Download::listLabel', array($project.shortname, $tag.id)} +{$tag.class}:{$tag.name}
+{/foreach} +

{/if} +{/block} diff --git a/indefero/src/IDF/templates/idf/downloads/download-created-email.txt b/indefero/src/IDF/templates/idf/downloads/download-created-email.txt new file mode 100644 index 0000000..6d7dfb0 --- /dev/null +++ b/indefero/src/IDF/templates/idf/downloads/download-created-email.txt @@ -0,0 +1,17 @@ +{trans 'Hello,'} + +{blocktrans}A new file is available for download:{/blocktrans} + +{$file.summary|safe} +{$file} - {$file.filesize|ssize} +{trans 'Project:'} {$project.name|safe} +{trans 'Submitted by:'} {$file.get_submitter|safe} +{if $tags.count()}{trans 'Labels:'} +{foreach $tags as $tag} {$tag.class|safe}:{$tag.name|safe} +{/foreach}{/if} +{trans 'Download:'} {$urlfile} +{if $file.changelog} +{trans 'Description:'} + +{$file.changelog} +{/if} diff --git a/indefero/src/IDF/templates/idf/downloads/download-updated-email.txt b/indefero/src/IDF/templates/idf/downloads/download-updated-email.txt new file mode 100644 index 0000000..1f5b1cf --- /dev/null +++ b/indefero/src/IDF/templates/idf/downloads/download-updated-email.txt @@ -0,0 +1,17 @@ +{trans 'Hello,'} + +{blocktrans}A file download was updated:{/blocktrans} + +{$file.summary|safe} +{$file} - {$file.filesize|ssize} +{trans 'Project:'} {$project.name|safe} +{trans 'Submitted by:'} {$file.get_submitter|safe} +{if $tags.count()}{trans 'Labels:'} +{foreach $tags as $tag} {$tag.class|safe}:{$tag.name|safe} +{/foreach}{/if} +{trans 'Download:'} {$urlfile} +{if $file.changelog} +{trans 'Description:'} + +{$file.changelog} +{/if} diff --git a/indefero/src/IDF/templates/idf/downloads/feedfragment.xml b/indefero/src/IDF/templates/idf/downloads/feedfragment.xml new file mode 100644 index 0000000..601df74 --- /dev/null +++ b/indefero/src/IDF/templates/idf/downloads/feedfragment.xml @@ -0,0 +1,14 @@ + + {$title} + + {$url} + {$date} + {$file.get_submitter()} +
+

{$file} - {$file.filesize|ssize}

+{if $file.changelog} +

{trans 'Details'}

+{markdown $file.changelog, $request} +{/if} +
+
diff --git a/indefero/src/IDF/templates/idf/downloads/index.html b/indefero/src/IDF/templates/idf/downloads/index.html new file mode 100644 index 0000000..97e76b3 --- /dev/null +++ b/indefero/src/IDF/templates/idf/downloads/index.html @@ -0,0 +1,21 @@ +{extends "idf/downloads/base.html"} +{block docclass}yui-t1{assign $inDownloads=true}{/block} +{block body} +{$downloads.render} +{if $isOwner or $isMember} +{aurl 'url', 'IDF_Views_Download::create', array($project.shortname)} +

+ {trans 'New Download'}

{/if} + +{/block} +{block context} +

{trans 'Number of files:'} {$downloads.nb_items}

+{assign $cloud_url = 'IDF_Views_Download::listLabel'} +{assign $cloud = 'downloads'} +{include 'idf/tags-cloud.html'} +{if $deprecated > 0} +{aurl 'url', 'IDF_Views_Download::listLabel', array($project.shortname, $dlabel.id)} +

{blocktrans}See the deprecated files.{/blocktrans}

+{/if} + +{/block} + diff --git a/indefero/src/IDF/templates/idf/downloads/js-autocomplete.html b/indefero/src/IDF/templates/idf/downloads/js-autocomplete.html new file mode 100644 index 0000000..6949c8f --- /dev/null +++ b/indefero/src/IDF/templates/idf/downloads/js-autocomplete.html @@ -0,0 +1,27 @@ +{if $isOwner or $isMember} + + + +{/if} diff --git a/indefero/src/IDF/templates/idf/downloads/view.html b/indefero/src/IDF/templates/idf/downloads/view.html new file mode 100644 index 0000000..478a0b9 --- /dev/null +++ b/indefero/src/IDF/templates/idf/downloads/view.html @@ -0,0 +1,82 @@ +{extends "idf/downloads/base.html"} +{block docclass}yui-t3{assign $inDownloads=true}{/block} +{block body} + +
+{if $deprecated}

{blocktrans}Attention! This file is marked as deprecated, download it only if you are sure you need this specific version.{/blocktrans}

{/if} +{$file} - {$file.filesize|size} +
+{trans 'md5:'} {$file.md5} +
+{if $file.changelog} +

{trans 'Changes'}

+ +{markdown $file.changelog, $request} +{/if} + +{if $form} +{if $form.errors} +
+

{trans 'The form contains some errors. Please correct them to update the file.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +
+{/if} + +
+ + + + + + + + + + + + + + +{aurl 'url', 'IDF_Views_Download::delete', array($project.shortname, $file.id)} + + +
{$form.f.summary.labelTag}:{if $form.f.summary.errors}{$form.f.summary.fieldErrors}{/if} +{$form.f.summary|unsafe} +
{$form.f.changelog.labelTag}:{if $form.f.changelog.errors}{$form.f.changelog.fieldErrors}{/if} +{$form.f.changelog|unsafe} +
{$form.f.label1.labelTag}: +{if $form.f.label1.errors}{$form.f.label1.fieldErrors}{/if}{$form.f.label1|unsafe} +{if $form.f.label2.errors}{$form.f.label2.fieldErrors}{/if}{$form.f.label2|unsafe} +{if $form.f.label3.errors}{$form.f.label3.fieldErrors}{/if}{$form.f.label3|unsafe}
+{if $form.f.label4.errors}{$form.f.label4.fieldErrors}{/if}{$form.f.label4|unsafe} +{if $form.f.label5.errors}{$form.f.label5.fieldErrors}{/if}{$form.f.label5|unsafe} +{if $form.f.label6.errors}{$form.f.label6.fieldErrors}{/if}{$form.f.label6|unsafe} +
 {* float left is a fix for Firefox < 3.5 *} + | {trans 'Cancel'} {trans 'Trash'} {trans 'Delete this file'} +
+
+{/if} +{/block} +{block context} +{ashowuser 'submitter', $file.get_submitter(), $request} +

{trans 'Uploaded:'} {$file.creation_dtime|dateago} {blocktrans}by {$submitter}{/blocktrans}

+{if $file.modif_dtime != $file.creation_dtime}

+{trans 'Updated:'} {$file.modif_dtime|dateago}

{/if} +

+{trans 'Downloads:'} {$file.downloads}

+{if $tags.count()} +

+{trans 'Labels:'}
+{foreach $tags as $tag}{aurl 'url', 'IDF_Views_Download::listLabel', array($project.shortname, $tag.id)} +{$tag.class}:{$tag.name}
+{/foreach} +

{/if} +{/block} +{block javascript}{if $form} + +{include 'idf/downloads/js-autocomplete.html'}{/if}{/block} + diff --git a/indefero/src/IDF/templates/idf/faq-api.html b/indefero/src/IDF/templates/idf/faq-api.html new file mode 100644 index 0000000..31eaef8 --- /dev/null +++ b/indefero/src/IDF/templates/idf/faq-api.html @@ -0,0 +1,83 @@ +{extends "idf/base-simple.html"} +{block docclass}yui-t3{/block} +{block body} +

At the moment, this documentation is only available in English.

+ + + +

How to access the API?

+ +

+The API is a REST API and you can access it by using the same URL you +are using for the web interface but with the /api/ +prefix. +

+

+For example, if you access a project with the +URL http://www.example.com/p/myproject/, you have the +following API URLs available: +

+
    +
  • http://www.example.com/api/p/myproject/issues/: list the open issues.
  • +
  • http://www.example.com/api/p/myproject/issues/create/: create a new issue.
  • +
+

+The answer you get is JSON and UTF-8 encoded. +

+ + +

How to authenticate the queries?

+ +

+Authentication is really simple and is optional. If you do not +authenticate your queries, you will have the same rights as an +anonymous user visiting the normal web interface. +

+

+To authenticate your query, you need to provide 3 parameters to your +requests, the parameters are the followings: +

+
    +
  • _login: your login.
  • +
  • _salt: a random salt string.
  • +
  • _hash: the sha1 hash created from the concatenation of the random salt string and the API key.
  • +
+

+Please note that the 3 parameters are all starting with the underscore +"_" character. +

+

+An example of PHP code to generate the _hash value is: +

+
+<?php 
+$api_key = '1234567890abcdefghijklmnopqrstuvwxyz';
+$_salt = rand(10000, 999999);
+$_hash = sha1($_salt.$api_key);
+echo sprintf("_salt: %s\n", $_salt);
+echo sprintf("_hash: %s\n", $_hash);
+?>
+
+

+If you replace the string '123...xyz' with your own API key and +execute this script, you will have as output something like that: +

+
+_salt: 123456
+_hash: 1357924680acegikmoqsuwybdfhjlnprtvxz
+
+

+Together with your login, you will be able to use those values to +authenticate a query. +

+ +{/block} {block context} +

{trans 'Here we are, just to help you.'}

+

{trans 'Projects'}

+
    {foreach $projects as $p} +
  • {$p}
  • +{/foreach}
+{/block} diff --git a/indefero/src/IDF/templates/idf/faq-archive-format.html b/indefero/src/IDF/templates/idf/faq-archive-format.html new file mode 100644 index 0000000..7952bb5 --- /dev/null +++ b/indefero/src/IDF/templates/idf/faq-archive-format.html @@ -0,0 +1,125 @@ +{extends "idf/base-simple.html"} +{block docclass}yui-t3{/block} +{block body} +

At the moment, this documentation is only available in English.

+ + + +

Motivation

+ +

+Adding multiple, individual downloads to a project for a release can be a tedious task if +one has to select each file manually, and then has to fill in the summary and correct labels +for each of these downloads individually. +

+ +

+InDefero therefore supports the upload of "archives" that contain multiple downloadable +files. These archives are standard PKZIP files with only one special property - they +contain an additional manifest file which describes the files that should be published. +

+ +

+Once such an archive has been uploaded and validated by InDefero, its files are extracted +and individual downloads are created for each of them. If the archive contains files +that should replace existing downloads, then InDefero takes care of this as well - +automatically. Files that exist in the archive but are not listed in the manifest are +not extracted. +

+ +

+An archive file and its manifest file can easily be compiled, either by hand with the help +of a text editor, or through an automated build system with the help of your build tool of +choice, such as Apache Ant. +

+ +

The manifest format

+ +

+The manifest is an XML file that follows a simple syntax. As it is always easier to look +at an example, here you have one: +

+ +
+<?xml version="1.0" encoding="UTF-8" ?>
+<manifest>
+  <file>
+    <name>foo-1.2.tar.gz</name>
+    <summary>Tarball</summary>
+    <replaces>foo-1.1.tar.gz</replaces>
+    <labels>
+       <label>Type:Archive</label>
+    </labels>
+  </file>
+  <file>
+    <name>foo-1.2-installer.exe</name>
+    <summary>Windows MSI Installer</summary>
+    <description>This installer needs Windows XP SP2 or later.</description>
+    <labels>
+       <label>Type:Installer</label>
+       <label>OpSys:Windows</label>
+    </labels>
+  </file>
+</manifest>
+
+ +

+This is the DTD for the format: +

+ +
+<!DOCTYPE manifest [
+<!ELEMENT manifest (file+)>
+<!ELEMENT file (name,summary,replaces?,description?,tags?)>
+<!ELEMENT name (#PCDATA)>
+<!ELEMENT summary (#PCDATA)>
+<!ELEMENT replaces (#PCDATA)>
+<!ELEMENT description (#PCDATA)>
+<!ELEMENT labels (label+)>
+<!ELEMENT label (#PCDATA)>
+]>
+
+ +

+The format is more or less self-explaining, all fields map to properties of a single download. Note +that there is a limit of six labels that you can attach to a download, similar to +what the regular file upload functionality allows. +

+ +

One special element has been introduced and this is named replaces. If this optional element +is given, InDefero looks for a file with that name in the project and acts in one of the following +two ways: +

+ +
    +
  • If the new file's name is distinct from the file's name that is given in replaces, +then the replaced file is marked as deprecated with the Other:Deprecated label +(or any other label that is configured as the very last label in the download project configuration).
  • +
  • If the new file's name is equal to the file's name that is given in replaces, +then the replaced file is deleted before the new file is created. This happens because each file name +has to be unique per project and a deprecated and a new file with the same name cannot coexist in InDefero. +Note that while the filename-based URI of the download keeps intact, the download counter will be reset by +this procedure.
  • +
+ +If no existing file is found for the replaces tag, then this is completely ignored. +

+ +

Final notes

+ +

Any file in the archive that is not enlisted in the manifest is ignored during +the upload process, so ensure that your manifest.xml contains all the file names (case +sensitive) you want to be processed.

+{/block} + +{block context} +

{trans 'Here we are, just to help you.'}

+

{trans 'Projects'}

+
    {foreach $projects as $p} +
  • {$p}
  • +{/foreach}
+{/block} diff --git a/indefero/src/IDF/templates/idf/faq.html b/indefero/src/IDF/templates/idf/faq.html new file mode 100644 index 0000000..0e744df --- /dev/null +++ b/indefero/src/IDF/templates/idf/faq.html @@ -0,0 +1,101 @@ +{extends "idf/base-simple.html"} +{block docclass}yui-t3{/block} +{block body} + + +

{trans 'What are the keyboard shortcuts?'}

+ +
    +
  • {trans 'Shift+h: This help page.'}
  • +
+ +

{trans 'If you are in a project, you have the following shortcuts:'}

+ +
    +
  • {trans 'Shift+u: Project updates.'}
  • +
  • {trans 'Shift+d: Downloads.'}
  • +
  • {trans 'Shift+o: Documentation.'}
  • +
  • {trans 'Shift+a: Create a new issue.'}
  • +
  • {trans 'Shift+i: List of open issues.'}
  • +
  • {trans 'Shift+m: The issues you submitted.'}
  • +
  • {trans 'Shift+w: The issues assigned to you.'}
  • +
  • {trans 'Shift+s: Source.'}
  • +
+ +

{trans 'You also have the standard access keys:'}

+ +
    +
  • {trans 'Alt+1: Home.'}
  • +
  • {trans 'Alt+2: Skip the menus.'}
  • +
  • {trans 'Alt+4: Search (when available).'}
  • +
+ +

{trans 'How to mark an issue as duplicate?'}

+ +{blocktrans}

This is simple:

+
    +
  1. Write in the comments "This is a duplicate of issue 123" or - if you are a member of the crew - +directly add the "duplicates" relation with the value "123" below the comment field. Change "123" +with the corresponding issue number.
  2. +
  3. Change the status of the current issue to Duplicate.
  4. +
  5. Submit the changes.
  6. +
{/blocktrans} + +

{trans 'How can I display my head next to my comments?'}

+ +

{blocktrans}You need to create an account on Gravatar, this takes about 5 minutes and is free.{/blocktrans}

+ +

{trans 'How can I embed images and other resources in my documentation pages?'}

+ +{blocktrans} +

To embed any previously uploaded resource into your wiki page, you can use the [[!ResourceName]] syntax.

+ +

The rendering of the resource can then be further fine-tuned: +

    +
  • [[!ImageResource, align=right, width=200]] renders "ImageResource" right-aligned and scale its width to 200
  • +
  • [[!TextResource, align=center, width=300, height=300]] renders "TextResource" in a centered, 300 by 300 px iframe
  • +
  • [[!AnyResource, preview=no]] does not render a preview of the resource, but only provides a download link (default for binary resources)
  • +
  • [[!BinaryResource, title=Download]] renders the download link of "BinaryResource" with an alternative title
  • +
+

+ +Resources are versioned, just like wiki pages. If you update a resource, old wiki pages still show the state of the resource +at the time when the wiki page was edited. If you specifically want to update a resource on a page, you therefor need to update +the resource at first and then also the page where it is referenced, otherwise the change won't be visible until the next regular edit. +{/blocktrans} + +

{trans 'What is this "Upload Archive" functionality about?'}

+ +{blocktrans}

If you have to publish many files at once for a new release, it is a very tedious task +to upload them one after another and enter meta information like a summary, a description or additional +labels for each of them.

+

InDefero therefore supports a special archive format that is basically a standard zip file which comes with +some meta information. These meta information are kept in a special manifest file, which is distinctly kept from +the rest of the files in the archive that should be published.

+

Once this archive has been uploaded, InDefero reads in the meta information, unpacks the other files from +the archive and creates new individual downloads for each of them.

{/blocktrans} + +{aurl 'url', 'IDF_Views::faqArchiveFormat'} +

{blocktrans}Learn more about the archive format.{/blocktrans}

+ +

{trans 'What is the API and how is it used?'}

+ +

{blocktrans}The API (Application Programming Interface) is used to interact with InDefero with another program. For example, this can be used to create a desktop program to submit new tickets easily.{/blocktrans}

+{aurl 'url', 'IDF_Views::faqApi'} +

{blocktrans}Learn more about the API.{/blocktrans}

+ +{/block} +{block context} +

{trans 'Here we are, just to help you.'}

+

{trans 'Projects'}

+
    {foreach $projects as $p} +
  • {$p}
  • +{/foreach}
+{/block} diff --git a/indefero/src/IDF/templates/idf/gadmin/base.html b/indefero/src/IDF/templates/idf/gadmin/base.html new file mode 100644 index 0000000..641b34f --- /dev/null +++ b/indefero/src/IDF/templates/idf/gadmin/base.html @@ -0,0 +1,69 @@ + +{* +# ***** BEGIN LICENSE BLOCK ***** +# This file is part of InDefero, an open source project management application. +# Copyright (C) 2008-2011 Céondo Ltd and contributors. +# +# InDefero is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# InDefero is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# ***** END LICENSE BLOCK ***** +*} + + + + + + {block extraheader}{/block} + {block pagetitle}{$page_title|strip_tags}{/block} + + {appversion} + + +
+
+ {include 'idf/main-menu.html'} + +

{block title}{$page_title}{/block}

+
+
+
+
+
+ {if $user and $user.id}{getmsgs $user}{/if} +
{block body}{/block}
+
+
+
+
{block context}{/block}
+
+
{block foot}{/block}
+
+{include 'idf/js-hotkeys.html'} +{block javascript}{/block} + + diff --git a/indefero/src/IDF/templates/idf/gadmin/forge/base.html b/indefero/src/IDF/templates/idf/gadmin/forge/base.html new file mode 100644 index 0000000..0094dca --- /dev/null +++ b/indefero/src/IDF/templates/idf/gadmin/forge/base.html @@ -0,0 +1,5 @@ +{extends "idf/gadmin/base.html"} +{block tabforge} class="active"{/block} +{block subtabs} +{trans 'Frontpage'} +{/block} diff --git a/indefero/src/IDF/templates/idf/gadmin/forge/index.html b/indefero/src/IDF/templates/idf/gadmin/forge/index.html new file mode 100644 index 0000000..fb6feda --- /dev/null +++ b/indefero/src/IDF/templates/idf/gadmin/forge/index.html @@ -0,0 +1,65 @@ +{extends "idf/gadmin/forge/base.html"} + +{block docclass}yui-t3{assign $inIndex=true}{/block} + +{block body} +
+ ++ + + + + + + + + + + + +
{$form.f.enabled|unsafe} +{$form.f.enabled.labelTag} +{if $form.f.enabled.errors}{$form.f.enabled.fieldErrors}{/if} +
+{if $form.f.content.errors}{$form.f.content.fieldErrors}{/if} +{$form.f.content|unsafe} +
+ +
+
+ +{/block} + +{block context} +{assign $eurl = 'http://michelf.com/projects/php-markdown/extra/'} +{assign $burl = 'http://daringfireball.net/projects/markdown/syntax'} +
+{blocktrans} +

Instructions:

+

You can set up a custom forge page that is used as entry page for the forge instead of the plain project listing. This page is then also accessible via the 'Home' link in main menu bar.

+

The content of the page can use the Markdown syntax with the Extra extension.

+

Additionally, the following macros are available:
+

    +
  • {projectlist, label=..., order=(name|activity), limit=...} - Renders a project list that can optionally be filtered by label, ordered by 'name' or 'activity' and / or limited to a specific number of projects.
  • +
+

+{/blocktrans} +
+{/block} + + diff --git a/indefero/src/IDF/templates/idf/gadmin/projects/base.html b/indefero/src/IDF/templates/idf/gadmin/projects/base.html new file mode 100644 index 0000000..4910ae6 --- /dev/null +++ b/indefero/src/IDF/templates/idf/gadmin/projects/base.html @@ -0,0 +1,7 @@ +{extends "idf/gadmin/base.html"} +{block tabprojects} class="active"{/block} +{block subtabs} +{trans 'Project List'} | +{trans 'Project Labels'} | +{trans 'Create Project'} {if $project} | {trans 'Change Project Details'}{/if} +{/block} diff --git a/indefero/src/IDF/templates/idf/gadmin/projects/create.html b/indefero/src/IDF/templates/idf/gadmin/projects/create.html new file mode 100644 index 0000000..fb9c85a --- /dev/null +++ b/indefero/src/IDF/templates/idf/gadmin/projects/create.html @@ -0,0 +1,186 @@ +{extends "idf/gadmin/projects/base.html"} + +{block docclass}yui-t3{assign $inCreate=true}{/block} + +{block body} +{if $form.errors} +
+

{trans 'The form contains some errors. Please correct them to create the project.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +
+{/if} +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{$form.f.name.labelTag}: +{if $form.f.name.errors}{$form.f.name.fieldErrors}{/if} +{$form.f.name|unsafe} +
{$form.f.shortname.labelTag}: +{if $form.f.shortname.errors}{$form.f.shortname.fieldErrors}{/if} +{$base_url}{$form.f.shortname|unsafe}/
+{$form.f.shortname.help_text} +
{$form.f.shortdesc.labelTag}: +{if $form.f.shortdesc.errors}{$form.f.shortdesc.fieldErrors}{/if} +{$form.f.shortdesc|unsafe}
+{$form.f.shortdesc.help_text} +
{$form.f.external_project_url.labelTag}:{if $form.f.external_project_url.errors}{$form.f.external_project_url.fieldErrors}{/if} +{$form.f.external_project_url|unsafe} +
{$form.f.scm.labelTag}:{if $form.f.scm.errors}{$form.f.scm.fieldErrors}{/if} +{$form.f.scm|unsafe} +
{$form.f.svn_remote_url.labelTag}:{if $form.f.svn_remote_url.errors}{$form.f.svn_remote_url.fieldErrors}{/if} +{$form.f.svn_remote_url|unsafe} +
{$form.f.svn_username.labelTag}:{if $form.f.svn_username.errors}{$form.f.svn_username.fieldErrors}{/if} +{$form.f.svn_username|unsafe} +
{$form.f.svn_password.labelTag}:{if $form.f.svn_password.errors}{$form.f.svn_password.fieldErrors}{/if} +{$form.f.svn_password|unsafe} +
{$form.f.mtn_master_branch.labelTag}:{if $form.f.mtn_master_branch.errors}{$form.f.mtn_master_branch.fieldErrors}{/if} +{$form.f.mtn_master_branch|unsafe}
+{$form.f.mtn_master_branch.help_text} +
{$form.f.template.labelTag}{if $form.f.template.errors}{$form.f.template.fieldErrors}{/if} +{$form.f.template|unsafe}
+{$form.f.template.help_text} +
{$form.f.label1.labelTag}: +{if $form.f.label1.errors}{$form.f.label1.fieldErrors}{/if}{$form.f.label1|unsafe} +{if $form.f.label2.errors}{$form.f.label2.fieldErrors}{/if}{$form.f.label2|unsafe}
+{if $form.f.label3.errors}{$form.f.label3.fieldErrors}{/if}{$form.f.label3|unsafe} +{if $form.f.label4.errors}{$form.f.label4.fieldErrors}{/if}{$form.f.label4|unsafe}
+{if $form.f.label5.errors}{$form.f.label5.fieldErrors}{/if}{$form.f.label5|unsafe} +{if $form.f.label6.errors}{$form.f.label6.fieldErrors}{/if}{$form.f.label6|unsafe} +
{$form.f.owners.labelTag}: +{if $form.f.owners.errors}{$form.f.owners.fieldErrors}{/if} +{$form.f.owners|unsafe}
+{trans 'Provide at least one owner for the project or use a template.'} +
{$form.f.members.labelTag}: +{if $form.f.members.errors}{$form.f.members.fieldErrors}{/if} +{$form.f.members|unsafe} +
{if $form.f.private_project.errors}{$form.f.private_project.fieldErrors}{/if} +{$form.f.private_project|unsafe} +{$form.f.private_project.labelTag}
  + +
+
+{include 'idf/project/js-autocomplete.html'}{/block} +{/block} + +{block context} +
+

{trans 'Instructions:'}

+

{blocktrans}You can select the type of repository you want. In the case of subversion, you can use optionally a remote repository instead of the local one.{/blocktrans}

+

{blocktrans}Once you have defined the repository type, you cannot change it.{/blocktrans}

+
+
+{blocktrans} +

Specify each person by its login. Each person must have already registered with the given login.

+

Separate the logins with commas and/or new lines.

+{/blocktrans} +
+
+{blocktrans} +

Notes:

+

A project owner may make any change to this project, including removing other project owners. You need to be carefull when you give owner rights.

+

A project member will not have access to the administration area but will have more options available in the use of the project.

+{/blocktrans} +
+{/block} + +{block javascript}{literal} + +{/literal}{/block} diff --git a/indefero/src/IDF/templates/idf/gadmin/projects/delete.html b/indefero/src/IDF/templates/idf/gadmin/projects/delete.html new file mode 100644 index 0000000..39b177f --- /dev/null +++ b/indefero/src/IDF/templates/idf/gadmin/projects/delete.html @@ -0,0 +1,72 @@ +{extends "idf/gadmin/projects/base.html"} +{block body} +{if $form.errors} +
+

{trans 'The form contains some errors. Please correct them to delete the project.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +
+{/if} + +{trans 'Project Statistics'} + + + + + + + + + + + + + +
{trans 'Tab'}{trans 'Number'}
{trans 'Downloads'}{$stats['downloads']}
{trans 'Code reviews'}{$stats['reviews']}
{trans 'Commits'}{$stats['commits']}
{trans 'Issues'}{$stats['issues']}
{trans 'Documentation pages'}{$stats['docpages']}
+ +

{trans 'Delete Project'}

+ +
+ + + + + + + + + + + + + +
  +{blocktrans}Confirmation code to confirm the deletion of the project: +{$code}.{/blocktrans}
+
+{$form.f.code.labelTag}: +{if $form.f.code.errors}{$form.f.code.fieldErrors}{/if} +{$form.f.code|unsafe} +
  +{if $form.f.agree.errors}{$form.f.agree.fieldErrors}{/if} +{$form.f.agree|unsafe} {$form.f.agree.labelTag} +
  + +| {trans 'Cancel'}{if $stats['total'] > 200}
+{trans 'For large projects, the suppression can take a while, please be patient.'}{/if} +
+
+{/block} +{block context} +
+

{blocktrans} +Attention! Deleting a project is a one second operation +with the consequences that all the data related to the +project will be deleted. +{/blocktrans}

+
+{/block} + + + diff --git a/indefero/src/IDF/templates/idf/gadmin/projects/index.html b/indefero/src/IDF/templates/idf/gadmin/projects/index.html new file mode 100644 index 0000000..5c9179b --- /dev/null +++ b/indefero/src/IDF/templates/idf/gadmin/projects/index.html @@ -0,0 +1,23 @@ +{extends "idf/gadmin/projects/base.html"} + +{block docclass}yui-t3{assign $inIndex=true}{/block} + +{block body} +{$projects.render} +{/block} + +{block context} +
+

{trans 'Space Usage Statistics'}

+
    +
  • {trans 'Repositories:'} {$size['repositories']|size}
  • +
  • {trans 'Attachments:'} {$size['attachments']|size}
  • +
  • {trans 'Downloads:'} {$size['downloads']|size}
  • +
  • {trans 'Database:'} {$size['database']|size}
  • +
  • {trans 'Total Forge:'} {$size['total']|size}
  • +
+ +
+{/block} + + diff --git a/indefero/src/IDF/templates/idf/gadmin/projects/labels.html b/indefero/src/IDF/templates/idf/gadmin/projects/labels.html new file mode 100644 index 0000000..6b7c66e --- /dev/null +++ b/indefero/src/IDF/templates/idf/gadmin/projects/labels.html @@ -0,0 +1,31 @@ +{extends "idf/gadmin/projects/base.html"} + +{block docclass}yui-t3{assign $inLabels=true}{/block} + +{block body} +
+ + + + + + + +
{$form.f.project_labels.labelTag}:
+{if $form.f.project_labels.errors}{$form.f.project_labels.fieldErrors}{/if} +{$form.f.project_labels|unsafe} +
+ +
+
+{/block} + +{block context} +
+{blocktrans} +

Instructions:

+

List one status value per line in desired sort-order.

+

Optionally, use an equals-sign to document the meaning of each status value.

+{/blocktrans} +
+{/block} diff --git a/indefero/src/IDF/templates/idf/gadmin/projects/update.html b/indefero/src/IDF/templates/idf/gadmin/projects/update.html new file mode 100644 index 0000000..8479453 --- /dev/null +++ b/indefero/src/IDF/templates/idf/gadmin/projects/update.html @@ -0,0 +1,101 @@ +{extends "idf/gadmin/projects/base.html"} +{block body} +{if $form.errors} +
+

{trans 'The form contains some errors. Please correct them to update the project.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +
+{/if} +
+ + + + + + + + + + + + + +{if $project.getConf().getVal('scm') == 'mtn'} + + + + +{/if} + + + + + + + + + + + + + + + + +
{$form.f.name.labelTag}: +{if $form.f.name.errors}{$form.f.name.fieldErrors}{/if} +{$form.f.name|unsafe} +
{$form.f.shortdesc.labelTag}: +{if $form.f.shortdesc.errors}{$form.f.shortdesc.fieldErrors}{/if} +{$form.f.shortdesc|unsafe}
+{$form.f.shortdesc.help_text} +
{$form.f.external_project_url.labelTag}:{if $form.f.external_project_url.errors}{$form.f.external_project_url.fieldErrors}{/if} +{$form.f.external_project_url|unsafe} +
{$form.f.mtn_master_branch.labelTag}:{if $form.f.mtn_master_branch.errors}{$form.f.mtn_master_branch.fieldErrors}{/if} +{$form.f.mtn_master_branch|unsafe}
+{$form.f.mtn_master_branch.help_text} +
{$form.f.label1.labelTag}: +{if $form.f.label1.errors}{$form.f.label1.fieldErrors}{/if}{$form.f.label1|unsafe} +{if $form.f.label2.errors}{$form.f.label2.fieldErrors}{/if}{$form.f.label2|unsafe}
+{if $form.f.label3.errors}{$form.f.label3.fieldErrors}{/if}{$form.f.label3|unsafe} +{if $form.f.label4.errors}{$form.f.label4.fieldErrors}{/if}{$form.f.label4|unsafe}
+{if $form.f.label5.errors}{$form.f.label5.fieldErrors}{/if}{$form.f.label5|unsafe} +{if $form.f.label6.errors}{$form.f.label6.fieldErrors}{/if}{$form.f.label6|unsafe} +
{$form.f.owners.labelTag}: +{if $form.f.owners.errors}{$form.f.owners.fieldErrors}{/if} +{$form.f.owners|unsafe}
+{trans 'Provide at least one owner for the project.'} +
{$form.f.members.labelTag}: +{if $form.f.members.errors}{$form.f.members.fieldErrors}{/if} +{$form.f.members|unsafe} +
  {aurl 'url', 'IDF_Views_Admin::projectDelete', array($project.id)} +{* float left is a fix for Firefox < 3.5 *} + +| {trans 'Cancel'} {if $isAdmin} + {trans 'Trash'} {trans 'Delete this project'}
{trans 'You will be asked to confirm.'}
{/if} +
+
+{include 'idf/project/js-autocomplete.html'}{/block} +{/block} + +{block context} +
+{blocktrans} +

Instructions:

+

Specify each person by its login. Each person must have already registered with the given login.

+

Separate the logins with commas and/or new lines.

+{/blocktrans} +
+
+{blocktrans} +

Notes:

+

A project owner may make any change to this project, including removing other project owners. You need to be carefull when you give owner rights.

+

A project member will not have access to the administration area but will have more options available in the use of the project.

+{/blocktrans} +
+{/block} + + + diff --git a/indefero/src/IDF/templates/idf/gadmin/users/base.html b/indefero/src/IDF/templates/idf/gadmin/users/base.html new file mode 100644 index 0000000..93116a6 --- /dev/null +++ b/indefero/src/IDF/templates/idf/gadmin/users/base.html @@ -0,0 +1,10 @@ +{extends "idf/gadmin/base.html"} +{block tabusers} class="active"{/block} +{block subtabs} +{trans 'User List'} +{if $inUpdate} | +{trans 'Update User'} +{/if} | +{trans 'Create User'} + +{/block} diff --git a/indefero/src/IDF/templates/idf/gadmin/users/create.html b/indefero/src/IDF/templates/idf/gadmin/users/create.html new file mode 100644 index 0000000..16a00de --- /dev/null +++ b/indefero/src/IDF/templates/idf/gadmin/users/create.html @@ -0,0 +1,68 @@ +{extends "idf/gadmin/users/base.html"} +{block docclass}yui-t1{assign $inCreate=true}{/block} +{block body} +{if $form.errors} +
+

{trans 'The form contains some errors. Please correct them to create the user.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +
+{/if} +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{$form.f.login.labelTag}:{if $form.f.login.errors}{$form.f.login.fieldErrors}{/if} +{$form.f.login|unsafe} +
{$form.f.first_name.labelTag}:{if $form.f.first_name.errors}{$form.f.first_name.fieldErrors}{/if} +{$form.f.first_name|unsafe} +
{$form.f.last_name.labelTag}:{if $form.f.last_name.errors}{$form.f.last_name.fieldErrors}{/if} +{$form.f.last_name|unsafe} +
{$form.f.email.labelTag}:{if $form.f.email.errors}{$form.f.email.fieldErrors}{/if} +{$form.f.email|unsafe}
+{$form.f.email.help_text} +
{$form.f.language.labelTag}:{if $form.f.language.errors}{$form.f.language.fieldErrors}{/if} +{$form.f.language|unsafe} +
{$form.f.public_key.labelTag}:{if $form.f.public_key.errors}{$form.f.public_key.fieldErrors}{/if} +{$form.f.public_key|unsafe}
+{$form.f.public_key.help_text} +
  | {trans 'Cancel'} +
+
+{/block} +{block context} +
+

{trans 'The user password will be sent by email to the user.'}

+
{/block} + +{block javascript}{/block} + diff --git a/indefero/src/IDF/templates/idf/gadmin/users/createuser-email.txt b/indefero/src/IDF/templates/idf/gadmin/users/createuser-email.txt new file mode 100644 index 0000000..9b08e75 --- /dev/null +++ b/indefero/src/IDF/templates/idf/gadmin/users/createuser-email.txt @@ -0,0 +1,16 @@ +{blocktrans}Hello {$user}, + +An account on the forge has been created for you by +the administrator {$admin}. + +Please find here your details to access the forge: + + Address: {$url} + Login: {$user.login} + Password: {$password} + +Yours faithfully, +The development team. +{/blocktrans} + + diff --git a/indefero/src/IDF/templates/idf/gadmin/users/index.html b/indefero/src/IDF/templates/idf/gadmin/users/index.html new file mode 100644 index 0000000..6ff8912 --- /dev/null +++ b/indefero/src/IDF/templates/idf/gadmin/users/index.html @@ -0,0 +1,16 @@ +{extends "idf/gadmin/users/base.html"} + +{block docclass}yui-t2{assign $inIndex=true}{/block} + +{block body} +{$users.render} +{/block} +{block context} +

{trans 'Number of users:'} {$users.nb_items}

+{if !$not_validated}{aurl 'url', 'IDF_Views_Admin::usersNotValidated'} +

{blocktrans}See not validated users.{/blocktrans}

+{/if} +
+{blocktrans}

You have here an overview of the users registered in the forge.

{/blocktrans} +
+{/block} diff --git a/indefero/src/IDF/templates/idf/gadmin/users/update.html b/indefero/src/IDF/templates/idf/gadmin/users/update.html new file mode 100644 index 0000000..d4a081d --- /dev/null +++ b/indefero/src/IDF/templates/idf/gadmin/users/update.html @@ -0,0 +1,134 @@ +{extends "idf/gadmin/users/base.html"} +{block docclass}yui-t1{assign $inUpdate=true}{/block} +{block body} +{if $form.errors} +
+

{trans 'The form contains some errors. Please correct them to update the user.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +
+{/if} +
+ + +{aurl 'url', 'IDF_Views_User::view', array($cuser.login)} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{if $user.administrator} + + + + +{/if} + + + + + + + + +
{trans 'Login:'}{$cuser.login}
{$form.f.first_name.labelTag}:{if $form.f.first_name.errors}{$form.f.first_name.fieldErrors}{/if} +{$form.f.first_name|unsafe} +
{$form.f.last_name.labelTag}:{if $form.f.last_name.errors}{$form.f.last_name.fieldErrors}{/if} +{$form.f.last_name|unsafe} +
{$form.f.email.labelTag}:{if $form.f.email.errors}{$form.f.email.fieldErrors}{/if} +{$form.f.email|unsafe} +
{$form.f.language.labelTag}:{if $form.f.language.errors}{$form.f.language.fieldErrors}{/if} +{$form.f.language|unsafe} +
{$form.f.password.labelTag}:{if $form.f.password.errors}{$form.f.password.fieldErrors}{/if} +{$form.f.password|unsafe}
+{$form.f.password.help_text} +
{$form.f.password2.labelTag}:{if $form.f.password2.errors}{$form.f.password2.fieldErrors}{/if} +{$form.f.password2|unsafe} +
{trans "Public Profile"}
{$form.f.description.labelTag}:{if $form.f.description.errors}{$form.f.description.fieldErrors}{/if} +{$form.f.description|unsafe} +
{$form.f.twitter.labelTag}:{if $form.f.twitter.errors}{$form.f.twitter.fieldErrors}{/if} +{$form.f.twitter|unsafe} +
{$form.f.public_email.labelTag}:{if $form.f.public_email.errors}{$form.f.public_email.fieldErrors}{/if} +{$form.f.public_email|unsafe} +
{$form.f.website.labelTag}:{if $form.f.website.errors}{$form.f.website.fieldErrors}{/if} +{$form.f.website|unsafe} +
{$form.f.custom_avatar.labelTag}:{if $form.f.custom_avatar.errors}{$form.f.custom_avatar.fieldErrors}{/if} +{$form.f.custom_avatar|unsafe}
+{$form.f.custom_avatar.help_text} +
{if $form.f.remove_custom_avatar.errors}{$form.f.remove_custom_avatar.fieldErrors}{/if} +{$form.f.remove_custom_avatar|unsafe} +{$form.f.remove_custom_avatar.labelTag}
+{$form.f.remove_custom_avatar.help_text}
{trans "Administrative"}
{if $form.f.staff.errors}{$form.f.staff.fieldErrors}{/if} +{$form.f.staff|unsafe} +{$form.f.staff.labelTag}
+{$form.f.staff.help_text}
{if $form.f.active.errors}{$form.f.active.fieldErrors}{/if} +{$form.f.active|unsafe} +{$form.f.active.labelTag}
+{$form.f.active.help_text}
  + +| {trans 'Cancel'} +
+
+{/block} +{block context} +
+

{trans 'Instructions:'}

+

{blocktrans}If you are changing the email address of the user, you +need to ensure that you are providing a valid email +address{/blocktrans}

+{if $user.administrator} +

{blocktrans}If you give the user staff rights, the user will be +able to create new projects and update other non staff users. +{/blocktrans}

{/if} +
+{/block} + + + diff --git a/indefero/src/IDF/templates/idf/gadmin/usher/base.html b/indefero/src/IDF/templates/idf/gadmin/usher/base.html new file mode 100644 index 0000000..8f8a8c5 --- /dev/null +++ b/indefero/src/IDF/templates/idf/gadmin/usher/base.html @@ -0,0 +1,6 @@ +{extends "idf/gadmin/base.html"} +{block tabusher} class="active"{/block} +{block subtabs} +{trans 'Configured servers'} | +{trans 'Usher control'} +{/block} diff --git a/indefero/src/IDF/templates/idf/gadmin/usher/connections.html b/indefero/src/IDF/templates/idf/gadmin/usher/connections.html new file mode 100644 index 0000000..8af6f60 --- /dev/null +++ b/indefero/src/IDF/templates/idf/gadmin/usher/connections.html @@ -0,0 +1,25 @@ +{extends "idf/gadmin/usher/base.html"} + +{block docclass}yui-t3{assign $inUsherServerConnections=true}{/block} + +{block body} + + + + + +{if count($connections) == 0} + + + +{else} +{foreach $connections as $connection} + + + + +{/foreach} +{/if} +
{trans "address"}{trans "port"}
{trans 'No connections found.'}
{$connection.address}{$connection.port}
+{/block} + diff --git a/indefero/src/IDF/templates/idf/gadmin/usher/control.html b/indefero/src/IDF/templates/idf/gadmin/usher/control.html new file mode 100644 index 0000000..e7d6802 --- /dev/null +++ b/indefero/src/IDF/templates/idf/gadmin/usher/control.html @@ -0,0 +1,32 @@ +{extends "idf/gadmin/usher/base.html"} + +{block docclass}yui-t3{assign $inUsherControl=true}{/block} + +{block body} +

+{trans 'current server status:'} {$status} | +{if $status == "SHUTDOWN"} + {trans 'startup'} +{else} + {trans 'shutdown'} +{/if} +

+ +

{trans 'reload server configuration:'} + {trans 'reload'} +

+{/block} + +{block context} +
+

{trans 'Status explanation'}

+
    +
  • ACTIVE n: {trans 'active with n total open connections'}
  • +
  • WAITING: {trans 'waiting for new connections'}
  • +
  • SHUTTINGDOWN: {trans 'usher is being shut down, not accepting connections'}
  • +
  • SHUTDOWN: {trans 'usher is shut down, all local servers are stopped and not accepting connections'}
  • +
+ +
+{/block} + diff --git a/indefero/src/IDF/templates/idf/gadmin/usher/index.html b/indefero/src/IDF/templates/idf/gadmin/usher/index.html new file mode 100644 index 0000000..9232765 --- /dev/null +++ b/indefero/src/IDF/templates/idf/gadmin/usher/index.html @@ -0,0 +1,58 @@ +{extends "idf/gadmin/usher/base.html"} + +{block docclass}yui-t3{assign $inUsher=true}{/block} + +{block body} + + + + + + +{if count($servers) == 0} + + + +{else} +{foreach $servers as $server} + + + + +{/foreach} +{/if} +
{trans "server name"}{trans "status"}{trans "action"}
{trans 'No monotone servers configured.'}
{$server.name}{$server.status} + {if preg_match("/ACTIVE|WAITING|RUNNING|SLEEPING/", $server.status)} + + {trans 'stop'} + {elseif $server.status == "STOPPED"} + + {trans 'start'} + {/if} + {if preg_match("/ACTIVE|WAITING|SLEEPING|STOPPING/", $server.status)} + | + {trans 'kill'} + {/if} + {if preg_match("/STOPPING|ACTIVE/", $server.status)} + | + {trans 'active connections'} + {/if} +
+{/block} + +{block context} +
+

{trans 'Status explanation'}

+
    +
  • REMOTE: {trans 'remote server without open connections'}
  • +
  • ACTIVE n: {trans 'server with n open connections'}
  • +
  • WAITING: {trans 'local server running, without open connections'}
  • +
  • SLEEPING: {trans 'local server not running, waiting for connections'}
  • +
  • STOPPING n: {trans 'local server is about to stop, n connections still open'}
  • +
  • STOPPED: {trans 'local server not running, not accepting connections'}
  • +
  • SHUTDOWN: {trans 'usher is shut down, not running and not accepting connections'}
  • +
+ +
+{/block} + diff --git a/indefero/src/IDF/templates/idf/index.atom b/indefero/src/IDF/templates/idf/index.atom new file mode 100644 index 0000000..d48b03b --- /dev/null +++ b/indefero/src/IDF/templates/idf/index.atom @@ -0,0 +1,9 @@ + + {$title}, {$project} - {$project.shortdesc} +{if !$user.isAnonymous()} {blocktrans}Personal project feed for {$user}.{/blocktrans}{/if} + + + {$feedurl} + {$date} +{$body} + diff --git a/indefero/src/IDF/templates/idf/index.html b/indefero/src/IDF/templates/idf/index.html new file mode 100644 index 0000000..0fcd7ba --- /dev/null +++ b/indefero/src/IDF/templates/idf/index.html @@ -0,0 +1,18 @@ +{extends "idf/base-simple.html"} +{block docclass}yui-t7{/block} +{block tabhome} class="active"{/block} +{block subtabs} +{trans 'Home'} | +{trans 'Projects'} +{/block} +{block body} +
+{markdown_forge $content, $request} +
+{/block} + +{block context}{/block} + +{block foot}
Powered by InDefero, +
a Céondo Ltd initiative.
+ srchub.org is ran by
Nathan Adams.
{/block} diff --git a/indefero/src/IDF/templates/idf/issues/attachment.html b/indefero/src/IDF/templates/idf/issues/attachment.html new file mode 100644 index 0000000..4bfdade --- /dev/null +++ b/indefero/src/IDF/templates/idf/issues/attachment.html @@ -0,0 +1,26 @@ +{extends "idf/issues/base.html"} +{block extraheader}{/block} +{block docclass}yui-t2{assign $inIssue=true}{/block} +{block body} + + +{$file} + +
+{aurl 'url', 'IDF_Views_Issue::getAttachment', array($project.shortname, $attachment.id, $attachment.filename)} +

{trans 'Archive'} {trans 'Download this file'}

+ +{/block} +{block context} +{aurl 'url', 'IDF_Views_Issue::view', array($project.shortname, $issue.id)} +{assign $url = $url~'#ic'~$comment.id} +

{blocktrans}Attachment to issue {$issue.id}{/blocktrans}

+{ashowuser 'submitter', $attachment.get_submitter(), $request} +

{trans 'Created:'} {$attachment.creation_dtime|dateago} {blocktrans}by {$submitter}{/blocktrans}

+ +{/block} + +{block javascript} + + +{/block} diff --git a/indefero/src/IDF/templates/idf/issues/base.html b/indefero/src/IDF/templates/idf/issues/base.html new file mode 100644 index 0000000..7b839c8 --- /dev/null +++ b/indefero/src/IDF/templates/idf/issues/base.html @@ -0,0 +1,22 @@ +{extends "idf/base.html"} +{block tabissues} class="active"{/block} +{block subtabs} +
+ {trans 'Summary'} +| {trans 'All Issues'} +{if !$user.isAnonymous()} +| {trans 'My Issues'} +| {trans 'My watch list'} +| {trans 'New Issue'} +{/if} +|
+ + +
+{if $inIssue} | +{aurl 'url', 'IDF_Views_Issue::view', array($project.shortname, $issue.id)} +{trans 'Back to the issue'} +{/if} +{superblock} +
+{/block} diff --git a/indefero/src/IDF/templates/idf/issues/by-label.html b/indefero/src/IDF/templates/idf/issues/by-label.html new file mode 100644 index 0000000..25e6625 --- /dev/null +++ b/indefero/src/IDF/templates/idf/issues/by-label.html @@ -0,0 +1,22 @@ +{extends "idf/issues/base.html"} +{block docclass}yui-t1{assign $inAllIssues=true}{/block} +{block body} +{$issues.render} +{if !$user.isAnonymous()} +{aurl 'url', 'IDF_Views_Issue::create', array($project.shortname)} +

+ {trans 'New Issue'}

{/if} + +{/block} +{block context} +{aurl 'open_url', 'IDF_Views_Issue::listLabel', array($project.shortname, $label.id, 'open')} +{aurl 'closed_url', 'IDF_Views_Issue::listLabel', array($project.shortname, $label.id, 'closed')} +{blocktrans}

Open issues: {$open}

+

Closed issues: {$closed}

+{/blocktrans} +

{trans 'Label:'} +{aurl 'url', 'IDF_Views_Issue::listLabel', array($project.shortname, $label.id, 'open')} +{$label.class}:{$label.name}

+{if $completion} +

{trans 'Completion:'} {$completion}

+{/if} +{/block} diff --git a/indefero/src/IDF/templates/idf/issues/create.html b/indefero/src/IDF/templates/idf/issues/create.html new file mode 100644 index 0000000..9d681a7 --- /dev/null +++ b/indefero/src/IDF/templates/idf/issues/create.html @@ -0,0 +1,145 @@ +{extends "idf/issues/base.html"} +{block docclass}yui-t3{assign $inCreate = true}{/block} +{block body} +{if $form.errors} +
+

{trans 'The form contains some errors. Please correct them to submit the issue.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +
+{/if} + +{if $preview} +

{trans 'Preview'}

+
+
{issuetext $preview, $request}
+
+
+{/if} + +
+ + + + + + + + + + + + + + + + + + + + +{if $isOwner or $isMember} + + + + + + + + + + + + + + + +{/if} + + + + +
{$form.f.summary.labelTag}:{if $form.f.summary.errors}{$form.f.summary.fieldErrors}{/if} +{$form.f.summary|unsafe} +
{$form.f.content.labelTag}:{if $form.f.content.errors}{$form.f.content.fieldErrors}{/if} +{$form.f.content|unsafe} +
{$form.f.attachment1.labelTag}:{if $form.f.attachment1.errors}{$form.f.attachment1.fieldErrors}{/if} +{$form.f.attachment1|unsafe} +
{$form.f.attachment2.labelTag}:{if $form.f.attachment2.errors}{$form.f.attachment2.fieldErrors}{/if} +{$form.f.attachment2|unsafe} +
{$form.f.attachment3.labelTag}:{if $form.f.attachment3.errors}{$form.f.attachment3.fieldErrors}{/if} +{$form.f.attachment3|unsafe} +
{$form.f.status.labelTag}:{if $form.f.status.errors}{$form.f.status.fieldErrors}{/if} +{$form.f.status|unsafe} +
{$form.f.owner.labelTag}:{if $form.f.owner.errors}{$form.f.owner.fieldErrors}{/if} +{$form.f.owner|unsafe} +
{$form.f.relation_type0.labelTag}: +{if $form.f.relation_type0.errors}{$form.f.relation_type0.fieldErrors}{/if} +{if $form.f.relation_issue0.errors}{$form.f.relation_issue0.fieldErrors}{/if} +{$form.f.relation_type0|unsafe} +{$form.f.relation_issue0|unsafe} +
{$form.f.label1.labelTag}: +{if $form.f.label1.errors}{$form.f.label1.fieldErrors}{/if}{$form.f.label1|unsafe} +{if $form.f.label2.errors}{$form.f.label2.fieldErrors}{/if}{$form.f.label2|unsafe} +{if $form.f.label3.errors}{$form.f.label3.fieldErrors}{/if}{$form.f.label3|unsafe}
+{if $form.f.label4.errors}{$form.f.label4.fieldErrors}{/if}{$form.f.label4|unsafe} +{if $form.f.label5.errors}{$form.f.label5.fieldErrors}{/if}{$form.f.label5|unsafe} +{if $form.f.label6.errors}{$form.f.label6.fieldErrors}{/if}{$form.f.label6|unsafe} +
  + + | +{trans 'Cancel'} +
+
+{/block} +{block context} +
+{blocktrans}

When you submit the issue do not forget to provide the following information:

+
    +
  • The steps to reproduce the problem.
  • +
  • The version of the software and your operating system.
  • +
  • Any information that can help the developers to solve the issue.
  • +
  • Do not provide any password or confidential information!
  • +
{/blocktrans} +
+{/block} +{block javascript} + +{/literal} +{include 'idf/issues/js-autocomplete.html'}{/block} + diff --git a/indefero/src/IDF/templates/idf/issues/feedfragment.xml b/indefero/src/IDF/templates/idf/issues/feedfragment.xml new file mode 100644 index 0000000..b44b946 --- /dev/null +++ b/indefero/src/IDF/templates/idf/issues/feedfragment.xml @@ -0,0 +1,31 @@ + + {$title} - {$issue.get_status} + + {$url} + {$date} + {$author} +
+
{issuetext $c.content, $request}
+{assign $attachments = $c.get_attachment_list()} +{if $attachments.count() > 0} +
+
    +{foreach $attachments as $a}
  • {$a.filename} - {$a.filesize|ssize}
  • {/foreach} +
{/if} +{if $c.changes} +{foreach $c.changes as $w => $v} +{if $w == 'su'}{trans 'Summary:'}{/if}{if $w == 'st'}{trans 'Status:'}{/if}{if $w == 'ow'}{trans 'Owner:'}{/if}{if $w == 'lb'}{trans 'Labels:'}{/if}{if $w == 'rel'}{trans 'Relations:'}{/if} +{if $w == 'lb' or $w == 'rel'} + {foreach $v as $t => $ls} + {foreach $ls as $l} + {if $t == 'rem'}{/if}{$l}{if $t == 'rem'}{/if} + {/foreach} + {/foreach} +{else} + {$v} +{/if}
+{/foreach} +{/if} +
+
+ diff --git a/indefero/src/IDF/templates/idf/issues/forge-watchlist.html b/indefero/src/IDF/templates/idf/issues/forge-watchlist.html new file mode 100644 index 0000000..b6d2884 --- /dev/null +++ b/indefero/src/IDF/templates/idf/issues/forge-watchlist.html @@ -0,0 +1,12 @@ +{extends "idf/base-simple.html"} + +{block body} +{$issues.render} +{/block} + +{block context} +{aurl 'open_url', 'IDF_Views_Issue::forgeWatchList', array('open')} +{aurl 'closed_url', 'IDF_Views_Issue::forgeWatchList', array('closed')} +{blocktrans}

Open issues: {$open}

+

Closed issues: {$closed}

{/blocktrans} +{/block} diff --git a/indefero/src/IDF/templates/idf/issues/index.html b/indefero/src/IDF/templates/idf/issues/index.html new file mode 100644 index 0000000..526d7ec --- /dev/null +++ b/indefero/src/IDF/templates/idf/issues/index.html @@ -0,0 +1,17 @@ +{extends "idf/issues/base.html"} +{block docclass}yui-t2{assign $inAllIssues=true}{/block} +{block body} +{$issues.render} +{if !$user.isAnonymous()} +{aurl 'url', 'IDF_Views_Issue::create', array($project.shortname)} +

+ {trans 'New Issue'}

{/if} + +{/block} +{block context} +{aurl 'open_url', 'IDF_Views_Issue::index', array($project.shortname)} +{aurl 'closed_url', 'IDF_Views_Issue::listStatus', array($project.shortname, 'closed')} +{blocktrans}

Open issues: {$open}

+

Closed issues: {$closed}

{/blocktrans} +{assign $cloud_url = 'IDF_Views_Issue::listLabel'} +{include 'idf/tags-cloud.html'} +{/block} diff --git a/indefero/src/IDF/templates/idf/issues/issue-created-email.txt b/indefero/src/IDF/templates/idf/issues/issue-created-email.txt new file mode 100644 index 0000000..df31528 --- /dev/null +++ b/indefero/src/IDF/templates/idf/issues/issue-created-email.txt @@ -0,0 +1,21 @@ +{trans 'Hello,'} + +{if $owns_issue}{blocktrans}A new issue has been created and assigned to you:{/blocktrans}{else}{blocktrans}A new issue has been created:{/blocktrans}{/if} + +{$issue.id} - {$issue.summary|safe} +{trans 'Project:'} {$project.name|safe} +{trans 'Status:'} {$issue.get_status.name|safe} +{trans 'Reported by:'} {$issue.get_submitter|safe} +{assign $tags = $issue.get_tags_list()}{if $tags.count()}{trans 'Labels:'} +{foreach $tags as $tag} {$tag.class|safe}:{$tag.name|safe} +{/foreach}{/if} +{trans 'Description:'} + +{$comment.content|safe}{assign $attachments = $comment.get_attachment_list()} +{if $attachments.count() > 0} +{trans 'Attachments:'}{foreach $attachments as $a} +- {$a.filename|safe} - {$a.filesize|ssize} + {$url_base}{url 'IDF_Views_Issue::viewAttachment', array($project.shortname, $a.id, $a.filename)}{/foreach} +{/if} +-- +{trans 'Issue:'} {$url_base}{url 'IDF_Views_Issue::view', array($project.shortname, $issue.id)} diff --git a/indefero/src/IDF/templates/idf/issues/issue-updated-email.txt b/indefero/src/IDF/templates/idf/issues/issue-updated-email.txt new file mode 100644 index 0000000..0e01534 --- /dev/null +++ b/indefero/src/IDF/templates/idf/issues/issue-updated-email.txt @@ -0,0 +1,29 @@ +{trans 'Hello,'} + +{if $owns_issue}{blocktrans}The following issue you are owning has been updated:{/blocktrans}{else}{blocktrans}The following issue has been updated:{/blocktrans}{/if} + +{$issue.id} - {$issue.summary|safe} +{trans 'Project:'} {$project.name|safe} +{trans 'Status:'} {$issue.get_status.name} +{trans 'Reported by:'} {$issue.get_submitter|safe} +{trans 'URL:'} {$url_base}{url 'IDF_Views_Issue::view', array($project.shortname, $issue.id)} +{assign $tags = $issue.get_tags_list()}{if $tags.count()}{trans 'Labels:'} +{foreach $tags as $tag} {$tag.class|safe}:{$tag.name|safe} +{/foreach} +{/if}{trans 'Comments (last first):'} + +{foreach $comments as $c}{assign $who = $c.get_submitter()}# {blocktrans}By {$who|safe}, {$c.creation_dtime|date}:{/blocktrans} + +{if strlen($c.content) > 0}{$c.content|safe}{/if}{if $c.changedIssue()} +{foreach $c.changes as $w => $v} + {if $w == 'su'}{trans 'Summary:'}{/if}{if $w == 'st'}{trans 'Status:'}{/if}{if $w == 'ow'}{trans 'Owner:'}{/if}{if $w == 'lb'}{trans 'Labels:'}{/if}{if $w == 'rel'}{trans 'Relations:'}{/if} {if $w == 'lb' or $w == 'rel'}{foreach $v as $t => $ls}{foreach $ls as $l}{if $t == 'rem'}-{/if}{$l} {/foreach}{/foreach}{else}{$v}{/if}{/foreach}{/if}{assign $attachments = $c.get_attachment_list()}{if $attachments.count() > 0} + +{trans 'Attachments:'}{foreach $attachments as $a} +- {$a.filename|safe} - {$a.filesize|ssize} + {$url_base}{url 'IDF_Views_Issue::viewAttachment', array($project.shortname, $a.id, $a.filename)}{/foreach} +{/if} + +{/foreach} + +-- +{trans 'Issue:'} {$url_base}{url 'IDF_Views_Issue::view', array($project.shortname, $issue.id)} diff --git a/indefero/src/IDF/templates/idf/issues/js-autocomplete.html b/indefero/src/IDF/templates/idf/issues/js-autocomplete.html new file mode 100644 index 0000000..24a0675 --- /dev/null +++ b/indefero/src/IDF/templates/idf/issues/js-autocomplete.html @@ -0,0 +1,96 @@ +{if $isOwner or $isMember} + + + +{/if} diff --git a/indefero/src/IDF/templates/idf/issues/project-watchlist.html b/indefero/src/IDF/templates/idf/issues/project-watchlist.html new file mode 100644 index 0000000..ecc9241 --- /dev/null +++ b/indefero/src/IDF/templates/idf/issues/project-watchlist.html @@ -0,0 +1,17 @@ +{extends "idf/issues/base.html"} + +{block docclass}yui-t2{assign $inWatchList = true}{/block} + +{block body} +{$issues.render} +{if !$user.isAnonymous()} +{aurl 'url', 'IDF_Views_Issue::create', array($project.shortname)} +

+ {trans 'New Issue'}

{/if} +{/block} + +{block context} +{aurl 'open_url', 'IDF_Views_Issue::watchList', array($project.shortname, 'open')} +{aurl 'closed_url', 'IDF_Views_Issue::watchList', array($project.shortname, 'closed')} +{blocktrans}

Open issues: {$open}

+

Closed issues: {$closed}

{/blocktrans} +{/block} diff --git a/indefero/src/IDF/templates/idf/issues/search.html b/indefero/src/IDF/templates/idf/issues/search.html new file mode 100644 index 0000000..4ffce24 --- /dev/null +++ b/indefero/src/IDF/templates/idf/issues/search.html @@ -0,0 +1,32 @@ +{extends "idf/issues/base.html"} +{block docclass}yui-t2{/block} +{block body} +{$issues.render} +{if !$user.isAnonymous()} +{aurl 'url', 'IDF_Views_Issue::create', array($project.shortname)} +

+ {trans 'New Issue'}

{/if} + +{/block} +{block context} +{aurl 'open_url', 'IDF_Views_Issue::searchStatus', array($project.shortname, 'open'), array('q' => $query)} +{aurl 'closed_url', 'IDF_Views_Issue::searchStatus', array($project.shortname, 'closed'), array('q' => $query)} +{if $tag != null} +{aurl 'open_url', 'IDF_Views_Issue::searchLabel', array($project.shortname, $tag.id, 'open'), array('q' => $query)} +{aurl 'closed_url', 'IDF_Views_Issue::searchLabel', array($project.shortname, $tag.id, 'closed'), array('q' => $query)} +{/if} +{blocktrans} +

Found open issues: {$open}

+

Found closed issues: {$closed}

{/blocktrans} +{if $tag !== null} +{blocktrans}

Label: +{$tag.class}:{$tag.name}

{/blocktrans} +{else} +{* yes, this is duplicated from tags-cloud.html, but the code there cannot be easily overridden *} +
{foreach $all_tags as $class => $labels} +
{$class}
+{foreach $labels as $idx => $label} +{aurl 'url', 'IDF_Views_Issue::searchLabel', array($project.shortname, $label.id, $status), array('q'=> $query)} +
{$label.name}{if $idx != count($labels) - 1},{/if}
+{/foreach}{/foreach}
+{/if} +{/block} diff --git a/indefero/src/IDF/templates/idf/issues/summary.html b/indefero/src/IDF/templates/idf/issues/summary.html new file mode 100644 index 0000000..d0c35ec --- /dev/null +++ b/indefero/src/IDF/templates/idf/issues/summary.html @@ -0,0 +1,108 @@ +{extends "idf/issues/base.html"} + +{block docclass}yui-t2{assign $inSummaryIssues=true}{/block} + +{block context} +

+

{blocktrans}View all open issues.{/blocktrans}

+{if !$user.isAnonymous()} +

{blocktrans}Create an issue.{/blocktrans}

+{/if} +{/block} + +{block body} +{if $trackerEmpty} + {aurl 'create_url', 'IDF_Views_Issue::create', array($project.shortname)} +

{blocktrans}The issue tracker is empty.
Create your first issue.{/blocktrans}

+{else} +
+{foreach $tagStatistics as $key => $class} +
+

{blocktrans}Unresolved: By {$key}{/blocktrans}

+ + + {foreach $class as $key => $value} + + + + + + {/foreach} + +
{$key}{$value[0]} + + + + + + +
+
+
{$value[1]}%
+
+
+{/foreach} +
+ +
+{if $status} +
+

{blocktrans}Status Summary{/blocktrans}

+ + + {foreach $status as $key => $value} + + + + + + {/foreach} + +
{$key}{$value[0]} + + + + + + +
+
+
{$value[1]}%
+
+
+{/if} + +{if $ownerStatistics} +
+

{blocktrans}Unresolved: By Assignee{/blocktrans}

+ + + {foreach $ownerStatistics as $key => $value} + + + + + + {/foreach} + +
+ {if !empty($value[2])} + {aurl 'url', 'IDF_Views_Issue::userIssues', array($project.shortname, $value[2], 'owner')} + {$key} + {else}{$key}{/if} + {$value[0]} + + + + + + +
+
+
{$value[1]}%
+
+
+{/if} +
+{/if} +{/block} diff --git a/indefero/src/IDF/templates/idf/issues/userIssues.html b/indefero/src/IDF/templates/idf/issues/userIssues.html new file mode 100644 index 0000000..018a642 --- /dev/null +++ b/indefero/src/IDF/templates/idf/issues/userIssues.html @@ -0,0 +1,20 @@ +{extends "idf/issues/base.html"} +{block docclass}yui-t2{if $user.login == $login}{assign $inMyIssues = true}{/if}{/block} +{block body} +{$issues.render} +{if !$user.isAnonymous()} +{aurl 'url', 'IDF_Views_Issue::create', array($project.shortname)} +

+ {trans 'New Issue'}

{/if} + +{/block} +{block context} +{aurl 'owner_url', 'IDF_Views_Issue::userIssues', array($project.shortname, $login, 'owner')} +{aurl 'submit_url', 'IDF_Views_Issue::userIssues', array($project.shortname, $login, 'submit')} +{aurl 'owner_closed_url', 'IDF_Views_Issue::userIssues', array($project.shortname, $login, 'ownerclosed')} +{aurl 'submit_closed_url', 'IDF_Views_Issue::userIssues', array($project.shortname, $login, 'submitclosed')} +

{trans 'Submitted issues:'} {$nb_submit} +{if $nb_submit_closed}
{blocktrans $nb_submit_closed}See the {$nb_submit_closed} closed.{plural}See the {$nb_submit_closed} closed.{/blocktrans}{/if}

+{if $nb_owner > 0} +

{trans 'Working issues:'} {$nb_owner} + {if $nb_owner_closed}
{blocktrans $nb_owner_closed}See the {$nb_owner_closed} closed.{plural}See the {$nb_owner_closed} closed.{/blocktrans}{/if}

{/if} +{/block} diff --git a/indefero/src/IDF/templates/idf/issues/view.html b/indefero/src/IDF/templates/idf/issues/view.html new file mode 100644 index 0000000..606437d --- /dev/null +++ b/indefero/src/IDF/templates/idf/issues/view.html @@ -0,0 +1,240 @@ +{extends "idf/issues/base.html"} +{block titleicon}{if $form}
{/if}{/block} +{block body} +
+{if $previous_issue_id} +Previous issue +{/if} +{if $previous_issue_id and $next_issue_id} - {/if} +{if $next_issue_id} +Next issue +{/if} +
+{assign $i = 0} +{assign $nc = $comments.count()} +{foreach $comments as $c}{ashowuser 'submitter', $c.get_submitter(), $request} +{assign $submitter = $c.get_submitter()} +{assign $submitter_data = $c.get_submitter_data()} +
+{if $submitter_data.avatar != ''} + +{else} + +{/if} +{if $i == 0} +

{blocktrans}Reported by {$submitter}, {$c.creation_dtime|date}{/blocktrans}

+{else} +{aurl 'url', 'IDF_Views_Issue::view', array($project.shortname, $issue.id)} +{assign $id = $c.id} +{assign $url = $url~'#ic'~$c.id} +

{blocktrans}Comment {$i} by {$submitter}, {$c.creation_dtime|date}{/blocktrans}

+{/if} + + +{if strlen($c.content) > 0}
{issuetext $c.content, $request}
{/if} +{assign $attachments = $c.get_attachment_list()} +{if $attachments.count() > 0} +
+{/if} +{if $i> 0 and $c.changedIssue()} +
+{foreach $c.changes as $w => $v} +{if $w == 'su'}{trans 'Summary:'}{/if}{if $w == 'st'}{trans 'Status:'}{/if}{if $w == 'ow'}{trans 'Owner:'}{/if}{if $w == 'lb'}{trans 'Labels:'}{/if}{if $w == 'rel'}{trans 'Relations:'}{/if} +{if $w == 'lb' or $w == 'rel'} + {foreach $v as $t => $ls} + {foreach $ls as $l} + {if $t == 'rem'}{/if}{$l}{if $t == 'rem'}{/if} + {/foreach} + {/foreach} +{else} + {$v} +{/if}
+{/foreach} +
+{/if} +
{assign $i = $i + 1}{if $i == $nc and false == $form} + +{/if} +{/foreach} + +{if $form} +
+ +{if $form.errors} +
+

{trans 'The form contains some errors. Please correct them to change the issue.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +
+{/if} + +{if $closed and (!$isOwner and !$isMember)} +

 {blocktrans}This issue is marked as closed, add a comment only if you think this issue is still valid and more work is needed to fully fix it.{/blocktrans}

+{/if} + +{if $preview} +

{trans 'Preview'}

+
+
{issuetext $preview, $request}
+
+
+{/if} + +
+ + + + + + + + + + + + + + + + +{if $isOwner or $isMember} + + + + + + + + + + + + + + + + + + + +{/if} + + + + +
{$form.f.content.labelTag}:{if $form.f.content.errors}{$form.f.content.fieldErrors}{/if} +{$form.f.content|unsafe} +
{$form.f.attachment1.labelTag}:{if $form.f.attachment1.errors}{$form.f.attachment1.fieldErrors}{/if} +{$form.f.attachment1|unsafe} +
{$form.f.attachment2.labelTag}:{if $form.f.attachment2.errors}{$form.f.attachment2.fieldErrors}{/if} +{$form.f.attachment2|unsafe} +
{$form.f.attachment3.labelTag}:{if $form.f.attachment3.errors}{$form.f.attachment3.fieldErrors}{/if} +{$form.f.attachment3|unsafe} +
{$form.f.summary.labelTag}:{if $form.f.summary.errors}{$form.f.summary.fieldErrors}{/if} +{$form.f.summary|unsafe} +
{$form.f.status.labelTag}:{if $form.f.status.errors}{$form.f.status.fieldErrors}{/if} +{$form.f.status|unsafe} +
{$form.f.owner.labelTag}:{if $form.f.owner.errors}{$form.f.owner.fieldErrors}{/if} +{$form.f.owner|unsafe} +
{$form.f.relation_type0.labelTag}: +{assign $prevField} +{foreach $form as $field} + {if strpos($field.name, 'relation_type') === 0} + {$field|unsafe} + {assign $prevField = $field} + {/if} + {if strpos($field.name, 'relation_issue') === 0} + {$field|unsafe}
+ {if $prevField.errors}{$prevField.fieldErrors}{/if} + {if $field.errors}{$field.fieldErrors}{/if} + {/if} +{/foreach} +
{$form.f.label1.labelTag}: +{if $form.f.label1.errors}{$form.f.label1.fieldErrors}{/if}{$form.f.label1|unsafe} +{if $form.f.label2.errors}{$form.f.label2.fieldErrors}{/if}{$form.f.label2|unsafe} +{if $form.f.label3.errors}{$form.f.label3.fieldErrors}{/if}{$form.f.label3|unsafe}
+{if $form.f.label4.errors}{$form.f.label4.fieldErrors}{/if}{$form.f.label4|unsafe} +{if $form.f.label5.errors}{$form.f.label5.fieldErrors}{/if}{$form.f.label5|unsafe} +{if $form.f.label6.errors}{$form.f.label6.fieldErrors}{/if}{$form.f.label6|unsafe} +
  + + | +{trans 'Cancel'} +
+
+{/if} +{/block} +{block context} +
+{ashowuser 'submitter', $issue.get_submitter(), $request} +

{trans 'Created:'} {$issue.creation_dtime|dateago} {blocktrans}by {$submitter}{/blocktrans}

+{if $issue.modif_dtime != $issue.creation_dtime}

+{trans 'Updated:'} {$issue.modif_dtime|dateago}

{/if} +

+{trans 'Status:'} {$issue.get_status.name}

+{if $issue.get_owner != null}

+{trans 'Owner:'} {showuser $issue.get_owner(), $request} +

{/if} +{if $interested > 0}

{trans 'Followed by:'} {blocktrans $interested}{$interested} person{plural}{$interested} persons{/blocktrans}

{/if} +{assign $tags = $issue.get_tags_list()}{if $tags.count()} +

+{trans 'Labels:'}
+{foreach $tags as $tag}{aurl 'url', 'IDF_Views_Issue::listLabel', array($project.shortname, $tag.id, 'open')} +{$tag.class}:{$tag.name}
+{/foreach} +

{/if} +{if count($related_issues) > 0} +{foreach $related_issues as $verb => $rel_issues} +

+{assign $verb = __($verb)} +{blocktrans}This issue {$verb}{/blocktrans}
+ {foreach $rel_issues as $rel_issue} + + + {$rel_issue.other_issue} - {$rel_issue.other_summary|shorten:30} + +
+ {/foreach} +

+{/foreach} +{/if} +
+{/block} +{block javascript}{if $form}{include 'idf/issues/js-autocomplete.html'} + +{/if}{/block} diff --git a/indefero/src/IDF/templates/idf/js-hotkeys.html b/indefero/src/IDF/templates/idf/js-hotkeys.html new file mode 100644 index 0000000..dc537a9 --- /dev/null +++ b/indefero/src/IDF/templates/idf/js-hotkeys.html @@ -0,0 +1,17 @@ + + + diff --git a/indefero/src/IDF/templates/idf/list-filter.html b/indefero/src/IDF/templates/idf/list-filter.html new file mode 100644 index 0000000..e788464 --- /dev/null +++ b/indefero/src/IDF/templates/idf/list-filter.html @@ -0,0 +1,59 @@ +{** + * Looks for input fields like + * + * and filters out anchors below $(target) which do not match + * the entered input. + *} + diff --git a/indefero/src/IDF/templates/idf/listProjects.html b/indefero/src/IDF/templates/idf/listProjects.html new file mode 100644 index 0000000..fcddffe --- /dev/null +++ b/indefero/src/IDF/templates/idf/listProjects.html @@ -0,0 +1,63 @@ +{extends "idf/base-simple.html"} +{block docclass}yui-t2{/block} +{block body} +{if $projects.count() == 0} +

{trans 'No projects managed with InDefero were found.'}

+{if $isAdmin} +{aurl 'url', 'IDF_Views_Admin::projectCreate'} +

+ {trans 'Create Project'}

{/if} +{else} +{include 'idf/project-list.html'} +{/if} +{/block} + +{block context} +{trans 'Filter projects by label'} +{if count($projectLabels) == 0} +

{trans 'No projects with labels found.'}

+{else} +
{foreach $projectLabels as $class => $labels} +
{$class}
+ {foreach $labels as $idx => $label} + {* 0.75 - or 75% - is the minimum font size we'd like to see in this tag cloud *} + {assign $fontScale = round($label.rel_project_count * 100) + 75} +
{$label.name}{if $idx != count($labels) - 1},{/if}
+ {/foreach} + {/foreach}
+ {if $tag} +

+ {blocktrans}Remove filter for {$tag}{/blocktrans}

+ {/if} +{/if} +
+ +{trans 'Order'} +{assign $labelPart = 'all'} +{if $tag}{assign $labelPart = $tag->id}{/if} +

+{if $order != 'name'}{/if} +{trans 'By name'}{if $order != 'name'}{/if} + – +{if $order != 'activity'}{/if} +{trans 'By activity'}{if $order != 'activity'}{/if} +

+
+ +{trans 'Filtered project stats'} +
+
{trans 'Issues:'}
{$stats.issues}
+
{trans 'Commits:'}
{$stats.commits}
+
{trans 'Documentations:'}
{$stats.docpages}
+
{trans 'Downloads:'}
{$stats.downloads}
+
{trans 'Code reviews:'}
{$stats.reviews}
+
Projects:
{$stats.proj_count}
+
+{/block} + +{block foot} +
Powered by InDefero, +
a Céondo Ltd initiative.
+srchub.org is ran by
Nathan Adams.
{/block} diff --git a/indefero/src/IDF/templates/idf/login_form.html b/indefero/src/IDF/templates/idf/login_form.html new file mode 100644 index 0000000..a9f313c --- /dev/null +++ b/indefero/src/IDF/templates/idf/login_form.html @@ -0,0 +1,35 @@ +{extends "idf/base-simple.html"} +{block docclass}yui-t2{/block} +{block body} +
+ +{if $error} +

{$error}

+{/if} +

{trans 'What is your account information?'}

+ + + + + + + +
{trans 'My login is'} +
{trans 'My password is'} +
+ +

+| {trans 'I lost my password!'} +

+
+ +{/block} +{block context} +
+

{trans 'Welcome.'}

+{aurl 'url', 'IDF_Views::register', array()} +

{blocktrans}You can create an account if you don't have one yet.{/blocktrans}

+

{trans 'It takes less than a minute to create your account.'}

+{/block} diff --git a/indefero/src/IDF/templates/idf/main-menu.html b/indefero/src/IDF/templates/idf/main-menu.html new file mode 100644 index 0000000..b4ae475 --- /dev/null +++ b/indefero/src/IDF/templates/idf/main-menu.html @@ -0,0 +1,32 @@ + + + +{if $allProjects.count() != 0} + +{/if} + diff --git a/indefero/src/IDF/templates/idf/project-list.html b/indefero/src/IDF/templates/idf/project-list.html new file mode 100644 index 0000000..74b42c9 --- /dev/null +++ b/indefero/src/IDF/templates/idf/project-list.html @@ -0,0 +1,41 @@ +
+ {foreach $projects as $p} +
+ +

+ {$p} + {assign $url = $p.external_project_url} + {if $url != ''} +   + {/if} + {if $p.private} - {trans 'Private project'}{/if} +

+

{$p.shortdesc}

+

{trans 'Labels:'} + {assign $tags = $p.get_tags_list()} + {if count($tags) == 0}{trans 'n/a'}{else} + {foreach $p.get_tags_list() as $idx => $label} + {if $idx != 0}, {/if} + {$label} + {/foreach} + {/if} +

+
+ {/foreach} +
+
diff --git a/indefero/src/IDF/templates/idf/project/home.html b/indefero/src/IDF/templates/idf/project/home.html new file mode 100644 index 0000000..61e776e --- /dev/null +++ b/indefero/src/IDF/templates/idf/project/home.html @@ -0,0 +1,48 @@ +{extends "idf/base.html"} +{block docclass}yui-t2{/block} +{block tabhome} class="active"{/block} +{block subtabs} + +{/block} +{block body} +{markdown $project.description, $request} +{/block} +{block context} +{if count($downloads) > 0} +

{trans 'Featured Downloads'}
+{foreach $downloads as $download} +{$download}
+{/foreach} + {trans 'show more...'} +{/if} +{if count($pages) > 0} +

{trans 'Featured Documentation'}
+{foreach $pages as $page} +{$page.title}
+{/foreach} + {trans 'show more...'} +{/if} +{assign $ko = 'owners'} +{assign $km = 'members'} +

{trans 'Development Team'}
+{trans 'Admins'}
+{foreach $team[$ko] as $owner}{aurl 'url', 'IDF_Views_User::view', array($owner.login)} +{$owner}
+{/foreach} +{if count($team[$km]) > 0} +{trans 'Happy Crew'}
+{foreach $team[$km] as $member}{aurl 'url', 'IDF_Views_User::view', array($member.login)} +{$member}
+{/foreach} +{/if} +

+

+{if $project.enableads} + +{/if} +

+{/block} + +{block foot}
Powered by InDefero,
a Céondo Ltd initiative.
srchub.org is ran by
Nathan Adams.
{/block} diff --git a/indefero/src/IDF/templates/idf/project/js-autocomplete.html b/indefero/src/IDF/templates/idf/project/js-autocomplete.html new file mode 100644 index 0000000..1799f16 --- /dev/null +++ b/indefero/src/IDF/templates/idf/project/js-autocomplete.html @@ -0,0 +1,25 @@ + + + diff --git a/indefero/src/IDF/templates/idf/project/timeline.html b/indefero/src/IDF/templates/idf/project/timeline.html new file mode 100644 index 0000000..c156b1b --- /dev/null +++ b/indefero/src/IDF/templates/idf/project/timeline.html @@ -0,0 +1,29 @@ +{extends "idf/base.html"} +{block extraheader}{/block} +{block docclass}yui-t2{/block} +{block tabhome} class="active"{/block} +{block subtabs} + +{/block} + +{block body} +{$timeline.render} +{/block} + +{block context} +

{trans 'All Updates'}

+

{trans 'Filter by type'}
+{foreach $accessible_model_filters as $filter_key => $filter_name} +{if $filter_key != 'all'} +{$filter_name}
+{/if} +{/foreach} +

+

{trans 'Subscribe to this timeline'}
+{trans 'RSS'} {trans 'Atom feed'} +

+{/block} + + diff --git a/indefero/src/IDF/templates/idf/register/confirmation-email.txt b/indefero/src/IDF/templates/idf/register/confirmation-email.txt new file mode 100644 index 0000000..7da9008 --- /dev/null +++ b/indefero/src/IDF/templates/idf/register/confirmation-email.txt @@ -0,0 +1,27 @@ +{blocktrans}Hello, + +You have requested the creation of an account to +participate in the life of a software project. + +To confirm the account please follow this link: + +{$url|safe} + +Alternatively, go to this page: + +{$urlik|safe} + +and provide the following confirmation key: + +{$key} + +If you are not interested any longer in taking +part in the life of the software project or if +you can't remember having requested the creation +of an account, please excuse us and simply ignore +this email. + +Yours faithfully, +The development team. +{/blocktrans} + diff --git a/indefero/src/IDF/templates/idf/register/confirmation.html b/indefero/src/IDF/templates/idf/register/confirmation.html new file mode 100644 index 0000000..cb4bf95 --- /dev/null +++ b/indefero/src/IDF/templates/idf/register/confirmation.html @@ -0,0 +1,65 @@ +{extends "idf/base-simple.html"} +{block body} +{if $form.errors} +
+

{trans 'Oops, please check the form for errors.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +{if $form.f.key.errors}{$form.f.key.fieldErrors}{/if} +
+{/if} + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{trans 'Login:'}{$new_user.login}
{trans 'Email:'}{$new_user.email}
{$form.f.first_name.labelTag}:{if $form.f.first_name.errors}{$form.f.first_name.fieldErrors}{/if} +{$form.f.first_name|unsafe} +
{$form.f.last_name.labelTag}:{if $form.f.last_name.errors}{$form.f.last_name.fieldErrors}{/if} +{$form.f.last_name|unsafe} +
{$form.f.password.labelTag}:{if $form.f.password.errors}{$form.f.password.fieldErrors}{/if} +{$form.f.password|unsafe}
+{$form.f.password.help_text} +
{$form.f.password2.labelTag}:{if $form.f.password2.errors}{$form.f.password2.fieldErrors}{/if} +{$form.f.password2|unsafe} +
  | {trans 'Cancel'} +
{$form.f.key|unsafe} +
+{/block} +{block context} +
+

{trans 'This is the last step, but just be sure to have the cookies enabled to log in afterwards.'}

+
+{/block} +{block javascript} +{/block} + diff --git a/indefero/src/IDF/templates/idf/register/index.html b/indefero/src/IDF/templates/idf/register/index.html new file mode 100644 index 0000000..0d63a4f --- /dev/null +++ b/indefero/src/IDF/templates/idf/register/index.html @@ -0,0 +1,77 @@ +{extends "idf/base-simple.html"} +{block body} +{if $form.errors} +
+

{trans 'Oops, please check the provided login and email address to register.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +
+{/if} + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
{$form.f.login.labelTag}:{if $form.f.login.errors}{$form.f.login.fieldErrors}{/if} +{$form.f.login|unsafe}
+{$form.f.login.help_text} +
{$form.f.regkey.labelTag}:{if $form.f.regkey.errors}{$form.f.regkey.fieldErrors}{/if} +{$form.f.regkey|unsafe}
+{$form.f.regkey.help_text} +
{$form.f.email.labelTag}:{if $form.f.email.errors}{$form.f.email.fieldErrors}{/if} +{$form.f.email|unsafe}
+{$form.f.email.help_text} +
 
{$terms}
  +{if $form.f.terms.errors}{$form.f.terms.fieldErrors}{/if} +{$form.f.terms|unsafe} {$form.f.terms.labelTag}
+{blocktrans}Read the terms and conditions – basically "Please be nice, we respect you".{/blocktrans} +
  | {trans 'Cancel'} +
+
+{/block} +{block context} +
+

{trans 'Be sure to provide a valid email address, as we are sending a validation link by email.'}

+{aurl 'url', 'IDF_Views::passwordRecoveryAsk'} +

{blocktrans}If you have just forgotten your login information, then there is no need to create a new account. You can just recover your login name and password.{/blocktrans}

+

{trans 'Did you know?'}
+{aurl 'url', 'IDF_Views::faq'} +{blocktrans}With your account, you will able to participate in the life of all the projects hosted here. Participating in a software project must be fun, so if you have troubles, you can let us know about your issues at anytime!{/blocktrans}

+
+{/block} +{block javascript} +{/block} + diff --git a/indefero/src/IDF/templates/idf/register/inputkey.html b/indefero/src/IDF/templates/idf/register/inputkey.html new file mode 100644 index 0000000..e79e2c0 --- /dev/null +++ b/indefero/src/IDF/templates/idf/register/inputkey.html @@ -0,0 +1,40 @@ +{extends "idf/base-simple.html"} +{block body} +{if $form.errors} +
+

{trans 'Oops, we found an error in the form.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +
+{/if} + +
+ + + + + + + + + +
 {$form.f.key.labelTag}:
+{if $form.f.key.errors}{$form.f.key.fieldErrors}{/if} +{$form.f.key|unsafe} +
  | {trans 'Cancel'} +
+
+{/block} +{block context} +
+

{trans 'Instructions'}

+

{trans 'Use your email software to read your emails and open your confirmation email. Either click directly on the confirmation link or copy/paste the confirmation key in the box and submit the form.'}

+

{trans 'Just after providing the confirmation key, you will be able to set your password and start using this website fully.'}

+
+{/block} +{block javascript} +{/block} + diff --git a/indefero/src/IDF/templates/idf/review/base-full.html b/indefero/src/IDF/templates/idf/review/base-full.html new file mode 100644 index 0000000..e013932 --- /dev/null +++ b/indefero/src/IDF/templates/idf/review/base-full.html @@ -0,0 +1,15 @@ +{extends "idf/base-full.html"} +{block tabreview} class="active"{/block} +{block subtabs} +
+{trans 'Open Reviews'} {* + +{if !$user.isAnonymous()} | {trans 'New Issue'} | {trans 'My Issues'}{/if} | +
+ + +
+*} +{superblock} +
+{/block} diff --git a/indefero/src/IDF/templates/idf/review/base.html b/indefero/src/IDF/templates/idf/review/base.html new file mode 100644 index 0000000..74a2396 --- /dev/null +++ b/indefero/src/IDF/templates/idf/review/base.html @@ -0,0 +1,9 @@ +{extends "idf/base.html"} +{block tabreview} class="active"{/block} +{block subtabs} +
+{trans 'Open Reviews'} +{if !$user.isAnonymous()} | {trans 'Start Code Review'} {/if} +{superblock} +
+{/block} diff --git a/indefero/src/IDF/templates/idf/review/create.html b/indefero/src/IDF/templates/idf/review/create.html new file mode 100644 index 0000000..d96caa5 --- /dev/null +++ b/indefero/src/IDF/templates/idf/review/create.html @@ -0,0 +1,69 @@ +{extends "idf/review/base.html"} +{block docclass}yui-t3{assign $inCreate = true}{/block} +{block body} +{if $form.errors} +
+

{trans 'The form contains some errors. Please correct them to submit the code review.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +
+{/if} + +
+ + + + + + + + + + + + + + + + +{if $isOwner or $isMember} + + + +{/if} + + + + +
{$form.f.summary.labelTag}:{if $form.f.summary.errors}{$form.f.summary.fieldErrors}{/if} +{$form.f.summary|unsafe} +
{$form.f.description.labelTag}:{if $form.f.description.errors}{$form.f.description.fieldErrors}{/if} +{$form.f.description|unsafe} +
{$form.f.commit.labelTag}:{if $form.f.commit.errors}{$form.f.commit.fieldErrors}{/if} +{$form.f.commit|unsafe}
+{trans 'Select the commit against which you created your patch to be sure it applies correctly.'} +
{$form.f.patch.labelTag}:{if $form.f.patch.errors}{$form.f.patch.fieldErrors}{/if} +{$form.f.patch|unsafe} +
{$form.f.status.labelTag}:{if $form.f.status.errors}{$form.f.status.fieldErrors}{/if} +{$form.f.status|unsafe} +
  | {trans 'Cancel'} +
+
+{/block} +{block context} +
+{blocktrans}

To start a code review, you need to provide:

+
    +
  • A commit or revision of the current code in the repository from which you started your work.
  • +
  • A patch describing your changes with respect to the reference commit.
  • +
  • Check your patch does not provide any password or confidential information!
  • +
{/blocktrans} +
+{/block} +{block javascript} +{/block} + + diff --git a/indefero/src/IDF/templates/idf/review/feedfragment.xml b/indefero/src/IDF/templates/idf/review/feedfragment.xml new file mode 100644 index 0000000..642ef32 --- /dev/null +++ b/indefero/src/IDF/templates/idf/review/feedfragment.xml @@ -0,0 +1,18 @@ + + {$title} - {$review.get_status} + + {$url} + {$date} + {$author} +
+{if $c} +
{issuetext $c.content, $request}
+{if $c.changes} +{foreach $c.changes as $w => $v} +{if $w == 'su'}{trans 'Summary:'}{/if}{if $w == 'st'}{trans 'Status:'}{/if}{if $w == 'ow'}{trans 'Owner:'}{/if}{if $w == 'lb'}{trans 'Labels:'}{/if} {if $w == 'lb'}{assign $l = implode(', ', $v)}{$l}{else}{$v}{/if}
+{/foreach} +{/if}{else} +
{issuetext $p.description, $request}
+{/if} +
+
diff --git a/indefero/src/IDF/templates/idf/review/index.html b/indefero/src/IDF/templates/idf/review/index.html new file mode 100644 index 0000000..876f606 --- /dev/null +++ b/indefero/src/IDF/templates/idf/review/index.html @@ -0,0 +1,8 @@ +{extends "idf/review/base.html"} +{block docclass}yui-t2{assign $inOpenReviews=true}{/block} +{block body} +{$reviews.render} +{if !$user.isAnonymous()} +{aurl 'url', 'IDF_Views_Review::create', array($project.shortname)} +

+ {trans 'Start Code Review'}

{/if} +{/block} diff --git a/indefero/src/IDF/templates/idf/review/review-created-email.txt b/indefero/src/IDF/templates/idf/review/review-created-email.txt new file mode 100644 index 0000000..63575df --- /dev/null +++ b/indefero/src/IDF/templates/idf/review/review-created-email.txt @@ -0,0 +1,17 @@ +{trans 'Hello,'} + +{blocktrans}The following review has been created:{/blocktrans} + +{$review.id} - {$review.summary|safe} + +{trans 'Project:'} {$project.name|safe} +{trans 'Status:'} {$review.get_status.name} +{trans 'Reported by:'} {$review.get_submitter|safe} +{trans 'URL:'} {$url_base}{url 'IDF_Views_Review::view', array($project.shortname, $review.id)} +{assign $tags = $review.get_tags_list()}{if $tags.count()}{trans 'Labels:'} +{foreach $tags as $tag} {$tag.class|safe}:{$tag.name|safe} +{/foreach} +{/if} + +-- +{trans 'Review:'} {$url_base}{url 'IDF_Views_Review::view', array($project.shortname, $review.id)} diff --git a/indefero/src/IDF/templates/idf/review/review-updated-email.txt b/indefero/src/IDF/templates/idf/review/review-updated-email.txt new file mode 100644 index 0000000..404688a --- /dev/null +++ b/indefero/src/IDF/templates/idf/review/review-updated-email.txt @@ -0,0 +1,29 @@ +{trans 'Hello,'} + +{blocktrans}The following review has been updated:{/blocktrans} + +{$review.id} - {$review.summary|safe} +{trans 'Project:'} {$project.name|safe} +{trans 'Status:'} {$review.get_status.name} +{trans 'Reported by:'} {$review.get_submitter|safe} +{trans 'URL:'} {$url_base}{url 'IDF_Views_Review::view', array($project.shortname, $review.id)} +{assign $tags = $review.get_tags_list()}{if $tags.count()}{trans 'Labels:'} +{foreach $tags as $tag} {$tag.class|safe}:{$tag.name|safe} +{/foreach} +{/if}{trans 'General comments (last first):'} + +{foreach $gcomments as $c}{assign $who = $c.get_submitter()}# {blocktrans}By {$who|safe}, {$c.creation_dtime|date}:{/blocktrans} +{$c.content|safe} + +{/foreach} +{trans 'Detailed file comments (last first):'} + +{foreach $comments as $c}{assign $who = $c.get_comment().get_submitter()}# {blocktrans}By {$who|safe}, {$c.creation_dtime|date}, on file: +{$c.cfile|safe} +{/blocktrans} +{$c.content|safe} + +{/foreach} + +-- +{trans 'Review:'} {$url_base}{url 'IDF_Views_Review::view', array($project.shortname, $review.id)} diff --git a/indefero/src/IDF/templates/idf/review/view.html b/indefero/src/IDF/templates/idf/review/view.html new file mode 100644 index 0000000..41d368b --- /dev/null +++ b/indefero/src/IDF/templates/idf/review/view.html @@ -0,0 +1,167 @@ +{extends "idf/review/base-full.html"} +{block extraheader}{/block} +{block docclass}yui-t1{assign $inCreate = true}{/block} +{block body} +{if !$user.isAnonymous() and $form.errors} +
+

{trans 'The form contains some errors. Please correct them to submit your review.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +
+{/if} +{if !$user.isAnonymous()} +
+

{trans 'How to Participate in a Code Review'}

+ +

{blocktrans}Code review is a process in which +after or before changes are commited into the code repository, +different people discuss the code changes. The goal is +to improve the quality of the code and the +contributions, as such, you must be pragmatic when writing +your review. Correctly mention the line numbers (in the old or in the +new file) and try to keep a good balance between seriousness and fun. +{/blocktrans}

+

{blocktrans} +Proposing code for review is intimidating, you know +you will receive critics, so please, as a reviewer, keep this +process fun, use it to help your contributor learn your +coding standards and the structure of the code and make them want +to propose more contributions. +{/blocktrans}

+{/if} + + + + + + + + + + + + + + + + + + +{if count($diff.files)} + + + +{/if} +{aurl 'url', 'IDF_Views_Review::getPatch', array($project.shortname, $patch.id)} + + +
{trans 'Created:'}{$patch.creation_dtime|date:"%Y-%m-%d %H:%M:%S"} ({$patch.creation_dtime|dateago})
{trans 'Updated:'}{$review.modif_dtime|dateago}
{trans 'Author:'}{$review.get_submitter()}
{trans 'Commit:'}{$patch.get_commit().scm_id}
{trans 'Description:'}{issuetext $review.summary, $request}

{issuetext $patch.description, $request}
{trans 'Reviewers:'}{if count($reviewers)}{foreach $reviewers as $r}{$r}, {/foreach}{else}{trans 'No reviewers at the moment.'}{/if}
{trans 'Files:'} +{foreach $diff.files as $filename=>$diffdef} +{assign $ndiff = count($diffdef['chunks'])} +{assign $nc = $files[$filename][2]->count()} +{$filename} ({blocktrans $ndiff}{$ndiff} diff{plural}{$ndiff} diffs{/blocktrans}{if $nc}, {blocktrans $nc}{$nc} comment{plural}{$nc} comments{/blocktrans}{/if})
+{/foreach} +
 {trans 'Archive'} {trans 'Download the corresponding diff file'}
+ +
+{foreach $files as $file=>$def} + + {$def[0]} + +{assign $fcomments = $def[2]} +{assign $nc = $fcomments.count()} +{assign $i = 1} +{foreach $fcomments as $c} +
{assign $who = $c.get_comment().get_submitter()}{aurl 'whourl', 'IDF_Views_User::view', array($who.login)} +{aurl 'url', 'IDF_Views_Review::view', array($project.shortname, $review.id)} +{assign $id = $c.id} +{assign $url = $url~'#ic'~$c.id} +{blocktrans}Comment {$i} by {$who}, {$c.creation_dtime|date}{/blocktrans}

+ +
{issuetext $c.content, $request}
+
{assign $i = $i + 1} +{/foreach} +{if !$user.isAnonymous()} + + + + +
  +

{blocktrans}Your comments on the changes in file {$file}:{/blocktrans}
{$def[1]|safe}

+
{/if} +{/foreach} + +{assign $i = 1} +{assign $nc = $comments.count()} +{if $nc}
+

{trans 'General Comments'}

+{/if} +{foreach $comments as $c}{ashowuser 'submitter', $c.get_submitter(), $request}{assign $submitter = $c.get_submitter()}{assign $submitter_data = $c.get_submitter_data()} +
+{if $submitter_data.avatar != ''} +  +{else} +  +{/if} +{aurl 'url', 'IDF_Views_Review::view', array($project.shortname, $review.id)} +{assign $id = $c.id} +{assign $url = $url~'#ic'~$c.id} +

{blocktrans}Comment {$i} by {$submitter}, {$c.creation_dtime|date}{/blocktrans}

+ + + +{if strlen($c.content) > 0}
{issuetext $c.content, $request}
{/if} + +{if $c.changedReview()} +
+{foreach $c.changes as $w => $v} +{if $w == 'su'}{trans 'Summary:'}{/if}{if $w == 'st'}{trans 'Status:'}{/if} {$v}
+{/foreach} +
+{/if} +
{assign $i = $i + 1}{if $i == $nc+1 and $user.isAnonymous()} + +{/if} +{/foreach} + +{if !$user.isAnonymous()} +{if !$nc}
{/if} + + + + + +{if $isOwner or $isMember} + + + + + + + +{/if} + + + +
{$form.f.content.labelTag}:{if $form.f.content.errors}{$form.f.content.fieldErrors}{/if} +{$form.f.content|unsafe} +
{$form.f.summary.labelTag}:{if $form.f.summary.errors}{$form.f.summary.fieldErrors}{/if} +{$form.f.summary|unsafe} +
{$form.f.status.labelTag}:{if $form.f.status.errors}{$form.f.status.fieldErrors}{/if} +{$form.f.status|unsafe} +
  | {trans 'Cancel'} +
+{/if} +
+{/block} + +{block javascript} + + +{if $isOwner or $isMember}{include 'idf/issues/js-autocomplete.html'}{/if} +{/block} diff --git a/indefero/src/IDF/templates/idf/source/base.html b/indefero/src/IDF/templates/idf/source/base.html new file mode 100644 index 0000000..0526095 --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/base.html @@ -0,0 +1,12 @@ +{extends "idf/base.html"} +{block tabsource} class="active"{/block} +{block subtabs} +{if !$inHelp and !$inError and (in_array($commit, $tree_in) or (in_array($commit, $tags_in)))}{assign $currentCommit = $commit}{else}{assign $currentCommit = $project.getScmRoot()}{/if} +
+{trans 'Source Tree'} | +{trans 'Change Log'} +{if $inCommit}| {trans 'Commit'}{/if} | +{trans 'How To Get The Code'} +
+{/block} +{block title}{$title}{/block} diff --git a/indefero/src/IDF/templates/idf/source/changelog.html b/indefero/src/IDF/templates/idf/source/changelog.html new file mode 100644 index 0000000..9223651 --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/changelog.html @@ -0,0 +1,40 @@ +{extends "idf/source/base.html"} +{block docclass}yui-t1{assign $inChangeLog=true}{/block} +{block body} + + + + + + + + +{foreach $changes as $change} +{aurl 'url', 'IDF_Views_Source::commit', array($project.shortname, $change.scm_id)} + + + + + + + +{/foreach} + +
{trans 'Age'}{trans 'Message'}
{$change.creation_dtime|dateago:"without"}{issuetext $change.summary, $request}{if $change.fullmessage}

{issuetext $change.fullmessage, $request, true, false, true, true, true}{/if} + + +{assign $parents = $change.extra.getVal('parents')} + +{if count($parents) > 1}
+{foreach $parents as $parent}
+{trans 'Parent:'} {$parent} +{/foreach}
{/if} + + +
+
{trans 'Commit'} {$change.scm_id}, +{trans 'by'} {showuser $change.get_author(), $request, $change.origauthor} +
+ +
+{/block} diff --git a/indefero/src/IDF/templates/idf/source/commit-created-email.txt b/indefero/src/IDF/templates/idf/source/commit-created-email.txt new file mode 100644 index 0000000..99c5683 --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/commit-created-email.txt @@ -0,0 +1,17 @@ +{trans 'Hello,'} + +{blocktrans}A new commit has been created:{/blocktrans} + +{$commit.summary|safe} + +{trans 'Commit:'} {$commit.scm_id|safe} +{trans 'Project:'} {$project.name|safe} +{trans 'Created by:'} {$commit.get_author|safe} +{trans 'Created at:'} {$commit.creation_dtime|date:"%Y-%m-%d %H:%M:%S"} +{if $commit.fullmessage} +{trans 'Content:'} + +{$commit.fullmessage} +{/if} +-- +{trans 'Commit details:'} {$url_base}{url 'IDF_Views_Source::commit', array($project.shortname, $commit.scm_id)} diff --git a/indefero/src/IDF/templates/idf/source/commit.html b/indefero/src/IDF/templates/idf/source/commit.html new file mode 100644 index 0000000..4ff919b --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/commit.html @@ -0,0 +1,83 @@ +{extends "idf/source/base.html"} +{block extraheader}{/block} +{block docclass}yui-t1{assign $inCommit=true}{/block} +{block body} + + + + + + + +{if $cobject.branch} + +{/if} + + + +{if $cobject.parents} + +{/if} + + +{if count($cobject.parents) < 2 and count($changes)} + + + +{/if} {* End of the if count($changes) *} +
{trans 'Date:'}{$cobject.date|date:"%Y-%m-%d %H:%M:%S"} ({$cobject.date|dateago})
{trans 'Author:'}{showuser $rcommit.get_author(), $request, $cobject.author}
{trans 'Branch:'}{$cobject.branch}
{trans 'Commit:'}{$cobject.commit}
{trans 'Parents:'}{foreach $cobject.parents as $parent} +{$parent}
+{/foreach} +
{trans 'Message:'}{issuetext $cobject.title, $request}{if isset($cobject.full_message)}

{issuetext $cobject.full_message, $request, true, false, true, true, true}{/if}
{trans 'Changes:'} + +{foreach $changes.deletions as $filename} + +{/foreach} +{foreach $changes.renames as $oldname => $newname} + +{/foreach} +{foreach $changes.copies as $srcname => $destname} + +{/foreach} +{foreach $changes.additions as $filename} + +{/foreach} +{foreach $changes.patches as $filename} + +{/foreach} +{foreach $changes.properties as $filename => $properties} + +{/foreach} +
D{$filename}{if !empty($diff.files[$filename])} ({trans 'full'}){/if}
R{$oldname} → {$newname}
C{$srcname} → {$destname}
A{$filename}{if !empty($diff.files[$filename])} ({trans 'full'}){/if}
M{$filename}{if !empty($diff.files[$filename])}{assign $ndiff = count($diff.files[$filename]['chunks'])} ({blocktrans $ndiff}{$ndiff} diff{plural}{$ndiff} diffs{/blocktrans}){/if}
P{$filename} + +{foreach $properties as $key => $value} + +{if $value == null} + +{else} + +{/if} + +{/foreach} +
{$key}{trans 'removed'}{$value}
+
+
+ +{if count($cobject.parents) < 2 and count($diff.files)} +

{trans 'File differences'}

+ +{$diff.as_html()} +{/if} + +{if count($cobject.parents) < 2 and (count($diff.files) or $large_commit)} +{aurl 'url', 'IDF_Views_Source::downloadDiff', array($project.shortname, $commit)} +

{trans 'Archive'} {trans 'Download the corresponding diff file'}

+{/if} + +{/block} +{block javascript} + + +{/block} diff --git a/indefero/src/IDF/templates/idf/source/disambiguate_revision.html b/indefero/src/IDF/templates/idf/source/disambiguate_revision.html new file mode 100644 index 0000000..85c3d61 --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/disambiguate_revision.html @@ -0,0 +1,33 @@ +{extends "idf/source/base.html"} +{block docclass}yui-t2{assign $inError=true}{/block} +{block body} + +

{blocktrans}The revision identifier {$commit} is ambiguous and can be +expanded to multiple valid revisions - please choose one:{/blocktrans}

+ + + + + + + + + + + + +{foreach $revisions as $revision} +{aurl 'url', $redirect, array($project.shortname, $revision.commit)} + + + + + + + + +{/foreach} + +
{trans 'Title'}{trans 'Author'}{trans 'Date'}{trans 'Branch'}{trans 'Revision'}
{$revision.title}{$revision.author}{$revision.date}{$revision.branch}{$revision.commit}
+{/block} + diff --git a/indefero/src/IDF/templates/idf/source/feedfragment.xml b/indefero/src/IDF/templates/idf/source/feedfragment.xml new file mode 100644 index 0000000..91eea24 --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/feedfragment.xml @@ -0,0 +1,11 @@ + + {blocktrans}{$cproject.name}: Commit {$c.scm_id}{/blocktrans} + + {$author} + {$url} + {$date} +
+{issuetext $c.summary, $request}{if $c.fullmessage}

+{issuetext $c.fullmessage, $request, true, false, true, true, true}{/if} +
+
diff --git a/indefero/src/IDF/templates/idf/source/git/branch_tag_list.html b/indefero/src/IDF/templates/idf/source/git/branch_tag_list.html new file mode 100644 index 0000000..b9c4026 --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/git/branch_tag_list.html @@ -0,0 +1,39 @@ +{if !$view_url} +{assign $view_url = 'IDF_Views_Source::treeBase'} +{/if} +
+
+

+ {trans 'Branches'} + + + + +

+ +{if $tags} +

+ {trans 'Tags'} + + + + +

+ +{/if} +
+ diff --git a/indefero/src/IDF/templates/idf/source/git/changelog.html b/indefero/src/IDF/templates/idf/source/git/changelog.html new file mode 100644 index 0000000..a5a82bd --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/git/changelog.html @@ -0,0 +1,5 @@ +{extends "idf/source/changelog.html"} +{block context} +{assign $view_url = 'IDF_Views_Source::changeLog'} +{include 'idf/source/git/branch_tag_list.html'} +{/block} diff --git a/indefero/src/IDF/templates/idf/source/git/commit.html b/indefero/src/IDF/templates/idf/source/git/commit.html new file mode 100644 index 0000000..8421adf --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/git/commit.html @@ -0,0 +1,5 @@ +{extends "idf/source/commit.html"} +{block context} +{include 'idf/source/git/branch_tag_list.html'} +{/block} + diff --git a/indefero/src/IDF/templates/idf/source/git/file.html b/indefero/src/IDF/templates/idf/source/git/file.html new file mode 100644 index 0000000..01691ad --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/git/file.html @@ -0,0 +1,31 @@ +{extends "idf/source/base.html"} +{block extraheader}{/block} +{block docclass}yui-t1{assign $inSourceTree=true}{/block} +{block body} +

{trans 'Root'}/{if $breadcrumb}{$breadcrumb|safe}{/if}

+ + +{if !$tree_in and !$tags_in} +{aurl 'url', 'IDF_Views_Source::commit', array($project.shortname, $commit)} + + + +{/if} + +{$file} + +
{blocktrans}Source at commit {$commit} created {$cobject.date|dateago}.{/blocktrans}
+{blocktrans}By {$cobject.author|strip_tags|trim}, {$cobject.title}{/blocktrans} +
+{aurl 'url', 'IDF_Views_Source::getFile', array($project.shortname, $commit, $fullpath)} +

{trans 'Archive'} {trans 'Download this file'}

+ +{/block} +{block context} +{include 'idf/source/git/branch_tag_list.html'} +{/block} + +{block javascript} + + +{/block} diff --git a/indefero/src/IDF/templates/idf/source/git/help.html b/indefero/src/IDF/templates/idf/source/git/help.html new file mode 100644 index 0000000..e270111 --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/git/help.html @@ -0,0 +1,38 @@ +{extends "idf/source/base.html"} +{block docclass}yui-t2{assign $inHelp=true}{/block} +{block body} + +

{blocktrans}The team behind {$project} is using +the git software to manage the source +code.{/blocktrans}

+ +

{trans 'Command-Line Access'}

+ +

git clone {$project.getSourceAccessUrl($user)}

+ +{aurl 'url', 'IDF_Views_User::myAccount'} +

{blocktrans}You may need to provide your SSH key. The synchronization of your SSH key can take a couple of minutes. You can learn more about SSH key authentication.{/blocktrans}

+ +{if $isOwner or $isMember} +

{trans 'First Commit'}

+ +

{blocktrans}To make a first commit in the repository, perform the following steps:{/blocktrans}

+ +
+git init
+git add .
+git commit -m "initial import"
+git remote add origin {$project.getWriteRemoteAccessUrl($user)}
+git push origin master
+
+ +{/if} + +{/block} +{block context} +
+

{blocktrans}Find here more details on how to access {$project} source code.{/blocktrans}

+
+{/block} + + diff --git a/indefero/src/IDF/templates/idf/source/git/invalid_revision.html b/indefero/src/IDF/templates/idf/source/git/invalid_revision.html new file mode 100644 index 0000000..2b5822e --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/git/invalid_revision.html @@ -0,0 +1,2 @@ +{extends "idf/source/invalid_revision.html"} + diff --git a/indefero/src/IDF/templates/idf/source/git/tree.html b/indefero/src/IDF/templates/idf/source/git/tree.html new file mode 100644 index 0000000..180069e --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/git/tree.html @@ -0,0 +1,56 @@ +{extends "idf/source/base.html"} +{block docclass}yui-t1{assign $inSourceTree=true}{/block} +{block body} +

{trans 'Root'}/{if $breadcrumb}{$breadcrumb|safe}{/if}

+ + + + + + + + + +{if !$tree_in and !$tags_in} +{aurl 'url', 'IDF_Views_Source::commit', array($project.shortname, $commit)} + + + +{/if} +{if $base} + + + + + +{/if} +{foreach $files as $file} +{aurl 'url', 'IDF_Views_Source::tree', array($project.shortname, $commit, $file.efullpath)} + + +{if $file.type != 'extern'} +{$file.file}{else}{/if} +{if $file.type == 'blob'} +{if isset($file.date) and $file.log != '----'} + + +{else}{/if} +{/if} +{if $file.type == 'extern'} + +{/if} + +{/foreach} + +
{trans 'File'}{trans 'Age'}{trans 'Message'}{trans 'Size'}
{blocktrans}Source at commit {$commit} created {$cobject.date|dateago}.{/blocktrans}
+{blocktrans}By {$cobject.author|strip_tags|trim}, {$cobject.title}{/blocktrans} +
  +..
{$file.type}{$file.file}{$file.date|dateago:"without"}{$file.author|strip_tags|trim}{trans ':'} {issuetext $file.log, $request, true, false}{$file.size|size}{$file.extern}
+{aurl 'url', 'IDF_Views_Source::download', array($project.shortname, $commit)} +

{trans 'Archive'} {trans 'Download this version'} {trans 'or'} git clone {$project.getSourceAccessUrl($user)} {trans 'Help'}

+ + +{/block} +{block context} +{include 'idf/source/git/branch_tag_list.html'} +{/block} diff --git a/indefero/src/IDF/templates/idf/source/invalid_revision.html b/indefero/src/IDF/templates/idf/source/invalid_revision.html new file mode 100644 index 0000000..b030b27 --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/invalid_revision.html @@ -0,0 +1,29 @@ +{extends "idf/source/base.html"} +{block docclass}yui-t2{assign $inError=true}{/block} +{block body} + +

{blocktrans}The branch or revision {$commit} is not valid or does not exist +in this repository.{/blocktrans}

+ +{if count($branches) > 0} +

{blocktrans}The following list shows all available branches:{/blocktrans}

+ +{/if} + +{if $isOwner or $isMember} +{aurl 'url', 'IDF_Views_Source::help', array($project.shortname)} +

{blocktrans}If this is a new repository, the reason for this error +could be that you have not committed and / or pushed any change so far. +In this case please take a look at the Help page +how to access your repository.{/blocktrans}

+{/if} + +{/block} + diff --git a/indefero/src/IDF/templates/idf/source/mercurial/branch_tag_list.html b/indefero/src/IDF/templates/idf/source/mercurial/branch_tag_list.html new file mode 100644 index 0000000..98b3312 --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/mercurial/branch_tag_list.html @@ -0,0 +1,39 @@ +{if !$view_url} +{assign $view_url = 'IDF_Views_Source::treeBase'} +{/if} +
+
+

+ {trans 'Branches'} + + + + +

+
    +{foreach $branches as $branch => $path} +{aurl 'url', $view_url, array($project.shortname, $branch)} +
  • + {$branch} +
  • +{/foreach} +
+{if $tags} +

+ {trans 'Tags'} + + + + +

+
    +{foreach $tags as $tag => $path} +{aurl 'url', $view_url, array($project.shortname, $tag)} +
  • + {$tag} +
  • +{/foreach} +
+{/if} +
+ diff --git a/indefero/src/IDF/templates/idf/source/mercurial/changelog.html b/indefero/src/IDF/templates/idf/source/mercurial/changelog.html new file mode 100644 index 0000000..8fb2ac3 --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/mercurial/changelog.html @@ -0,0 +1,6 @@ +{extends "idf/source/changelog.html"} +{block context} +{assign $view_url = 'IDF_Views_Source::changeLog'} +{include 'idf/source/mercurial/branch_tag_list.html'} +{/block} + diff --git a/indefero/src/IDF/templates/idf/source/mercurial/commit.html b/indefero/src/IDF/templates/idf/source/mercurial/commit.html new file mode 100644 index 0000000..707cb23 --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/mercurial/commit.html @@ -0,0 +1,5 @@ +{extends "idf/source/commit.html"} +{block context} +{include 'idf/source/mercurial/branch_tag_list.html'} +{/block} + diff --git a/indefero/src/IDF/templates/idf/source/mercurial/file.html b/indefero/src/IDF/templates/idf/source/mercurial/file.html new file mode 100644 index 0000000..25d4572 --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/mercurial/file.html @@ -0,0 +1,32 @@ +{extends "idf/source/base.html"} +{block extraheader}{/block} +{block docclass}yui-t1{assign $inSourceTree=true}{/block} + +{block body} +

{trans 'Root'}/{if $breadcrumb}{$breadcrumb|safe}{/if}

+ + +{if !$tree_in} +{aurl 'url', 'IDF_Views_Source::commit', array($project.shortname, $commit)} + + + +{/if} + +{$file} + +
{blocktrans}Source at commit {$commit} created {$cobject.date|dateago}.{/blocktrans}
+{blocktrans}By {$cobject.author|strip_tags|trim}, {$cobject.title}{/blocktrans} +
+{aurl 'url', 'IDF_Views_Source::getFile', array($project.shortname, $commit, $efullpath)} +

{trans 'Archive'} {trans 'Download this file'}

+{/block} + +{block context} +{include 'idf/source/mercurial/branch_tag_list.html'} +{/block} + +{block javascript} + + +{/block} diff --git a/indefero/src/IDF/templates/idf/source/mercurial/help.html b/indefero/src/IDF/templates/idf/source/mercurial/help.html new file mode 100644 index 0000000..2084c0c --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/mercurial/help.html @@ -0,0 +1,31 @@ +{extends "idf/source/base.html"} +{block docclass}yui-t2{assign $inHelp=true}{/block} +{block body} + +

{blocktrans}The team behind {$project} is using +the Mercurial software to manage the source +code.{/blocktrans}

+ +

{trans 'Command-Line Access'}

+ +

hg clone {$project.getRemoteAccessUrl()}

+ + +{if $isOwner or $isMember} +

{trans 'Write Access Authentication'}

+ +{aurl 'url', 'IDF_Views_User::myAccount'} +

{blocktrans}To get write access to the repository, you need to use your username and your extra password.{/blocktrans}

+ +

hg clone {$project.getRemoteAccessUrl()}

+ +{/if} + +{/block} +{block context} +
+

{blocktrans}Find here more details on how to access {$project} source code.{/blocktrans}

+
+{/block} + + diff --git a/indefero/src/IDF/templates/idf/source/mercurial/invalid_revision.html b/indefero/src/IDF/templates/idf/source/mercurial/invalid_revision.html new file mode 100644 index 0000000..2b5822e --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/mercurial/invalid_revision.html @@ -0,0 +1,2 @@ +{extends "idf/source/invalid_revision.html"} + diff --git a/indefero/src/IDF/templates/idf/source/mercurial/tree.html b/indefero/src/IDF/templates/idf/source/mercurial/tree.html new file mode 100644 index 0000000..4df5a30 --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/mercurial/tree.html @@ -0,0 +1,52 @@ +{extends "idf/source/base.html"} +{block docclass}yui-t1{assign $inSourceTree=true}{/block} +{block body} +

{trans 'Root'}/{if $breadcrumb}{$breadcrumb|safe}{/if}

+ + + + + + + + + +{if !$tree_in and !$tags_in} +{aurl 'url', 'IDF_Views_Source::commit', array($project.shortname, $commit)} + + + +{/if} +{if $base} + + + + + +{/if} +{foreach $files as $file} +{aurl 'url', 'IDF_Views_Source::tree', array($project.shortname, $commit, $file.efullpath)} + + +{$file.file} +{if $file.type == 'blob'} +{if isset($file.date)} + + +{else}{/if} +{/if} + +{/foreach} + +
{trans 'File'}{trans 'Age'}{trans 'Message'}{trans 'Size'}
{blocktrans}Source at commit {$commit} created {$cobject.date|dateago}.{/blocktrans}
+{blocktrans}By {$cobject.author|strip_tags|trim}, {$cobject.title}{/blocktrans} +
  +..
{$file.type}{$file.date|dateago:"without"}{$file.author|strip_tags|trim}{trans ':'} {$file.log}
+{aurl 'url', 'IDF_Views_Source::download', array($project.shortname, $commit)} +

{trans 'Archive'} {trans 'Download this version'} {trans 'or'} hg clone {$project.getRemoteAccessUrl()} {trans 'Help'}

+{/block} + +{block context} +{include 'idf/source/mercurial/branch_tag_list.html'} +{/block} + diff --git a/indefero/src/IDF/templates/idf/source/mtn/branch_tag_list.html b/indefero/src/IDF/templates/idf/source/mtn/branch_tag_list.html new file mode 100644 index 0000000..c0a772f --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/mtn/branch_tag_list.html @@ -0,0 +1,39 @@ +{if !$view_url} +{assign $view_url = 'IDF_Views_Source::treeBase'} +{/if} +
+
+

+ {trans 'Branches'} + + + + +

+
    +{foreach $branches as $selector => $branch} +{aurl 'url', $view_url, array($project.shortname, $selector)} +
  • + {$branch} +
  • +{/foreach} +
+{if $tags} +

+ {trans 'Tags'} + + + + +

+
    +{foreach $tags as $selector => $tag} +{aurl 'url', $view_url, array($project.shortname, $selector)} +
  • + {$tag} +
  • +{/foreach} +
+{/if} +
+ diff --git a/indefero/src/IDF/templates/idf/source/mtn/changelog.html b/indefero/src/IDF/templates/idf/source/mtn/changelog.html new file mode 100644 index 0000000..cb124a6 --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/mtn/changelog.html @@ -0,0 +1,5 @@ +{extends "idf/source/changelog.html"} +{block context} +{assign $view_url = 'IDF_Views_Source::changeLog'} +{include 'idf/source/mtn/branch_tag_list.html'} +{/block} diff --git a/indefero/src/IDF/templates/idf/source/mtn/commit.html b/indefero/src/IDF/templates/idf/source/mtn/commit.html new file mode 100644 index 0000000..bec83e2 --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/mtn/commit.html @@ -0,0 +1,4 @@ +{extends "idf/source/commit.html"} +{block context} +{include 'idf/source/mtn/branch_tag_list.html'} +{/block} diff --git a/indefero/src/IDF/templates/idf/source/mtn/file.html b/indefero/src/IDF/templates/idf/source/mtn/file.html new file mode 100644 index 0000000..0c1bd19 --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/mtn/file.html @@ -0,0 +1,43 @@ +{extends "idf/source/base.html"} +{block extraheader}{/block} +{block docclass}yui-t1{assign $inSourceTree=true}{/block} +{block body} +

{trans 'Root'}/{if $breadcrumb}{$breadcrumb|safe}{/if}

+ + +{if (!$tree_in and !$tags_in) or $props} +{aurl 'url', 'IDF_Views_Source::commit', array($project.shortname, $commit)} + + {if $props} + + {/if} + {if !$tree_in and !$tags_in} + + + + {/if} + +{/if} + +{$file} + +
+
    + {foreach $props as $prop => $val} +
  • {blocktrans}Property {$prop} set to {$val}{/blocktrans}
  • + {/foreach} +
+
{blocktrans}Source at commit {$commit} created {$cobject.date|dateago}.{/blocktrans}
+ {blocktrans}By {$cobject.author|strip_tags|trim}, {$cobject.title}{/blocktrans} +
+{aurl 'url', 'IDF_Views_Source::getFile', array($project.shortname, $commit, $fullpath)} +

{trans 'Archive'} {trans 'Download this file'}

+{/block} +{block javascript} + + +{/block} +{block context} +{include 'idf/source/mtn/branch_tag_list.html'} +{/block} + diff --git a/indefero/src/IDF/templates/idf/source/mtn/help.html b/indefero/src/IDF/templates/idf/source/mtn/help.html new file mode 100644 index 0000000..6b2fd0c --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/mtn/help.html @@ -0,0 +1,34 @@ +{extends "idf/source/base.html"} +{block docclass}yui-t2{assign $inHelp=true}{/block} +{block body} + +

{blocktrans}The team behind {$project} is using +the monotone software to manage the source +code.{/blocktrans}

+ +

{trans 'Command-Line Access'}

+ +

mtn clone {$project.getSourceAccessUrl()}

+ +{if $isOwner or $isMember} +

{trans 'First Commit'}

+ +

{blocktrans}To make a first commit in the repository, perform the following steps:{/blocktrans}

+ +
+mtn setup -b {$project.getConf().getVal('mtn_master_branch', 'your-branch')} .
+mtn add -R .
+mtn commit -m "initial import"
+mtn push {$project.getSourceAccessUrl()}
+
+ +{/if} + +{/block} +{block context} +
+

{blocktrans}Find here more details on how to access {$project} source code.{/blocktrans}

+
+{/block} + + diff --git a/indefero/src/IDF/templates/idf/source/mtn/invalid_revision.html b/indefero/src/IDF/templates/idf/source/mtn/invalid_revision.html new file mode 100644 index 0000000..2b5822e --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/mtn/invalid_revision.html @@ -0,0 +1,2 @@ +{extends "idf/source/invalid_revision.html"} + diff --git a/indefero/src/IDF/templates/idf/source/mtn/tree.html b/indefero/src/IDF/templates/idf/source/mtn/tree.html new file mode 100644 index 0000000..2a77ad3 --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/mtn/tree.html @@ -0,0 +1,71 @@ +{extends "idf/source/base.html"} +{block docclass}yui-t1{assign $inSourceTree=true}{/block} +{block body} +

{trans 'Root'}/{if $breadcrumb}{$breadcrumb|safe}{/if}

+ + + + + + + + + + +{if (!$tree_in and !$tags_in) or $props} +{aurl 'url', 'IDF_Views_Source::commit', array($project.shortname, $commit)} + + {if $props} + + {/if} + {if !$tree_in and !$tags_in} + + {/if} +{/if} + + +{if $base} + + + + + +{/if} +{foreach $files as $file} +{aurl 'url', 'IDF_Views_Source::tree', array($project.shortname, $commit, $file.efullpath)} + + +{if $file.type != 'extern'} +{$file.file}{else}{/if} +{if $file.type == 'blob'} +{if isset($file.date) and $file.log != '----'} + + +{else}{/if} +{/if} +{if $file.type == 'extern'} + +{/if} + +{/foreach} + +
{trans 'File'}{trans 'Age'}{trans 'Message'}{trans 'Size'}
+
    + {foreach $props as $prop => $val} +
  • {blocktrans}Property {$prop} set to {$val}{/blocktrans}
  • + {/foreach} +
+
{blocktrans}Source at commit {$commit} created {$cobject.date|dateago}.{/blocktrans}
+ {blocktrans}By {$cobject.author|strip_tags|trim}, {$cobject.title}{/blocktrans} +
  +..
{$file.type}{$file.file}{$file.date|dateago:"without"}{$file.author|strip_tags|trim}{trans ':'} {issuetext $file.log, $request, true, false}{$file.size|size}{$file.extern}
+{aurl 'url', 'IDF_Views_Source::download', array($project.shortname, $commit)} +

+{trans 'Archive'} {trans 'Download this version'} {trans 'or'} +mtn clone {$project.getSourceAccessUrl($user, $commit)} {trans 'Help'} +

+{/block} +{block context} +{include 'idf/source/mtn/branch_tag_list.html'} +{/block} + diff --git a/indefero/src/IDF/templates/idf/source/svn/changelog.html b/indefero/src/IDF/templates/idf/source/svn/changelog.html new file mode 100644 index 0000000..12287a8 --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/svn/changelog.html @@ -0,0 +1,11 @@ +{extends "idf/source/changelog.html"} +{block context} +
+

{trans 'Revision:'} {$commit}

+

+ + +

+
+{/block} + diff --git a/indefero/src/IDF/templates/idf/source/svn/commit.html b/indefero/src/IDF/templates/idf/source/svn/commit.html new file mode 100644 index 0000000..024f539 --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/svn/commit.html @@ -0,0 +1,11 @@ +{extends "idf/source/commit.html"} +{block context} +
+

{trans 'Revision:'} {$commit}

+

+ + +

+
+{/block} + diff --git a/indefero/src/IDF/templates/idf/source/svn/file.html b/indefero/src/IDF/templates/idf/source/svn/file.html new file mode 100644 index 0000000..4e08bdc --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/svn/file.html @@ -0,0 +1,48 @@ +{extends "idf/source/base.html"} +{block extraheader}{/block} +{block docclass}yui-t1{assign $inSourceTree=true}{/block} +{block body} +

{trans 'Root'}/{if $breadcrumb}{$breadcrumb|safe}{/if}

+ + +{if !$tree_in || $props} + {aurl 'url', 'IDF_Views_Source::commit', array($project.shortname, $commit)} + + {if $props} + + {/if} + {if !$tree_in} + + {/if} + + {/if} + +{$file} + +
+
    + {foreach $props as $prop => $val} +
  • {blocktrans}Property {$prop} set to {$val}{/blocktrans}
  • + {/foreach} +
+
{blocktrans}Source at commit {$commit} created {$cobject.date|dateago}.{/blocktrans}
+ {blocktrans}By {$cobject.author|strip_tags|trim}, {$cobject.title}{/blocktrans} +
+{aurl 'url', 'IDF_Views_Source::getFile', array($project.shortname, $commit, $efullpath)} +

{trans 'Archive'} {trans 'Download this file'}

+ +{/block} +{block context} +
+

{trans 'Revision:'} {$commit}

+

+ + +

+
+{/block} + +{block javascript} + + +{/block} diff --git a/indefero/src/IDF/templates/idf/source/svn/help.html b/indefero/src/IDF/templates/idf/source/svn/help.html new file mode 100644 index 0000000..b6f9caf --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/svn/help.html @@ -0,0 +1,31 @@ +{extends "idf/source/base.html"} +{block docclass}yui-t2{assign $inHelp=true}{/block} +{block body} + +

{blocktrans}The team behind {$project} is using +the subversion software to manage the source +code.{/blocktrans}

+ +

{trans 'Command-Line Access'}

+ +

svn co {$project.getRemoteAccessUrl()}

+ + +{if $isOwner or $isMember} +

{trans 'Write Access Authentication'}

+ +{aurl 'url', 'IDF_Views_User::myAccount'} +

{blocktrans}To get write access to the repository, you need to use your username and your extra password.{/blocktrans}

+ +

svn co {$project.getRemoteAccessUrl()} --username {$user.login}

+ +{/if} + +{/block} +{block context} +
+

{blocktrans}Find here more details on how to access {$project} source code.{/blocktrans}

+
+{/block} + + diff --git a/indefero/src/IDF/templates/idf/source/svn/invalid_revision.html b/indefero/src/IDF/templates/idf/source/svn/invalid_revision.html new file mode 100644 index 0000000..8880b99 --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/svn/invalid_revision.html @@ -0,0 +1,30 @@ +{extends "idf/source/base.html"} +{block docclass}yui-t2{assign $inError=true}{/block} +{block body} + +

{blocktrans}The revision {$commit} is not valid or does not exist +in this repository.{/blocktrans}

+ +{if count($branches) > 0} +

{blocktrans}The following list shows all available branches:{/blocktrans}

+
    +{foreach $branches as $branch => $path} +{if $path}{aurl 'url', 'IDF_Views_Source::tree', array($project.shortname, 'HEAD', $path)} +{else}{aurl 'url', 'IDF_Views_Source::treeBase', array($project.shortname, 'HEAD')}{/if} +
  • + {$branch} +
  • +{/foreach} +
+{/if} + +{if $isOwner or $isMember} +{aurl 'url', 'IDF_Views_Source::help', array($project.shortname)} +

{blocktrans}If this is a new repository, the reason for this error +could be that you have not committed and / or pushed any change so far. +In this case please take a look at the Help page +how to access your repository.{/blocktrans}

+{/if} + +{/block} + diff --git a/indefero/src/IDF/templates/idf/source/svn/tree.html b/indefero/src/IDF/templates/idf/source/svn/tree.html new file mode 100644 index 0000000..fd5d5aa --- /dev/null +++ b/indefero/src/IDF/templates/idf/source/svn/tree.html @@ -0,0 +1,87 @@ +{extends "idf/source/base.html"} +{block docclass}yui-t1{assign $inSourceTree=true}{/block} +{block body} +

{trans 'Root'}/{if $breadcrumb}{$breadcrumb|safe}{/if}

+ + + + + + + + + + + {if (!$tree_in and !$tags_in and $commit != 'HEAD') || $props} + {aurl 'url', 'IDF_Views_Source::commit', array($project.shortname, $commit)} + + {if $props} + + {/if} + {if !$tree_in} + + {/if} + + {/if} + {if $base} + + + + + + {/if} + {foreach $files as $file} + {aurl 'url', 'IDF_Views_Source::tree', array($project.shortname, $commit, $file.efullpath)} + + + + + + + {$file.author|strip_tags|trim}{trans ':'} {issuetext $file.log, $request, true, false} + {if $file.type == 'blob'} + + {/if} + + + {/foreach} + +
{trans 'File'}{trans 'Age'}{trans 'Rev'}{trans 'Message'}{trans 'Size'}
+
    + {foreach $props as $prop => $val} +
  • {blocktrans}Property {$prop} set to {$val}{/blocktrans}
  • + {/foreach} +
+
{blocktrans}Source at commit {$commit} created {$cobject.date|dateago}.{/blocktrans}
+ {blocktrans}By {$cobject.author|strip_tags|trim}, {$cobject.title}{/blocktrans} +
  + ..
{$file.type}{$file.file}{$file.date|dateago:"without"}{$file.rev}{$file.size|size}
+

svn co -r {$commit} {$project.getRemoteAccessUrl()} {trans 'Help'}

+ + +{/block} +{block context} +
+

{trans 'Revision:'} {$commit}

+

+ + +

+
+

{trans 'Branches:'}
+{foreach $branches as $branch => $path} +{if $path}{aurl 'url', 'IDF_Views_Source::tree', array($project.shortname, 'HEAD', $path)} +{else}{aurl 'url', 'IDF_Views_Source::treeBase', array($project.shortname, 'HEAD')}{/if} +{$branch}
+{/foreach} +

+{if $tags} +

{trans 'Tags:'}
+{foreach $tags as $tag => $path} +{aurl 'url', 'IDF_Views_Source::tree', array($project.shortname, 'HEAD', $path)} +{$tag}
+{/foreach} +

+{/if} + +{/block} diff --git a/indefero/src/IDF/templates/idf/tags-cloud.html b/indefero/src/IDF/templates/idf/tags-cloud.html new file mode 100644 index 0000000..cf8478c --- /dev/null +++ b/indefero/src/IDF/templates/idf/tags-cloud.html @@ -0,0 +1,6 @@ +
{foreach $project.getTagCloud($cloud) as $class => $labels} +
{$class}
+{foreach $labels as $idx => $label} +{aurl 'url', $cloud_url, array($project.shortname, $label.id, 'open')} +
{$label.name}{if $idx != count($labels) - 1},{/if}
+{/foreach}{/foreach}
diff --git a/indefero/src/IDF/templates/idf/terms.html b/indefero/src/IDF/templates/idf/terms.html new file mode 100644 index 0000000..7ba6ba7 --- /dev/null +++ b/indefero/src/IDF/templates/idf/terms.html @@ -0,0 +1,25 @@ +

Terms and Conditions

+ +

Legal stuff

+ +
    +
  • Respect others.
  • +
  • You are legally responsible for what you write.
  • +
  • Do not write things you will be ashmed of in 5 years.
  • +
  • We may send you an email from time to time with respect to the use of this service.
  • +
  • We are not going to spam you in any way.
  • +
  • We reserve the right to disable accounts with a non functional email address.
  • +
+ +

Technical stuff

+ +
    +
  • You will need to enable cookies in your browser.
  • +
  • The interface will look nicer with Javascript enabled.
  • +
  • We will send you an email to validate your account.
  • +
+ +

Very important stuff

+ +

You are welcome!

+ diff --git a/indefero/src/IDF/templates/idf/user/changeemail-email.txt b/indefero/src/IDF/templates/idf/user/changeemail-email.txt new file mode 100644 index 0000000..8e9c5a9 --- /dev/null +++ b/indefero/src/IDF/templates/idf/user/changeemail-email.txt @@ -0,0 +1,22 @@ +{blocktrans}Hello {$user}, + +To confirm that you want {$email} +to be your new email address, just follow this link: + +{$url} + +Alternatively, go to this page: + +{$urlik} + +and provide the following verification key: + +{$key} + +If you do not want to change your email address, +just ignore this message. + +Yours faithfully, +The development team. +{/blocktrans} + diff --git a/indefero/src/IDF/templates/idf/user/changeemail.html b/indefero/src/IDF/templates/idf/user/changeemail.html new file mode 100644 index 0000000..3ddb4c7 --- /dev/null +++ b/indefero/src/IDF/templates/idf/user/changeemail.html @@ -0,0 +1,39 @@ +{extends "idf/base-simple.html"} +{block body} +{if $form.errors} +
+

{trans 'Oops, we found an error in the form.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +
+{/if} + +
+ + + + + + + + + +
 {$form.f.key.labelTag}:
+{if $form.f.key.errors}{$form.f.key.fieldErrors}{/if} +{$form.f.key|unsafe} +
  | {trans 'Cancel'} +
+
+{/block} +{block context} +
+

{trans 'Instructions'}

+

{trans 'Use your email software to read your emails and open your verification email. Either click directly on the verification link or copy/paste the verification key in the box and submit the form.'}

+
+{/block} +{block javascript} +{/block} + diff --git a/indefero/src/IDF/templates/idf/user/dashboard.html b/indefero/src/IDF/templates/idf/user/dashboard.html new file mode 100644 index 0000000..584d837 --- /dev/null +++ b/indefero/src/IDF/templates/idf/user/dashboard.html @@ -0,0 +1,17 @@ +{extends "idf/base-simple.html"} +{block body} +{$issues.render} +{/block} +{block context} +{if $nb_owner > 0} +

{trans 'Working issues:'} {$nb_owner}

+{/if} +

{trans 'Submitted issues:'} {$nb_submit}

+{aurl 'url', 'IDF_Views_User::myAccount'} +

{blocktrans}Update your account.{/blocktrans}

+{aurl 'url', 'IDF_Views_User::view', array($user.login)} +

{blocktrans}See your public profile.{/blocktrans}

+{aurl 'url', 'IDF_Views_Issue::forgeWatchList', array('open')} +

{blocktrans}See your forge issue watch list.{/blocktrans}

+{/block} + diff --git a/indefero/src/IDF/templates/idf/user/myaccount.html b/indefero/src/IDF/templates/idf/user/myaccount.html new file mode 100644 index 0000000..4fceeae --- /dev/null +++ b/indefero/src/IDF/templates/idf/user/myaccount.html @@ -0,0 +1,171 @@ +{extends "idf/base-simple.html"} +{block body} +{if $form.errors} +
+

{trans 'Oops, please check the form for errors.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +
+{/if} + +
+ + +{aurl 'url', 'IDF_Views_User::view', array($user.login)} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{trans 'Login:'}{$user.login}
{$form.f.first_name.labelTag}:{if $form.f.first_name.errors}{$form.f.first_name.fieldErrors}{/if} +{$form.f.first_name|unsafe} +
{$form.f.last_name.labelTag}:{if $form.f.last_name.errors}{$form.f.last_name.fieldErrors}{/if} +{$form.f.last_name|unsafe} +
{$form.f.email.labelTag}:{if $form.f.email.errors}{$form.f.email.fieldErrors}{/if} +{$form.f.email|unsafe}
+{$form.f.email.help_text} +
{$form.f.language.labelTag}:{if $form.f.language.errors}{$form.f.language.fieldErrors}{/if} +{$form.f.language|unsafe} +
{$form.f.password.labelTag}:{if $form.f.password.errors}{$form.f.password.fieldErrors}{/if} +{$form.f.password|unsafe}
+{$form.f.password.help_text} +
{$form.f.password2.labelTag}:{if $form.f.password2.errors}{$form.f.password2.fieldErrors}{/if} +{$form.f.password2|unsafe} +
{trans "Public Profile"}
{$form.f.description.labelTag}:{if $form.f.description.errors}{$form.f.description.fieldErrors}{/if} +{$form.f.description|unsafe} +
{$form.f.twitter.labelTag}:{if $form.f.twitter.errors}{$form.f.twitter.fieldErrors}{/if} +{$form.f.twitter|unsafe} +
{$form.f.public_email.labelTag}:{if $form.f.public_email.errors}{$form.f.public_email.fieldErrors}{/if} +{$form.f.public_email|unsafe} +
{$form.f.website.labelTag}:{if $form.f.website.errors}{$form.f.website.fieldErrors}{/if} +{$form.f.website|unsafe} +
{$form.f.custom_avatar.labelTag}:{if $form.f.custom_avatar.errors}{$form.f.custom_avatar.fieldErrors}{/if} +{$form.f.custom_avatar|unsafe}
+{$form.f.custom_avatar.help_text} +
{if $form.f.remove_custom_avatar.errors}{$form.f.remove_custom_avatar.fieldErrors}{/if} +{$form.f.remove_custom_avatar|unsafe} +{$form.f.remove_custom_avatar.labelTag}
+{$form.f.remove_custom_avatar.help_text}
{trans "Key Management"}
{$form.f.public_key.labelTag}:{if $form.f.public_key.errors}{$form.f.public_key.fieldErrors}{/if} +{$form.f.public_key|unsafe}
+{$form.f.public_key.help_text} +
{trans "Secondary Emails"}
{$form.f.secondary_mail.labelTag}:{if $form.f.secondary_mail.errors}{$form.f.secondary_mail.fieldErrors}{/if} +{$form.f.secondary_mail|unsafe}
+{$form.f.secondary_mail.help_text} +
{trans 'Extra password'}:{$ext_pass}
+{trans 'This password is used to access some of the external systems managed by our infrastructure. It will be regenerated if you change your password.'} +
{trans 'API key'}:{$api_key}
+{trans 'Your API key will be regenerated automatically if you change your password.'} +
  | {trans 'Cancel'} +
+
+ +{if count($keys)} + + +{foreach $keys as $key} +{/foreach} +
{trans 'Your Current Public Keys'}
+{$key.showCompact()}
+
+{/if} +{if count($mailaddrs)>1} + + +{foreach $mailaddrs as $mail}{if $mail.id != -1} +{/if}{/foreach} +
{trans 'Your additional email addresses'}
+{$mail.address}
+
+{/if} +{/block} +{block context} +
+

{trans 'If possible, use your real name. By using your real name, people will have more trust in your comments and remarks.'}

+

{trans 'The extra password is used to access some of the external systems and the API key is used to interact with this website using a program.'}

+
{/block} + +{block javascript} +{/block} + diff --git a/indefero/src/IDF/templates/idf/user/passrecovery-ask.html b/indefero/src/IDF/templates/idf/user/passrecovery-ask.html new file mode 100644 index 0000000..dfc3e58 --- /dev/null +++ b/indefero/src/IDF/templates/idf/user/passrecovery-ask.html @@ -0,0 +1,39 @@ +{extends "idf/base-simple.html"} +{block body} +{if $form.errors} +
+

{trans 'Oops, please check the provided login or email address to recover your password.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +
+{/if} + +
+ + + + + + + + + +
{$form.f.account.labelTag}:{if $form.f.account.errors}{$form.f.account.fieldErrors}{/if} +{$form.f.account|unsafe}
+{$form.f.account.help_text} +
  | {trans 'Cancel'} +
+
+{/block} +{block context} +
+

{trans 'Provide either your login or email address, if a corresponding user is found in the database, we will send you an email with the details on how to reset your password.'}

+ +
+{/block} +{block javascript} +{/block} + diff --git a/indefero/src/IDF/templates/idf/user/passrecovery-email.txt b/indefero/src/IDF/templates/idf/user/passrecovery-email.txt new file mode 100644 index 0000000..503fdad --- /dev/null +++ b/indefero/src/IDF/templates/idf/user/passrecovery-email.txt @@ -0,0 +1,25 @@ +{blocktrans}Hello {$user}, + +You lost your password and wanted to recover it. +To provide a new password for your account, you +just have to follow the provided link. You will +get a simple form to provide a new password. + +{$url} + +Alternatively, go to this page: + +{$urlik} + +and provide the following verification key: + +{$key} + +If you are not the one who requested to reset +your password, simply ignore this email, your +password will not be changed. + +Yours faithfully, +The development team. +{/blocktrans} + diff --git a/indefero/src/IDF/templates/idf/user/passrecovery-inputkey.html b/indefero/src/IDF/templates/idf/user/passrecovery-inputkey.html new file mode 100644 index 0000000..a55c6a5 --- /dev/null +++ b/indefero/src/IDF/templates/idf/user/passrecovery-inputkey.html @@ -0,0 +1,40 @@ +{extends "idf/base-simple.html"} +{block body} +{if $form.errors} +
+

{trans 'Oops, we found an error in the form.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +
+{/if} + +
+ + + + + + + + + +
 {$form.f.key.labelTag}:
+{if $form.f.key.errors}{$form.f.key.fieldErrors}{/if} +{$form.f.key|unsafe} +
  | {trans 'Cancel'} +
+
+{/block} +{block context} +
+

{trans 'Instructions'}

+

{trans 'Use your email software to read your emails and open your verification email. Either click directly on the verification link or copy/paste the verification key in the box and submit the form.'}

+

{trans 'Just after providing the confirmation key, you will be able to reset your password and use this website fully.'}

+
+{/block} +{block javascript} +{/block} + diff --git a/indefero/src/IDF/templates/idf/user/passrecovery.html b/indefero/src/IDF/templates/idf/user/passrecovery.html new file mode 100644 index 0000000..7129130 --- /dev/null +++ b/indefero/src/IDF/templates/idf/user/passrecovery.html @@ -0,0 +1,53 @@ +{extends "idf/base-simple.html"} +{block body} +{if $form.errors} +
+

{trans 'Oops, please check the form for errors.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +{if $form.f.key.errors}{$form.f.key.fieldErrors}{/if} +
+{/if} + +
+ + + + + + + + + + + + + + + + + + + + + +
{trans 'Login:'}{$new_user.login}
{trans 'Email:'}{$new_user.email}
{$form.f.password.labelTag}:{if $form.f.password.errors}{$form.f.password.fieldErrors}{/if} +{$form.f.password|unsafe}
+{$form.f.password.help_text} +
{$form.f.password2.labelTag}:{if $form.f.password2.errors}{$form.f.password2.fieldErrors}{/if} +{$form.f.password2|unsafe} +
  | {trans 'Cancel'} +
{$form.f.key|unsafe} +
+{/block} +{block context} +
+

{trans 'This is the last step, but just be sure to have the cookies enabled to log in afterwards.'}

+
+{/block} +{block javascript} +{/block} + diff --git a/indefero/src/IDF/templates/idf/user/public.html b/indefero/src/IDF/templates/idf/user/public.html new file mode 100644 index 0000000..4021211 --- /dev/null +++ b/indefero/src/IDF/templates/idf/user/public.html @@ -0,0 +1,66 @@ +{extends "idf/base-simple.html"} +{block body} + + + + + +{if $user_data.description != ''} + + + + +{/if} +{if $user_data.twitter != ''} + + + + +{/if} +{if $user_data.public_email != ''} + + + + +{/if} +{if $user_data.website != ''} + + + + +{/if} + + + + + + + + + +
{if $user_data.avatar != ''} +  +{else} +  +{/if} +{$member}
{trans 'Description:'}{$user_data.description}
{trans 'Twitter:'}{$user_data.twitter}
{trans 'Public Email:'}{$user_data.public_email}
{trans 'Website:'}{$user_data.website}
{trans 'Last time seen:'}{$member.last_login|dateago}
{trans 'Member since:'}{$member.date_joined|date}
+Projects: + +{foreach $projects as $p} +{if $p.private == 0} + + + +{/if} +{/foreach} +
+{$p.name} - {$p.shortdesc} +
+{/block} +{block context} +
+

{blocktrans}You are looking at the public profile of {$member}.{/blocktrans}

+
+{/block} + + diff --git a/indefero/src/IDF/templates/idf/wiki/base.html b/indefero/src/IDF/templates/idf/wiki/base.html new file mode 100644 index 0000000..ff9ab19 --- /dev/null +++ b/indefero/src/IDF/templates/idf/wiki/base.html @@ -0,0 +1,23 @@ +{extends "idf/base.html"} +{block tabwiki} class="active"{/block} +{block subtabs} +
+{trans 'List Pages'} +{if !$user.isAnonymous()} + | {trans 'List Resources'} + | {trans 'New Page'} + | {trans 'New Resource'} + {if $inPageView} + | {trans 'Update This Page'} + {/if} + {if $inResourceView} + | {trans 'Update This Resource'} + {/if} +{/if} +|
+ + +
+{superblock} +
+{/block} diff --git a/indefero/src/IDF/templates/idf/wiki/createPage.html b/indefero/src/IDF/templates/idf/wiki/createPage.html new file mode 100644 index 0000000..9ef86a5 --- /dev/null +++ b/indefero/src/IDF/templates/idf/wiki/createPage.html @@ -0,0 +1,68 @@ +{extends "idf/wiki/base.html"} +{block docclass}yui-t2{assign $inCreatePage = true}{/block} +{block body} + +{if $preview} +

{trans 'Preview of the Page'}

+ +{markdown $preview, $request} +{/if} + +{if $form.errors} +
+

{trans 'The form contains some errors. Please correct them to create the page.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +
+{/if} + +
+ + + + + + + + + + + + +{if $isOwner or $isMember} + + + +{/if} + + + + +
{$form.f.title.labelTag}:{if $form.f.title.errors}{$form.f.title.fieldErrors}{/if} +{$form.f.title|unsafe}
+{$form.f.title.help_text} +
{$form.f.summary.labelTag}:{if $form.f.summary.errors}{$form.f.summary.fieldErrors}{/if} +{$form.f.summary|unsafe}
+{$form.f.summary.help_text} +
{$form.f.content.labelTag}:{if $form.f.content.errors}{$form.f.content.fieldErrors}{/if} +{$form.f.content|unsafe} +
{$form.f.label1.labelTag}: +{if $form.f.label1.errors}{$form.f.label1.fieldErrors}{/if}{$form.f.label1|unsafe} +{if $form.f.label2.errors}{$form.f.label2.fieldErrors}{/if}{$form.f.label2|unsafe} +{if $form.f.label3.errors}{$form.f.label3.fieldErrors}{/if}{$form.f.label3|unsafe} +
    | {trans 'Cancel'} +
+
+{/block} +{block context} +
+{include 'idf/wiki/edit-info.html'} +
+{/block} +{block javascript} + +{include 'idf/wiki/js-autocomplete.html'}{/block} + diff --git a/indefero/src/IDF/templates/idf/wiki/createResource.html b/indefero/src/IDF/templates/idf/wiki/createResource.html new file mode 100644 index 0000000..8c0e5ec --- /dev/null +++ b/indefero/src/IDF/templates/idf/wiki/createResource.html @@ -0,0 +1,56 @@ +{extends "idf/wiki/base.html"} +{block docclass}yui-t1{assign $inCreateResource = true}{/block} +{block body} + +{if $form.errors} +
+

{trans 'The form contains some errors. Please correct them to create the page.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +
+{/if} + +
+ + + + + + + + + + + + + + + + +
{$form.f.title.labelTag}:{if $form.f.title.errors}{$form.f.title.fieldErrors}{/if} +{$form.f.title|unsafe}
+{$form.f.title.help_text} +
{$form.f.summary.labelTag}:{if $form.f.summary.errors}{$form.f.summary.fieldErrors}{/if} +{$form.f.summary|unsafe}
+{$form.f.summary.help_text} +
{$form.f.file.labelTag}:{if $form.f.file.errors}{$form.f.file.fieldErrors}{/if} +{$form.f.file|unsafe} +
  | {trans 'Cancel'} +
+
+{/block} +{block context} +
+{blocktrans} +Wiki resources are later addressed in wiki pages by their title, so ensure that you +give your resource a unique and an easy to remember name. +{/blocktrans} +
+{/block} +{block javascript} + +{/block} + diff --git a/indefero/src/IDF/templates/idf/wiki/deletePage.html b/indefero/src/IDF/templates/idf/wiki/deletePage.html new file mode 100644 index 0000000..acc21aa --- /dev/null +++ b/indefero/src/IDF/templates/idf/wiki/deletePage.html @@ -0,0 +1,42 @@ +{extends "idf/wiki/base.html"} +{block docclass}yui-t3{assign $inPageView=true}{/block} +{block body} + +

{blocktrans}If you delete this documentation page, it will be removed from the database with all the associated revisions and you will not be able to recover it.{/blocktrans}

+
+ + + + + +
  +{$form.f.confirm|unsafe} {$form.f.confirm.labelTag}
+{if $form.f.confirm.errors}{$form.f.confirm.fieldErrors}{/if} + | {trans 'Cancel'} +
+
+ +

{$page.summary}

+ +{markdown $rev.content, $request} + +{/block} +{block context} +{assign $submitter = $page.get_submitter()} +

{trans 'Created:'} {$page.creation_dtime|dateago}
{blocktrans}by {$submitter}{/blocktrans}

+{if $rev.creation_dtime != $page.creation_dtime}

{assign $submitter = $rev.get_submitter()} +{trans 'Updated:'} {$rev.creation_dtime|dateago}
{blocktrans}by {$submitter}{/blocktrans}

{/if} +{if $tags.count()} +

+{trans 'Labels:'}
+{foreach $tags as $tag} +{$tag.class}:{$tag.name}
+{/foreach} +

{/if} +{if $revs.count() > 0} +

{trans 'Old Revisions'}

+ +{/if} +{/block} diff --git a/indefero/src/IDF/templates/idf/wiki/deletePageRev.html b/indefero/src/IDF/templates/idf/wiki/deletePageRev.html new file mode 100644 index 0000000..1969118 --- /dev/null +++ b/indefero/src/IDF/templates/idf/wiki/deletePageRev.html @@ -0,0 +1,46 @@ +{extends "idf/wiki/base.html"} +{block extraheader}{if $oldrev}{/if}{/block} +{block docclass}yui-t3{assign $inPageView=true}{/block} +{block body} + +{assign $submitter = $oldrev.get_submitter()}{aurl 'url', 'IDF_Views_Wiki::viewPage', array($project.shortname, $page.title)} +
+

{blocktrans}You are looking at an old revision ({$oldrev.summary}) of the page +{$page.title}. This revision was created +by {$submitter}.{/blocktrans}

+
+

{blocktrans}If you delete this old revision, it will be removed from the database and you will not be able to recover it.{/blocktrans}

+
+ + + + + +
  | {trans 'Cancel'} +
+
+ +

{$page.summary}

+ +{markdown $oldrev.content, $request} + +{/block} +{block context} +{assign $submitter = $page.get_submitter()} +

{trans 'Created:'} {$page.creation_dtime|dateago}
{blocktrans}by {$submitter}{/blocktrans}

+{if $rev.creation_dtime != $page.creation_dtime}

{assign $submitter = $rev.get_submitter()} +{trans 'Updated:'} {$rev.creation_dtime|dateago}
{blocktrans}by {$submitter}{/blocktrans}

{/if} +{if $tags.count()} +

+{trans 'Labels:'}
+{foreach $tags as $tag} +{$tag.class}:{$tag.name}
+{/foreach} +

{/if} +{if $revs.count() > 0} +

{trans 'Old Revisions'}

+ +{/if} +{/block} diff --git a/indefero/src/IDF/templates/idf/wiki/deleteResource.html b/indefero/src/IDF/templates/idf/wiki/deleteResource.html new file mode 100644 index 0000000..c229190 --- /dev/null +++ b/indefero/src/IDF/templates/idf/wiki/deleteResource.html @@ -0,0 +1,47 @@ +{extends "idf/wiki/base.html"} +{block docclass}yui-t3{assign $inResourceView=true}{/block} +{block body} + +

{blocktrans}If you delete this documentation resource, it will be removed from the database with all the associated revisions +and you will not be able to recover it. Any documentation pages that reference this resource, +will no longer be able to render it, but won't be deleted.{/blocktrans}

+
+ + + + + +
  +{$form.f.confirm|unsafe} {$form.f.confirm.labelTag}
+{if $form.f.confirm.errors}{$form.f.confirm.fieldErrors}{/if} + | {trans 'Cancel'} +
+
+ +

{$resource.summary}

+ +{assign $preview = $rev.renderRaw()} +{if $preview == ''} + {assign $preview = __('Unable to render preview for this MIME type.')} +{/if} +

{$preview|unsafe}

+ + +{/block} + +{block context} +{assign $submitter = $resource.get_submitter()} +

{trans 'Created:'} {$resource.creation_dtime|dateago}
{blocktrans}by {$submitter}{/blocktrans}

+{if $rev.creation_dtime != $resource.creation_dtime}

{assign $submitter = $rev.get_submitter()} +{trans 'Updated:'} {$rev.creation_dtime|dateago}
{blocktrans}by {$submitter}{/blocktrans}

{/if} +{if $revs.count() > 0} +

{trans 'Old Revisions'}

+ +{/if} +{/block} diff --git a/indefero/src/IDF/templates/idf/wiki/deleteResourceRev.html b/indefero/src/IDF/templates/idf/wiki/deleteResourceRev.html new file mode 100644 index 0000000..aac8ed7 --- /dev/null +++ b/indefero/src/IDF/templates/idf/wiki/deleteResourceRev.html @@ -0,0 +1,49 @@ +{extends "idf/wiki/base.html"} +{block extraheader}{if $oldrev}{/if}{/block} +{block docclass}yui-t3{assign $inResourceView=true}{/block} +{block body} + +{assign $submitter = $oldrev.get_submitter()}{aurl 'url', 'IDF_Views_Wiki::viewResource', array($project.shortname, $resource.title)} +
+

{blocktrans}You are looking at an old revision ({$oldrev.summary}) of the resource +{$resource.title}. This revision was created by {$submitter}.{/blocktrans}

+
+

{blocktrans}If you delete this old revision, it will be removed from the database and you will not be able to recover it.{/blocktrans}

+
+ + + + + +
  | {trans 'Cancel'} +
+
+ +

{$resource.summary}

+ +{assign $preview = $oldrev.renderRaw()} +{if $preview == ''} + {assign $preview = __('Unable to render preview for this MIME type.')} +{/if} +

{$preview|unsafe}

+ + +{/block} + +{/block} +{block context} +{assign $submitter = $resource.get_submitter()} +

{trans 'Created:'} {$resource.creation_dtime|dateago}
{blocktrans}by {$submitter}{/blocktrans}

+{if $oldrev.creation_dtime != $resource.creation_dtime}

{assign $submitter = $oldrev.get_submitter()} +{trans 'Updated:'} {$oldrev.creation_dtime|dateago}
{blocktrans}by {$submitter}{/blocktrans}

{/if} +{if $revs.count() > 0} +

{trans 'Old Revisions'}

+ +{/if} +{/block} diff --git a/indefero/src/IDF/templates/idf/wiki/edit-info.html b/indefero/src/IDF/templates/idf/wiki/edit-info.html new file mode 100644 index 0000000..926926d --- /dev/null +++ b/indefero/src/IDF/templates/idf/wiki/edit-info.html @@ -0,0 +1,10 @@ +{assign $eurl = 'http://michelf.com/projects/php-markdown/extra/'} +{assign $burl = 'http://daringfireball.net/projects/markdown/syntax'} +{aurl 'furl', 'IDF_Views::faq'} +{blocktrans} +

Instructions:

+

The content of the page can use the Markdown syntax with the Extra extension.

+

Website addresses are automatically linked and you can link to another page in the documentation using double square brackets like that [[AnotherPage]].

+

If you want to embed uploaded resources, use the [[!ResourceName]] syntax for that. This is described more in detail in the FAQ.

+

To directly include a file content from the repository, embrace its path with triple square brackets: [[[my/file.txt]]].

+{/blocktrans} diff --git a/indefero/src/IDF/templates/idf/wiki/feedfragment-page.xml b/indefero/src/IDF/templates/idf/wiki/feedfragment-page.xml new file mode 100644 index 0000000..6c0e625 --- /dev/null +++ b/indefero/src/IDF/templates/idf/wiki/feedfragment-page.xml @@ -0,0 +1,11 @@ + + {$title} + + {$url}:{$rev.id} + {$date} + {$rev.get_submitter()} +
+{if !$create}

{trans 'Changes:'} {$rev.summary}:

{/if} +{markdown $rev.content, $request} +
+
diff --git a/indefero/src/IDF/templates/idf/wiki/feedfragment-resource.xml b/indefero/src/IDF/templates/idf/wiki/feedfragment-resource.xml new file mode 100644 index 0000000..2fddefb --- /dev/null +++ b/indefero/src/IDF/templates/idf/wiki/feedfragment-resource.xml @@ -0,0 +1,11 @@ + + {$title} + + {$url}:{$rev.id} + {$date} + {$rev.get_submitter()} +
+{if !$create}

{trans 'Changes:'} {$rev.summary}

+{else}{trans 'Initial creation'}{/if} +
+
diff --git a/indefero/src/IDF/templates/idf/wiki/js-autocomplete.html b/indefero/src/IDF/templates/idf/wiki/js-autocomplete.html new file mode 100644 index 0000000..0d00d55 --- /dev/null +++ b/indefero/src/IDF/templates/idf/wiki/js-autocomplete.html @@ -0,0 +1,27 @@ +{if $isOwner or $isMember} + + + +{/if} diff --git a/indefero/src/IDF/templates/idf/wiki/listPages.html b/indefero/src/IDF/templates/idf/wiki/listPages.html new file mode 100644 index 0000000..8473148 --- /dev/null +++ b/indefero/src/IDF/templates/idf/wiki/listPages.html @@ -0,0 +1,20 @@ +{extends "idf/wiki/base.html"} +{block docclass}yui-t1{assign $inPageList=true}{/block} +{block body} +{$pages.render} +{if !$user.isAnonymous()} +{aurl 'url', 'IDF_Views_Wiki::createPage', array($project.shortname)} +

+ {trans 'New Page'}

{/if} + +{/block} +{block context} +

{trans 'Number of pages:'} {$pages.nb_items}

+{assign $cloud_url = 'IDF_Views_Wiki::listPagesWithLabel'} +{assign $cloud = 'wiki'} +{include 'idf/tags-cloud.html'} +{if $deprecated > 0} +{aurl 'url', 'IDF_Views_Wiki::listPagesWithLabel', array($project.shortname, $dlabel.id)} +

{blocktrans}See the deprecated pages.{/blocktrans}

+{/if} +{/block} + diff --git a/indefero/src/IDF/templates/idf/wiki/listResources.html b/indefero/src/IDF/templates/idf/wiki/listResources.html new file mode 100644 index 0000000..dd7d5f2 --- /dev/null +++ b/indefero/src/IDF/templates/idf/wiki/listResources.html @@ -0,0 +1,12 @@ +{extends "idf/wiki/base.html"} +{block docclass}yui-t1{assign $inResourceList=true}{/block} +{block body} +{$resources.render} +{aurl 'url', 'IDF_Views_Wiki::createResource', array($project.shortname)} +

+ {trans 'New Resource'}

+ +{/block} +{block context} +

{trans 'Number of resources:'} {$resources.nb_items}

+{/block} + diff --git a/indefero/src/IDF/templates/idf/wiki/search.html b/indefero/src/IDF/templates/idf/wiki/search.html new file mode 100644 index 0000000..bc4b468 --- /dev/null +++ b/indefero/src/IDF/templates/idf/wiki/search.html @@ -0,0 +1,13 @@ +{extends "idf/wiki/base.html"} +{block docclass}yui-t1{assign $inWiki=true}{/block} +{block body} +{$pages.render} +{if !$user.isAnonymous()} +{aurl 'url', 'IDF_Views_Wiki::createPage', array($project.shortname)} +

+ {trans 'New Page'}

{/if} + +{/block} +{block context} +

{trans 'Pages found:'} {$pages.nb_items}

+{/block} + diff --git a/indefero/src/IDF/templates/idf/wiki/updatePage.html b/indefero/src/IDF/templates/idf/wiki/updatePage.html new file mode 100644 index 0000000..0533a7a --- /dev/null +++ b/indefero/src/IDF/templates/idf/wiki/updatePage.html @@ -0,0 +1,75 @@ +{extends "idf/wiki/base.html"} +{block docclass}yui-t2{/block} +{block body} + +{if $preview} +

{trans 'Preview of the Page'}

+ +{markdown $preview, $request} +{/if} + +{if $form.errors} +
+

{trans 'The form contains some errors. Please correct them to update the page.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +
+{/if} + +
+{if $isOwner or $isMember} + + + + + + + +{/if} + + + + + + + +{if $isOwner or $isMember} + + + +{/if} + + + + +
{$form.f.title.labelTag}:{if $form.f.title.errors}{$form.f.title.fieldErrors}{/if} +{$form.f.title|unsafe}
+{$form.f.title.help_text} +
{$form.f.summary.labelTag}:{if $form.f.summary.errors}{$form.f.summary.fieldErrors}{/if} +{$form.f.summary|unsafe}
+{$form.f.summary.help_text} +
{$form.f.content.labelTag}:{if $form.f.content.errors}{$form.f.content.fieldErrors}{/if} +{$form.f.content|unsafe} +
{$form.f.comment.labelTag}:{if $form.f.comment.errors}{$form.f.comment.fieldErrors}{/if} +{$form.f.comment|unsafe}
+{$form.f.comment.help_text} +
{$form.f.label1.labelTag}: +{if $form.f.label1.errors}{$form.f.label1.fieldErrors}{/if}{$form.f.label1|unsafe} +{if $form.f.label2.errors}{$form.f.label2.fieldErrors}{/if}{$form.f.label2|unsafe} +{if $form.f.label3.errors}{$form.f.label3.fieldErrors}{/if}{$form.f.label3|unsafe} +
 {* float left is a fix for Firefox < 3.5 *} +   | {trans 'Cancel'}{if $isOwner or $isAdmin or $isMember} +{aurl 'url', 'IDF_Views_Wiki::deletePage', array($project.shortname, $page.id)} +{trans 'Trash'} {trans 'Delete this page'}{/if} +
+
+{/block} +{block context} +
+{include 'idf/wiki/edit-info.html'} +
+{/block} +{block javascript} +{include 'idf/wiki/js-autocomplete.html'}{/block} + diff --git a/indefero/src/IDF/templates/idf/wiki/updateResource.html b/indefero/src/IDF/templates/idf/wiki/updateResource.html new file mode 100644 index 0000000..d93fe39 --- /dev/null +++ b/indefero/src/IDF/templates/idf/wiki/updateResource.html @@ -0,0 +1,46 @@ +{extends "idf/wiki/base.html"} +{block docclass}yui-t2{/block} +{block body} + +{if $form.errors} +
+

{trans 'The form contains some errors. Please correct them to update the page.'}

+{if $form.get_top_errors} +{$form.render_top_errors|unsafe} +{/if} +
+{/if} + +
+ + + + + + + + + + + + + + + + + +
{$form.f.summary.labelTag}:{if $form.f.summary.errors}{$form.f.summary.fieldErrors}{/if} +{$form.f.summary|unsafe}
+{$form.f.summary.help_text} +
{$form.f.file.labelTag}:{if $form.f.file.errors}{$form.f.file.fieldErrors}{/if} +{$form.f.file|unsafe} +
{$form.f.comment.labelTag}:{if $form.f.comment.errors}{$form.f.comment.fieldErrors}{/if} +{$form.f.comment|unsafe}
+{$form.f.comment.help_text} +
 {* float left is a fix for Firefox < 3.5 *} + | {trans 'Cancel'}{if $isOwner or $isAdmin or $isMember} +{aurl 'url', 'IDF_Views_Wiki::deleteResource', array($project.shortname, $resource.id)} +{trans 'Trash'} {trans 'Delete this resource'}{/if} +
+
+{/block} diff --git a/indefero/src/IDF/templates/idf/wiki/viewPage.html b/indefero/src/IDF/templates/idf/wiki/viewPage.html new file mode 100644 index 0000000..43a2cf4 --- /dev/null +++ b/indefero/src/IDF/templates/idf/wiki/viewPage.html @@ -0,0 +1,58 @@ +{extends "idf/wiki/base.html"} + +{block extraheader} +{if !$rev.is_head}{/if} + +{/block} + +{block docclass}yui-t3{assign $inPageView=true}{/block} + +{block body} +{if $deprecated}{* deprecated page *} +
+

{blocktrans}Attention! This page is marked as deprecated, +use it as reference only if you are sure you need these specific information.{/blocktrans}

+
+{/if} +{if !$rev.is_head} +{ashowuser 'submitter', $rev.get_submitter(), $request}{aurl 'url', 'IDF_Views_Wiki::viewPage', array($project.shortname, $page.title)} +
+

{blocktrans}You are looking at an old revision of the page +{$page.title}. This revision was created +by {$submitter}.{/blocktrans}

+
+{/if} + +
+
{trans 'Table of Content'}
+ +

{$page.summary}

+ +{markdown $rev.content, $request} + +{if !$rev.is_head and ($isOwner or $isAdmin)} +{aurl 'url', 'IDF_Views_Wiki::deletePageRev', array($project.shortname, $rev.id)} +

{trans 'Trash'} {trans 'Delete this revision'}

+{/if} + +
+{/block} +{block context} +{ashowuser 'submitter', $page.get_submitter(), $request} +

{trans 'Created:'} {$page.creation_dtime|dateago}
{blocktrans}by {$submitter}{/blocktrans}

+{if $rev.creation_dtime != $page.creation_dtime}

{ashowuser 'submitter', $rev.get_submitter(), $request} +{trans 'Updated:'} {$rev.creation_dtime|dateago}
{blocktrans}by {$submitter}{/blocktrans}

{/if} +{if $tags.count()} +

+{trans 'Labels:'}
+{foreach $tags as $tag} +{$tag.class}:{$tag.name}
+{/foreach} +

{/if} +{if $revs.count() > 0} +

{trans 'Old Revisions'}

+ +{/if} +{/block} diff --git a/indefero/src/IDF/templates/idf/wiki/viewResource.html b/indefero/src/IDF/templates/idf/wiki/viewResource.html new file mode 100644 index 0000000..a41714e --- /dev/null +++ b/indefero/src/IDF/templates/idf/wiki/viewResource.html @@ -0,0 +1,62 @@ +{extends "idf/wiki/base.html"} + +{block extraheader} +{if !$rev.is_head}{/if} +{/block} + +{block docclass}yui-t3{assign $inResourceView=true}{/block} + +{block body} +{if !$rev.is_head} +{ashowuser 'submitter', $rev.get_submitter(), $request}{aurl 'url', 'IDF_Views_Wiki::viewResource', array($project.shortname, $resource.title)} +
+

{blocktrans}You are looking at an old revision of the resource +{$resource.title}. This revision was created +by {$submitter}.{/blocktrans}

+
+{/if} + +
+

{$resource.summary}

+ +{assign $preview = $rev.renderRaw()} +{if $preview == ''} + {assign $preview = __('Unable to render preview for this MIME type.')} +{/if} +

{$preview|unsafe}

+ + + +{if !$rev.is_head and ($isOwner or $isAdmin)} +{aurl 'url', 'IDF_Views_Wiki::deleteResourceRev', array($project.shortname, $rev.id)} +

{trans 'Trash'} {trans 'Delete this revision'}

+{/if} + +

{trans 'Page Usage'}

+{if $pagerevs.count() == 0} +

{trans 'This resource is not used on any pages yet.'}

+{else} + +{/if} +
+{/block} +{block context} +{ashowuser 'submitter', $resource.get_submitter(), $request} +

{trans 'Created:'} {$resource.creation_dtime|dateago}
{blocktrans}by {$submitter}{/blocktrans}

+{if $rev.creation_dtime != $resource.creation_dtime}

{ashowuser 'submitter', $rev.get_submitter(), $request} +{trans 'Updated:'} {$rev.creation_dtime|dateago}
{blocktrans}by {$submitter}{/blocktrans}

{/if} +{if $revs.count() > 0} +

{trans 'Old Revisions'}

+ +{/if} +{/block} diff --git a/indefero/src/IDF/templates/idf/wiki/wiki-created-email.txt b/indefero/src/IDF/templates/idf/wiki/wiki-created-email.txt new file mode 100644 index 0000000..6ce65c7 --- /dev/null +++ b/indefero/src/IDF/templates/idf/wiki/wiki-created-email.txt @@ -0,0 +1,16 @@ +{trans 'Hello,'} + +{blocktrans}A new documentation page has been created:{/blocktrans} + +{$page.title|safe} - {$page.summary|safe} +{trans 'Project:'} {$project.name|safe} +{trans 'Created by:'} {$rev.get_submitter|safe} +{assign $tags = $page.get_tags_list()}{if $tags.count()}{trans 'Labels:'} +{foreach $tags as $tag} {$tag.class|safe}:{$tag.name|safe} +{/foreach}{/if} +{trans 'Content:'} + +{$rev.content} + +-- +{trans 'Documentation page:'} {$url_base}{url 'IDF_Views_Wiki::viewPage', array($project.shortname, $page.title)} diff --git a/indefero/src/IDF/templates/idf/wiki/wiki-updated-email.txt b/indefero/src/IDF/templates/idf/wiki/wiki-updated-email.txt new file mode 100644 index 0000000..4249088 --- /dev/null +++ b/indefero/src/IDF/templates/idf/wiki/wiki-updated-email.txt @@ -0,0 +1,21 @@ +{trans 'Hello,'} + +{blocktrans}The following documentation page has been updated:{/blocktrans} + +{$page.title|safe} - {$page.summary|safe} +{trans 'Project:'} {$project.name|safe} +{trans 'Summary:'} {$rev.summary|safe} +{trans 'Updated by:'} {$page.get_submitter|safe} +{trans 'Created by:'} {$rev.get_submitter|safe} +{assign $tags = $page.get_tags_list()}{if $tags.count()}{trans 'Labels:'} +{foreach $tags as $tag} {$tag.class|safe}:{$tag.name|safe} +{/foreach}{/if}{if $rev.changedRevision()}{trans 'Changes:'} +{foreach $rev.changes as $w => $v} + {if $w == 'su'}{trans 'Summary:'}{/if}{if $w == 'lb'}{trans 'Labels:'}{/if} {if $w == 'lb'}{assign $l = implode(', ', $v)}{$l}{else}{$v}{/if}{/foreach}{/if} + +{trans 'New content:'} + +{$rev.content} + +-- +{trans 'Documentation page:'} {$url_base}{url 'IDF_Views_Wiki::viewPage', array($project.shortname, $page.title)} diff --git a/indefero/src/IDF/version.php b/indefero/src/IDF/version.php new file mode 100644 index 0000000..1f6f8c5 --- /dev/null +++ b/indefero/src/IDF/version.php @@ -0,0 +1,5 @@ + '1.3.3', + 'revision' => 'ebb8d46420ecdd177dcbf4a7c7bd64959ffadbec', +); diff --git a/indefero/www/index.php b/indefero/www/index.php new file mode 100644 index 0000000..8e15573 --- /dev/null +++ b/indefero/www/index.php @@ -0,0 +1,27 @@ + + + + + \ No newline at end of file diff --git a/indefero/www/media/idf/css/prettify.css b/indefero/www/media/idf/css/prettify.css new file mode 100644 index 0000000..2eb91bf --- /dev/null +++ b/indefero/www/media/idf/css/prettify.css @@ -0,0 +1 @@ +.str,.atv{color:#080}.kwd,.tag{color:#008}.com{color:#800}.typ,.atn,.dec{color:#606}.lit{color:#066}.pun{color:#660}.pln{color:#000}pre.prettyprint{padding:2px;border:1px solid #888}@media print{.str{color:#060}.kwd,.tag{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{font-weight:bold}.lit{color:#044}.pun{color:#440}.atn,.typ{color:#404}.atv{color:#060}} \ No newline at end of file diff --git a/indefero/www/media/idf/css/print-wiki.css b/indefero/www/media/idf/css/print-wiki.css new file mode 100644 index 0000000..ba1eb38 --- /dev/null +++ b/indefero/www/media/idf/css/print-wiki.css @@ -0,0 +1,32 @@ +/* +# ***** BEGIN LICENSE BLOCK ***** +# This file is part of InDefero, an open source project management application. +# Copyright (C) 2008-2011 Céondo Ltd and contributors. +# +# InDefero is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# InDefero is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# ***** END LICENSE BLOCK ***** */ + +#hd, #ft, #context { + display: none; +} + +.yui-t3 #yui-main .yui-b { + margin: 0; +} + +#wiki-toc { + float: none; +} diff --git a/indefero/www/media/idf/css/style.css b/indefero/www/media/idf/css/style.css new file mode 100644 index 0000000..30e4524 --- /dev/null +++ b/indefero/www/media/idf/css/style.css @@ -0,0 +1,1398 @@ +/* +# ***** BEGIN LICENSE BLOCK ***** +# This file is part of InDefero, an open source project management application. +# Copyright (C) 2008-2011 Céondo Ltd and contributors. +# +# InDefero is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# InDefero is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# ***** END LICENSE BLOCK ***** */ + +body { + font-family: arial, helvetica, sans-serif; +} + +.top { + margin-top: 5px; +} + +a:link { + color: #00e; +} + +a:visited { + color: #551a8b; +} + +a:active{ + color: #f00; +} + +.yui-g { + padding: 0 1em; +} + +.left { + text-align: left !important; +} + +.right { + text-align: right !important; +} + +.a-c { + text-align: center !important; +} + +.dellink { + float: right; + position: relative; +} + +.dellink a { + color: #a00; +} + +a.userw { + color: #000; +} + +.mono { + font-family: monospace; +} + +.soft { + color: #777; +} + +.soft a { + color: #777; +} + +a.soft { + color: #777; +} + +a.soft:visited { + color: #777; +} + +div.context { + padding-top: 0.5em; + padding-left: 1em; + position: relative; + top: 0; +} + +div.context h3 { + font-size: 13px; + font-weight: bold; + margin: 10px 0 5px; +} + +/** + * Form + */ +form.star { + display: inline; +} + +table.form th, table.form td { + border: none; + vertical-align: top; +} +table.form th { + text-align: right; + font-weight: normal; +} + +table.form td.separator { + font-weight: bold; + text-align: center; +} + +.px-message-error { + padding-left: 37px; + background: url("../img/dialog-error.png"); + background-repeat: no-repeat; + background-position: 3px 0; + color: #c00; + font-weight: bold; + padding-bottom: 5px; +} + +ul.errorlist { + color: #c00; + font-weight: bold; +} + +div.user-messages { + border: 1px solid rgb(229, 225, 169); + background-color: #fffde3; + margin-bottom: 2em; + margin-left: -1px; + width: 100%; +} + +div.theterms { + border: 1px solid rgb(229, 225, 169); + background-color: #fffde3; + padding: 1em 1em 0 1em; +} + + +/** + * Recent issues + */ +table.uploads { + width: 90%; + text-align:center; +} + +table.uploads tr.log { + border-bottom: 1px solid #e7ebe3; +} + +table.uploads th { + background-color: #e4e8E0; + vertical-align: top; + border-color: #d3d7cf; +} + +table.uploads tr { + border-left: 1px solid #d3d7cf; + border-right: 1px solid #d3d7cf; + border-bottom: 1px solid #d3d7cf; +} + +table.uploads td { + border: none; + vertical-align: top; +} + +table.uploads tfoot th { + text-align: right; +} + +table.uploads tfoot th a { + color: #000; + font-weight: normal; +} + +table.uploads th a.px-current-page { + font-weight: bold; + text-decoration: none; +} + +table.recent-issues { + width: 90%; +} + +table.minsize { + width: auto !important; +} + +table.recent-issues tr.log { + border-bottom: 1px solid #e7ebe3; +} + +table.recent-issues th { + background-color: #e4e8E0; + vertical-align: top; + border-color: #d3d7cf; +} + +table.recent-issues tr { + border-left: 1px solid #d3d7cf; + border-right: 1px solid #d3d7cf; + border-bottom: 1px solid #d3d7cf; +} + +table.recent-issues td { + border: none; + vertical-align: top; +} + +table.recent-issues tfoot th { + text-align: right; +} + +table.recent-issues tfoot th a { + color: #000; + font-weight: normal; +} + +table.recent-issues th a.px-current-page { + font-weight: bold; + text-decoration: none; +} + +span.px-sort { + font-weight: normal; + font-size: 70%; + white-space: nowrap; + padding-left: 1em; +} + +span.px-header-title { + white-space: nowrap; +} + +span.px-header-title a, span.px-header-title a:link, span.px-header-title a:visited, span.px-header-title a:active { + color: #000; +} + +dl.tagscloud, +dl.statistics { + margin: 0; + margin-bottom: 1em; +} + +dl.tagscloud dt { + margin-top: .5em; + font-weight: bold; +} + +dl.tagscloud dd { + margin: 0; + display: inline; +} + +dl.statistics dt { + margin-top: .5em; + font-style: italic; +} + +dl.statistics dd { + margin: 0; + float: right; + margin-top: -1.2em; + margin-right: 2em; +} + +/** + * Issue + */ +a.issue-c { + text-decoration: line-through; +} + +pre.issue-comment-text { + font-family: monospace; + line-height: 1.2; /* to be nice also with links */ +} + +div.issue-comment { + border-left: 3px solid #8ae234; + border-bottom: 1px solid #d3d7cf; + border-right: 1px solid #d3d7cf; + padding: 0.5em; +} + +.issue-comment-focus { + border-right: 3px solid #8ae234 !important; +} + +div.issue-comment-first { + border-top: 1px solid #d3d7cf; + clear: both; +} + +div.issue-comment-signin { + -moz-border-radius: 0 0 3px 3px; + -webkit-border-radius: 3px; + -webkit-border-top-left-radius: 0; + -webkit-border-top-right-radius: 0; + background-color: #d3d7cf; + padding: 4px; +} + +div.issue-comment-signin a { + color: #000; +} + +div.issue-changes { + background-color: #d3d7cf; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + padding: 4px; + width: 60%; +} + +div.issue-changes-timeline { + background-color: #eeeeec; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + margin-top: 4px; + padding: 4px; + width: 60%; + color: #888a85; +} + +div.issue-prev-next { + float: right; + margin-top: -1.5em; +} + +div.issue-submit-info { + background-color: #d3d7cf; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + padding: 0.5em; + margin-bottom: 1em; +} + +div.issue-submit-info h2 { + margin-top: 0; +} + +span.label { + color: #204a87; + padding-left: 0.5em; +} + +span.label img { + max-height: 13px; + vertical-align: -10%; +} + +a.label { + color: #204a87; + text-decoration: none; +} + +.label { + color: #204a87; +} + +.nobrk { + white-space: nowrap; +} + +hr { + height: 1px; + border: 0; + background: #e6e6e6; +} + +hr.attach { + visibility: visible; + border: 0; + background-color: #d3d7cf; + color: #d3d7cf; + width: 40%; +} + +textarea { + font-family: monospace; +} + +h1.title { + font-weight: normal; +} + +h1.project-title { + float: right; + font-weight: normal; + margin-top: 0.5em; + margin-bottom: 0; + text-align: right; + z-index: 100; + position: relative; + padding-right: 3px; +} + +h1.project-title img.logo { + max-height: 22px; + vertical-align: text-bottom; + padding-left: 7px; +} + +h1.project-title img.lock { + width: 12px; + position: absolute; + right: 1px; + top: 12px; +} + +.note { + font-size: 80%; +} + +.smaller { + font-size: 90%; +} + +span.active { + font-weight: bold; +} + +.helptext { + font-size: 80%; + color: #555753; + max-width: 600px; + margin-top: 0.25em; + display: inline-block; +} + +div.container { + clear: both; +} + +.sep { + margin: 0 0.3em; +} + +/** + * Tabs + */ +#main-tabs { + line-height: normal; +} + +#main-tabs a { + background-color: #d3d7cf; + -moz-border-radius: 3px 3px 0 0; + -webkit-border-radius: 3px; + -webkit-border-bottom-left-radius: 0; + -webkit-border-bottom-right-radius: 0; + padding: 4px 4px 0 4px; + text-decoration: none; + color: #2e3436; + font-weight: 600; +} + +#main-tabs a.active { + background-color: #a5e26a; +} + +#sub-tabs { + background-color: #a5e26a; + -moz-border-radius: 0 3px 3px 3px; + -webkit-border-radius: 3px; + -webkit-border-top-left-radius: 0; + padding: 4px; +} + +#sub-tabs a { + color: #2e3436; +} + +#sub-tabs a.active { + text-decoration: none; +} +/** + * Tree list + */ +table.tree-list { + width: 100%; +} + +table.tree-list th { + background-color: #e4e8E0; + vertical-align: top; + border-color: #d3d7cf; +} + +table.tree-list tr { + border-left: 1px solid #d3d7cf; + border-right: 1px solid #d3d7cf; + border-bottom: 1px solid #d3d7cf; +} + +table.tree-list td { + border: none; + vertical-align: top; +} + +table.tree-list tfoot th, table.code tfoot th { + text-align: right; + font-weight: normal; +} + +table.tree-list tfoot th a, table.code tfoot th a { + color: #000; + font-weight: normal; +} + +table.tree-list tfoot th ul, table.code tfoot th ul { + text-align: left; + font-size: 85%; +} + +table.tree-list tr.log { + border-bottom: 1px solid #e7ebe3; + /* background-color: #eef2ea !important; */ +} + +table.tree-list tr.extra { +/* border-bottom: 1px solid #e7ebe3; */ +/* background-color: #eef2ea !important; */ +} + +table td.fileicon { + width: 20px; + +} + +/** + * Autocomplete. + */ +.ac_results { + padding: 0px; + border: 1px solid black; + background-color: white; + overflow: hidden; + z-index: 99999; + text-align: left; +} + +.ac_results ul { + width: 100%; + list-style-position: outside; + list-style: none; + padding: 0; + margin: 0; +} + +.ac_results li { + margin: 0px; + padding: 2px 5px; + cursor: default; + display: block; + /* + if width will be 100% horizontal scrollbar will apear + when scroll mode will be used + */ + /*width: 100%;*/ + font: menu; + font-size: 12px; + /* + it is very important, if line-height not setted or setted + in relative units scroll will be broken in firefox + */ + line-height: 16px; + overflow: hidden; +} + +.ac_loading { + background: white url('../img/indicator.gif') right center no-repeat; +} + +.ac_odd { + background-color: #eee; +} + +.ac_over { + background-color: #4e9a06; + color: white; +} + +table.disp th, table.disp td { + border: none; + vertical-align: top; +} + +/** + * Commit + */ +table.commit th, table.commit td { + border: none; + vertical-align: top; +} +table.commit th { + text-align: right; + font-weight: normal; +} +table.commit td, table.commit th { + padding: 3px; +} +table.commit table.changes td { + padding: 2px; +} +table.commit table.changes table.properties { + margin: 0; +} +table.commit table.changes table.properties tr:nth-child(even) { + background: #E4E8E0; +} +table.commit table.changes table.properties td { + white-space: pre-wrap; +} +table.commit table.changes table.properties td.removed { + font-style: italic; +} + +/** + * syntax highlighting of diffs + */ +span.ctrl-char { + color: white; + background: black; + text-align: center; + display: inline-block; + padding: 1px 1px 0px 1px; + margin-left: 1px; + margin-right: 1px; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + cursor: default; +} + +/* special formatting for the TAB character: make it wider, so it is rendered more properly */ +span.ctrl-char[title="0x09"] { + width: 24px; +} + +/* override any prettify css rule */ +span.ctrl-char > * { + color: white; +} + +table.diff { + width: 100%; + table-layout: fixed; +} + +table.diff td { + border: none; + vertical-align: top; + padding: 0; +} + +table.diff.unified > tbody > tr > td + td, +table.diff.context > tbody > tr > td + td + td + td { + border-right: 1px solid #d3d7cf; +} + +table.diff th { + background-color: #e4e8E0; + vertical-align: top; + border-color: #d3d7cf; +} + +table.diff div.scroll { + overflow: auto; +} + +table.diff-contents td, +table.diff-linecounts td { + vertical-align: top; + border-color: inherit; + padding: 0; +} + +table.diff-contents td.next, +table.diff-linecounts td.next { + background-color: #e4e8E0; + vertical-align: top; + text-align: right; + border-color: #d3d7cf; + padding: 1px 10px; +} + +table.diff-linecounts { + margin: 0; +} + +table.diff-contents { + border-bottom: 1px solid #d3d7cf; + width: 100%; + margin: 0; +} + +table.diff-linecounts tr, +table.diff-contents tr { + height: 22px; +} + +table.diff-linecounts tr { + border: 1px solid #d3d7cf; +} + +table.diff-linecounts tr:first-child { + border-top: 0px; +} + +table.diff-linecounts td { + line-height: 12px; + font-size: 90%; + padding: 2px 10px; + text-align: right; + border-left: 1px solid #d3d7cf; +} + +table.diff-linecounts.left-hidden tr > td:first-child, +table.diff-linecounts.right-hidden tr > td + td { + display: none; +} + +table.diff-contents td { + line-height: 12px; + padding: 2px; + font-size: 90%; + border: none; + white-space: pre; +} + +table.diff-contents td.added { + background-color: #dfd; +} + +table.diff-contents td.removed { + background-color: #fdd; +} + +table.diff-contents td > span.ctrl-char { + visibility: hidden; +} + +table.diff-contents td:hover > span.ctrl-char { + visibility: visible; +} + +table.diff-contents td.added > span.ctrl-char { + background: #0A0; +} + +table.diff-contents td.removed > span.ctrl-char { + background: #A00; +} + +/** + * view file content + */ +table.code { + border-bottom: 1px solid #d3d7cf; + border-top: 1px solid #d3d7cf; + width: 100%; +} + +table.code th { + background-color: #e4e8E0; + vertical-align: top; + border-color: #d3d7cf; +} + +table.code tr { + border-left: 1px solid #d3d7cf; + border-right: 1px solid #d3d7cf; + border-bottom: none; + border-top: none; +} + +table.code td { + font-size: 90%; + vertical-align: top; + padding: 1px; + border-color: inherit; +} + +table.code td.code { + border: none; + /* Whitespace hacking from: http://ln.hixie.ch/ */ + white-space: pre; /* CSS2 */ + white-space: -moz-pre-wrap; /* Mozilla */ + white-space: -hp-pre-wrap; /* HP printers */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: pre-wrap; /* CSS 2.1 */ + word-wrap: break-word; /* IE */ + padding-left: 5px; +} + +table.code td.code span.ctrl-char { + visibility: hidden; +} + +table.code td.code:hover span.ctrl-char { + visibility: visible; +} + +table.code td.code-lc { + text-align: right; + padding: 1px 5px; + border-color: inherit; + border-top: 1px solid #d3d7cf; + border-bottom: 1px solid #d3d7cf; + width: 3em; +} + +table.code td.code-lc a { + color: #555753; + text-decoration: none; +} + +/** + * Download + */ +div.download-file { + padding: 1em 1em 1em 3em; + background: url("../img/down-large.png"); + background-repeat: no-repeat; + background-position: 1em 1em; + font-size: 140%; + margin-bottom: 1.5em; + background-color: #bbe394; + width: 40%; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; +} + +table.download { + margin-top: 1.5em; +} + +/** + * Wiki + */ +p.desc { + background-color: #eeeeec; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + padding: 4px; + width: 60%; +} + +p.preview img { + max-width: 60%; +} + +p.preview iframe { + width: 60%; + height: 300px; +} + +div.old-rev { + padding: 1em 1em 0.1em 1em; + margin-bottom: 1em; + background-color: #bbe394; + width: 40%; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; +} + +div.deprecated-page { + padding: 1em 1em 0.1em 3em; + margin-bottom: 1em; + background: url("../img/warning-large.png"); + background-repeat: no-repeat; + background-position: 1em 1em; + font-size: 120%; + background-color: #bbe394; + width: 40%; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; +} + +li.old-rev { + font-style: italic; +} + +.delp { + float: right; + position: relative; +} + +.delp a { + color: #a00; +} + +ul > li { + list-style: disc outside none; +} + +ol > li { + list-style: decimal outside none; +} + +#branding { + float: right; + position: relative; + margin-right: -10px; + margin-bottom: 10px; + width: 115px; + font-size: 8px; + text-align: right; + padding-right: 20px; + padding-left: 0px; + background-color: #eeeeec; + -moz-border-radius: 3px 0 0 3px; + -webkit-border-radius: 3px; + -webkit-border-top-right-radius: 0; + -webkit-border-bottom-right-radius: 0; + color: #888a85; + clear: both; + background-image: url("../img/ceondo.png"); + background-repeat: no-repeat; + background-position: top right; +} + +#branding a { + color: #777; +} + +#branding a:visited { + color: #777; +} + +#ft { + padding: 0px; + margin: 0px; +} + +#wiki-toc { + float: right; + margin-left: 10px; + margin-bottom: 10px; + max-width: 33%; +} + +#wiki-toc-content { + border: 1px solid #999999; + border-width: 1px 0; + padding: 10px 0; + padding-bottom: 15px; + background-color: #ffffff; + display: block; +} + +#wiki-toc-content a { + display: block; + margin-top: 0.5em; + font-size: 90%; +} + +#wiki-toc-content a:first-child { + margin-top: 0; +} + +#wiki-toc-content a.wiki-h2 { + margin-left: 1em; +} + +#wiki-toc-content a.wiki-h3 { + margin-left: 2em; +} + +.resource-container { + border: 1px solid #EEE; + padding: 5px; +} + +.resource-container + * { + clear: both; +} + +.resource-container .preview { + margin-bottom: 5px; +} + +.resource-container .preview * { + width: 100%; + height: 100%; +} + +.resource-container .preview img { + height: auto; +} + +.resource-container .preview + .title { + font-size: 80%; +} + +.resource-container .title * { + vertical-align: middle; +} + +.resource-container .title .download { + display: inline-block; + margin-right: 5px; + background: url("../img/down-large.png") no-repeat; + width: 22px; + height: 22px; +} + +/** + * main menu + */ +#main-menu { + padding: 0; + margin: 5px 0 13px; +} + +#main-menu > li { + list-style-type: none; + margin-left: 5px; + padding-left: 5px; + border-left: 1px solid black; + display: inline-block; + line-height: 1em; +} + +#main-menu > li:first-child { + margin-left: 0; + padding-left: 0; + border-left: none; +} + +/** + * project list popup + */ +#project-list { + position: relative; + padding-left: 0 !important; +} + +#project-list > a { + padding-left: 5px; + padding-right: 5px; + margin-top: -3px; + padding-top: 3px; +} + +#project-list + li { + margin-left: 0; +} + +#project-list ul { + display: none; + background: #A5E26A; + border-top: 0; + position: absolute; + margin: 0; + z-index: 1000; + top: 1.1em; + -moz-border-radius: 0 0 3px 3px; + border-radius: 0 0 3px 3px; + -moz-box-shadow: 0 10px 20px #333; + -webkit-box-shadow: 0 10px 20px #333; + box-shadow: 0 10px 20px #333; + max-height: 400px; + min-width: 100%; + overflow-x: hidden; + overflow-y: auto; +} + +#project-list ul li { + margin: 7px; + white-space: nowrap; + font-size: 0.95em; + list-style-type: none; + position: relative; +} + +#project-list ul li img.logo { + max-height: 16px; + vertical-align: text-bottom; + padding-right: 5px; +} + +#project-list ul li img.lock { + position: absolute; + width: 9px; + left: 9px; + top: 9px; +} + +#project-list ul li:first-child { + margin-top: 10px; +} + +#project-list ul li a { + text-decoration: none; +} + +#project-list:hover > a { + background: #A5E26A; + text-decoration: none; +} + +#project-list:hover a { + color: #2E3436; +} + +/** + * List expander for tag and branch view + */ +.context > .expander { + position: relative; + overflow: hidden; + background: white; +} + +.context > .expander > ul { + margin: 5px; +} + +.context > .expander > ul > li { + white-space: nowrap; + list-style-type: none; +} + +.context > .expander > ul > li.active { + font-weight: bold; +} + +.context > .expander > .gradient { + position: absolute; + right: 0; + width: 20px; + height: 100%; + z-index: 998; + background: url(../img/white_gradient.png) repeat-y; +} + +.context > .expander:hover, +.context > .expander.activated { + position: absolute; + z-index: 999; + overflow: visible; + -moz-border-radius: 0 10px 10px 0; + -webkit-border-radius: 0 10px 10px 0; + border-radius: 0 10px 10px 0; + -moz-box-shadow: 3px 3px 5px #333; + -webkit-box-shadow: 3px 3px 5px #333; + box-shadow: 3px 3px 5px #333; + padding: 5px 10px; + margin: -5px -10px; + min-width: 180px; +} + +.context > .expander:hover > .gradient, +.context > .expander.activated > .gradient { + display: none; +} + +.context > .expander span.input-with-delete { + padding: 1px; + border: 1px dotted #474747; + display: none; + float: right; + margin-left: 10px; + margin-top: -3px; +} + +.context > .expander span.input-with-delete * { + vertical-align: middle; +} + +.context > .expander span.input-with-delete span { + display: inline-block; + width: 13px; + height: 12px; + background: url(../img/clear.png) left top no-repeat; + cursor: pointer; +} + +.context > .expander span.input-with-delete input.filter-list { + font-size: 11px; + font-weight: normal; + color: #333; + border: 0; + width: 100px; + height: 11px; +} + +.context > .expander:hover span.input-with-delete.activated, +.context > .expander.activated span.input-with-delete.activated { + display: block; +} + +.context > .expander div.input-with-delete.default { + opacity: 0.5; +} + +/** + * SCM action icons in the commit view + */ +span.scm-action { + display: inline-block; + line-height: 9px; + font-size: 9px; + text-align: center; + padding: 2px; + width: 9px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; + color: white; + cursor: default; + margin-top: 2px; +} + +span.scm-action.added { + background-color: darkgreen; +} + +span.scm-action.deleted { + background-color: darkred; +} + +span.scm-action.patched { + background-color: orange; +} + +span.scm-action.renamed { + background-color: purple; +} + +span.scm-action.copied { + background-color: orchid; +} + +span.scm-action.property-changed { + background-color: blue; +} + +/* + * Stats on index + */ +#stats > h3 { + text-decoration : underline; +} + +#stats table tr td { + border-style: none; +} + +#stats td { + padding: .2em; +} + +/* + * Project list + */ +div.p-list-prj { + width: 24em; + min-height: 5em; + float: left; + margin: 0 1em 0.5em 0; +} + +div.p-list-prj div.logo { + float: left; + width: 32px; + height: 32px; + position: relative; +} + +div.p-list-prj div.logo img { + max-width: 32px; + max-height: 32px; +} + +div.p-list-prj div.logo .private { + top: 18px; + right: -3px; + position: absolute; +} + +div.p-list-prj div.logo .activity { + height: 4px; + width: 32px; + margin-top: 5px; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + border-radius: 2px; + background: #E6E6E6; +} + +div.p-list-prj div.logo .activity .bar { + background: #A5E26A; + height: 100%; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + border-radius: 2px; +} + +div.p-list-prj p { + margin: 0; + margin-left: 42px; +} + +div.p-list-prj .smaller { + font-size: 85%; +} + +a.external-link { + background: url(../img/external_link.png) no-repeat right center; + padding-right: 15px; + text-decoration: none; +} + +/* + * Issue summary + */ +div.issue-summary { + float: left; + width: 50%; +} + +div.issue-summary > div { + margin-right: 3em; + padding-top: 1em; +} + +div.issue-summary h2 { + border-bottom: 1px solid #A5E26A; +} + +table.issue-summary { + width: 100%; +} + +table.issue-summary tr td { + border: 0; + padding: .1em .005em; +} + +table.issue-summary td.graph { + width: 60%; +} + +table.issue-summary td.count { + text-align: right; + padding-right: .5em; +} + +table.graph { + width: 100%; + margin: 0; + padding: 0; +} + +table.issue-summary td.graph-color { + background: #3C78B5; +} + +table.issue-summary td.graph-percent { + padding-left: 1em; +} + +table.form.access-rights {} + +table.form.access-rights th + th, +table.form.access-rights td + td { + padding-left: 1em; +} + +table.form.access-rights td + td label { + padding-right: 0.5em; +} + +table.form.access-rights th *, +table.form.access-rights td * { + vertical-align: middle; +} diff --git a/indefero/www/media/idf/css/yui.css b/indefero/www/media/idf/css/yui.css new file mode 100644 index 0000000..4bca9c4 --- /dev/null +++ b/indefero/www/media/idf/css/yui.css @@ -0,0 +1,9 @@ +/* +Copyright (c) 2008, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.net/yui/license.txt +version: 2.5.1 +*/ +html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym {border:0;font-variant:normal;}sup {vertical-align:text-top;}sub {vertical-align:text-bottom;}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}input,textarea,select{*font-size:100%;}legend{color:#000;}body {font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}table {font-size:inherit;font:100%;}pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;} +body{text-align:center;}#ft{clear:both;}#doc,#doc2,#doc3,#doc4,.yui-t1,.yui-t2,.yui-t3,.yui-t4,.yui-t5,.yui-t6,.yui-t7{margin:auto;text-align:left;width:57.69em;*width:56.25em;min-width:750px;}#doc2{width:73.076em;*width:71.25em;}#doc3{margin:auto 10px;width:auto;}#doc4{width:74.923em;*width:73.05em;}.yui-b{position:relative;}.yui-b{_position:static;}#yui-main .yui-b{position:static;}#yui-main{width:100%;}.yui-t1 #yui-main,.yui-t2 #yui-main,.yui-t3 #yui-main{float:right;margin-left:-25em;}.yui-t4 #yui-main,.yui-t5 #yui-main,.yui-t6 #yui-main{float:left;margin-right:-25em;}.yui-t1 .yui-b{float:left;width:12.30769em;*width:12.00em;}.yui-t1 #yui-main .yui-b{margin-left:13.30769em;*margin-left:13.05em;}.yui-t2 .yui-b{float:left;width:13.8461em;*width:13.50em;}.yui-t2 #yui-main .yui-b{margin-left:20em;*margin-left:14.55em;}.yui-t3 .yui-b{float:left;width:23.0769em;*width:22.50em;}.yui-t3 #yui-main .yui-b{margin-left:24.0769em;*margin-left:23.62em;}.yui-t4 .yui-b{float:right;width:13.8456em;*width:13.50em;}.yui-t4 #yui-main .yui-b{margin-right:14.8456em;*margin-right:14.55em;}.yui-t5 .yui-b{float:right;width:18.4615em;*width:18.00em;}.yui-t5 #yui-main .yui-b{margin-right:19.4615em;*margin-right:19.125em;}.yui-t6 .yui-b{float:right;width:23.0769em;*width:22.50em;}.yui-t6 #yui-main .yui-b{margin-right:24.0769em;*margin-right:23.62em;}.yui-t7 #yui-main .yui-b{display:block;margin:0 0 1em 0;}#yui-main .yui-b{float:none;width:auto;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf,.yui-gc .yui-u,.yui-gd .yui-g,.yui-g .yui-gc .yui-u,.yui-ge .yui-u,.yui-ge .yui-g,.yui-gf .yui-g,.yui-gf .yui-u{float:right;}.yui-g div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first,.yui-ge div.first,.yui-gf div.first,.yui-g .yui-gc div.first,.yui-g .yui-ge div.first,.yui-gc div.first div.first{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf{width:49.1%;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{width:32%;margin-left:1.99%;}.yui-gb .yui-u{*margin-left:1.9%;*width:31.9%;}.yui-gc div.first,.yui-gd .yui-u{width:66%;}.yui-gd div.first{width:32%;}.yui-ge div.first,.yui-gf .yui-u{width:74.2%;}.yui-ge .yui-u,.yui-gf div.first{width:24%;}.yui-g .yui-gb div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first{margin-left:0;}.yui-g .yui-g .yui-u,.yui-gb .yui-g .yui-u,.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u,.yui-ge .yui-g .yui-u,.yui-gf .yui-g .yui-u{width:49%;*width:48.1%;*margin-left:0;}.yui-g .yui-gb div.first,.yui-gb .yui-gb div.first{*margin-right:0;*width:32%;_width:31.7%;}.yui-g .yui-gc div.first,.yui-gd .yui-g{width:66%;}.yui-gb .yui-g div.first{*margin-right:4%;_margin-right:1.3%;}.yui-gb .yui-gc div.first,.yui-gb .yui-gd div.first{*margin-right:0;}.yui-gb .yui-gb .yui-u,.yui-gb .yui-gc .yui-u{*margin-left:1.8%;_margin-left:4%;}.yui-g .yui-gb .yui-u{_margin-left:1.0%;}.yui-gb .yui-gd .yui-u{*width:66%;_width:61.2%;}.yui-gb .yui-gd div.first{*width:31%;_width:29.5%;}.yui-g .yui-gc .yui-u,.yui-gb .yui-gc .yui-u{width:32%;_float:right;margin-right:0;_margin-left:0;}.yui-gb .yui-gc div.first{width:66%;*float:left;*margin-left:0;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf .yui-u{margin:0;}.yui-gb .yui-gb .yui-u{_margin-left:.7%;}.yui-gb .yui-g div.first,.yui-gb .yui-gb div.first{*margin-left:0;}.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u{*width:48.1%;*margin-left:0;}s .yui-gb .yui-gd div.first{width:32%;}.yui-g .yui-gd div.first{_width:29.9%;}.yui-ge .yui-g{width:24%;}.yui-gf .yui-g{width:74.2%;}.yui-gb .yui-ge div.yui-u,.yui-gb .yui-gf div.yui-u{float:right;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf div.first{float:left;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf div.first{*width:24%;_width:20%;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf .yui-u{*width:73.5%;_width:65.5%;}.yui-ge div.first .yui-gd .yui-u{width:65%;}.yui-ge div.first .yui-gd div.first{width:32%;}#bd:after,.yui-g:after,.yui-gb:after,.yui-gc:after,.yui-gd:after,.yui-ge:after,.yui-gf:after{content:".";display:block;height:0;clear:both;visibility:hidden;}#bd,.yui-g,.yui-gb,.yui-gc,.yui-gd,.yui-ge,.yui-gf{zoom:1;} +h1{font-size:138.5%;}h2{font-size:123.1%;}h3{font-size:108%;}h1,h2,h3{margin:1em 0;}h1,h2,h3,h4,h5,h6,strong{font-weight:bold;}abbr,acronym{border-bottom:1px dotted #000;cursor:help;} em{font-style:italic;}blockquote,ul,ol,dl{margin:1em;}ol,ul,dl{margin-left:2em;}ol li{list-style:decimal outside;}ul li{list-style:disc outside;}dl dd{margin-left:1em;}th,td{border:1px solid #000;padding:.5em;}th{font-weight:bold;text-align:center;}caption{margin-bottom:.5em;text-align:center;}p,fieldset,table,pre{margin-bottom:1em;} diff --git a/indefero/www/media/idf/img/add.png b/indefero/www/media/idf/img/add.png new file mode 100644 index 0000000..1aa7f09 Binary files /dev/null and b/indefero/www/media/idf/img/add.png differ diff --git a/indefero/www/media/idf/img/attachment.png b/indefero/www/media/idf/img/attachment.png new file mode 100644 index 0000000..529bb7f Binary files /dev/null and b/indefero/www/media/idf/img/attachment.png differ diff --git a/indefero/www/media/idf/img/blob.png b/indefero/www/media/idf/img/blob.png new file mode 100644 index 0000000..2d7f2d6 Binary files /dev/null and b/indefero/www/media/idf/img/blob.png differ diff --git a/indefero/www/media/idf/img/ceondo.png b/indefero/www/media/idf/img/ceondo.png new file mode 100644 index 0000000..7499ed6 Binary files /dev/null and b/indefero/www/media/idf/img/ceondo.png differ diff --git a/indefero/www/media/idf/img/clear.png b/indefero/www/media/idf/img/clear.png new file mode 100644 index 0000000..11079dd Binary files /dev/null and b/indefero/www/media/idf/img/clear.png differ diff --git a/indefero/www/media/idf/img/day.png b/indefero/www/media/idf/img/day.png new file mode 100644 index 0000000..7dc15ea Binary files /dev/null and b/indefero/www/media/idf/img/day.png differ diff --git a/indefero/www/media/idf/img/dialog-error.png b/indefero/www/media/idf/img/dialog-error.png new file mode 100644 index 0000000..7d6aaf6 Binary files /dev/null and b/indefero/www/media/idf/img/dialog-error.png differ diff --git a/indefero/www/media/idf/img/down-large.png b/indefero/www/media/idf/img/down-large.png new file mode 100644 index 0000000..af23788 Binary files /dev/null and b/indefero/www/media/idf/img/down-large.png differ diff --git a/indefero/www/media/idf/img/extern.png b/indefero/www/media/idf/img/extern.png new file mode 100644 index 0000000..55c0f0d Binary files /dev/null and b/indefero/www/media/idf/img/extern.png differ diff --git a/indefero/www/media/idf/img/external_link.png b/indefero/www/media/idf/img/external_link.png new file mode 100644 index 0000000..ef6ca95 Binary files /dev/null and b/indefero/www/media/idf/img/external_link.png differ diff --git a/indefero/www/media/idf/img/favicon.png b/indefero/www/media/idf/img/favicon.png new file mode 100644 index 0000000..51c91e4 Binary files /dev/null and b/indefero/www/media/idf/img/favicon.png differ diff --git a/indefero/www/media/idf/img/help.png b/indefero/www/media/idf/img/help.png new file mode 100644 index 0000000..f25fc3f Binary files /dev/null and b/indefero/www/media/idf/img/help.png differ diff --git a/indefero/www/media/idf/img/home.png b/indefero/www/media/idf/img/home.png new file mode 100644 index 0000000..13d2c00 Binary files /dev/null and b/indefero/www/media/idf/img/home.png differ diff --git a/indefero/www/media/idf/img/indicator.gif b/indefero/www/media/idf/img/indicator.gif new file mode 100644 index 0000000..085ccae Binary files /dev/null and b/indefero/www/media/idf/img/indicator.gif differ diff --git a/indefero/www/media/idf/img/lock.png b/indefero/www/media/idf/img/lock.png new file mode 100644 index 0000000..0466619 Binary files /dev/null and b/indefero/www/media/idf/img/lock.png differ diff --git a/indefero/www/media/idf/img/night.png b/indefero/www/media/idf/img/night.png new file mode 100644 index 0000000..4345752 Binary files /dev/null and b/indefero/www/media/idf/img/night.png differ diff --git a/indefero/www/media/idf/img/no_logo.png b/indefero/www/media/idf/img/no_logo.png new file mode 100644 index 0000000..43e72e3 Binary files /dev/null and b/indefero/www/media/idf/img/no_logo.png differ diff --git a/indefero/www/media/idf/img/package-grey.png b/indefero/www/media/idf/img/package-grey.png new file mode 100644 index 0000000..6abb01f Binary files /dev/null and b/indefero/www/media/idf/img/package-grey.png differ diff --git a/indefero/www/media/idf/img/package.png b/indefero/www/media/idf/img/package.png new file mode 100644 index 0000000..9015426 Binary files /dev/null and b/indefero/www/media/idf/img/package.png differ diff --git a/indefero/www/media/idf/img/powered-by-indefero.png b/indefero/www/media/idf/img/powered-by-indefero.png new file mode 100644 index 0000000..318cbf4 Binary files /dev/null and b/indefero/www/media/idf/img/powered-by-indefero.png differ diff --git a/indefero/www/media/idf/img/rss.png b/indefero/www/media/idf/img/rss.png new file mode 100644 index 0000000..7e204b4 Binary files /dev/null and b/indefero/www/media/idf/img/rss.png differ diff --git a/indefero/www/media/idf/img/spacer.gif b/indefero/www/media/idf/img/spacer.gif new file mode 100644 index 0000000..ef3c30b Binary files /dev/null and b/indefero/www/media/idf/img/spacer.gif differ diff --git a/indefero/www/media/idf/img/star-grey.png b/indefero/www/media/idf/img/star-grey.png new file mode 100644 index 0000000..20339ac Binary files /dev/null and b/indefero/www/media/idf/img/star-grey.png differ diff --git a/indefero/www/media/idf/img/star.png b/indefero/www/media/idf/img/star.png new file mode 100644 index 0000000..96156b1 Binary files /dev/null and b/indefero/www/media/idf/img/star.png differ diff --git a/indefero/www/media/idf/img/start.png b/indefero/www/media/idf/img/start.png new file mode 100644 index 0000000..a7de0fe Binary files /dev/null and b/indefero/www/media/idf/img/start.png differ diff --git a/indefero/www/media/idf/img/trash.png b/indefero/www/media/idf/img/trash.png new file mode 100644 index 0000000..0e0953c Binary files /dev/null and b/indefero/www/media/idf/img/trash.png differ diff --git a/indefero/www/media/idf/img/tree.png b/indefero/www/media/idf/img/tree.png new file mode 100644 index 0000000..901edc9 Binary files /dev/null and b/indefero/www/media/idf/img/tree.png differ diff --git a/indefero/www/media/idf/img/warning-large.png b/indefero/www/media/idf/img/warning-large.png new file mode 100644 index 0000000..45b64a7 Binary files /dev/null and b/indefero/www/media/idf/img/warning-large.png differ diff --git a/indefero/www/media/idf/img/warning.png b/indefero/www/media/idf/img/warning.png new file mode 100644 index 0000000..a9e4ff3 Binary files /dev/null and b/indefero/www/media/idf/img/warning.png differ diff --git a/indefero/www/media/idf/img/white_gradient.png b/indefero/www/media/idf/img/white_gradient.png new file mode 100644 index 0000000..667bc00 Binary files /dev/null and b/indefero/www/media/idf/img/white_gradient.png differ diff --git a/indefero/www/media/idf/js/jquery-1.7.2.min.js b/indefero/www/media/idf/js/jquery-1.7.2.min.js new file mode 100644 index 0000000..5627896 --- /dev/null +++ b/indefero/www/media/idf/js/jquery-1.7.2.min.js @@ -0,0 +1,4 @@ +/*! jQuery v1.7.2 jquery.com | jquery.org/license */ +(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cu(a){if(!cj[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),b.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write((f.support.boxModel?"":"")+""),cl.close();d=cl.createElement(a),cl.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ck)}cj[a]=e}return cj[a]}function ct(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function cs(){cq=b}function cr(){setTimeout(cs,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){if(c!=="border")for(;e=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?+d:j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){if(typeof c!="string"||!c)return null;var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c
a",d=p.getElementsByTagName("*"),e=p.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=p.getElementsByTagName("input")[0],b={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:p.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,pixelMargin:!0},f.boxModel=b.boxModel=c.compatMode==="CSS1Compat",i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete p.test}catch(r){b.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",function(){b.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),i.setAttribute("name","t"),p.appendChild(i),j=c.createDocumentFragment(),j.appendChild(p.lastChild),b.checkClone=j.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,j.removeChild(i),j.appendChild(p);if(p.attachEvent)for(n in{submit:1,change:1,focusin:1})m="on"+n,o=m in p,o||(p.setAttribute(m,"return;"),o=typeof p[m]=="function"),b[n+"Bubbles"]=o;j.removeChild(p),j=g=h=p=i=null,f(function(){var d,e,g,h,i,j,l,m,n,q,r,s,t,u=c.getElementsByTagName("body")[0];!u||(m=1,t="padding:0;margin:0;border:",r="position:absolute;top:0;left:0;width:1px;height:1px;",s=t+"0;visibility:hidden;",n="style='"+r+t+"5px solid #000;",q="
"+""+"
",d=c.createElement("div"),d.style.cssText=s+"width:0;height:0;position:static;top:0;margin-top:"+m+"px",u.insertBefore(d,u.firstChild),p=c.createElement("div"),d.appendChild(p),p.innerHTML="
t
",k=p.getElementsByTagName("td"),o=k[0].offsetHeight===0,k[0].style.display="",k[1].style.display="none",b.reliableHiddenOffsets=o&&k[0].offsetHeight===0,a.getComputedStyle&&(p.innerHTML="",l=c.createElement("div"),l.style.width="0",l.style.marginRight="0",p.style.width="2px",p.appendChild(l),b.reliableMarginRight=(parseInt((a.getComputedStyle(l,null)||{marginRight:0}).marginRight,10)||0)===0),typeof p.style.zoom!="undefined"&&(p.innerHTML="",p.style.width=p.style.padding="1px",p.style.border=0,p.style.overflow="hidden",p.style.display="inline",p.style.zoom=1,b.inlineBlockNeedsLayout=p.offsetWidth===3,p.style.display="block",p.style.overflow="visible",p.innerHTML="
",b.shrinkWrapBlocks=p.offsetWidth!==3),p.style.cssText=r+s,p.innerHTML=q,e=p.firstChild,g=e.firstChild,i=e.nextSibling.firstChild.firstChild,j={doesNotAddBorder:g.offsetTop!==5,doesAddBorderForTableAndCells:i.offsetTop===5},g.style.position="fixed",g.style.top="20px",j.fixedPosition=g.offsetTop===20||g.offsetTop===15,g.style.position=g.style.top="",e.style.overflow="hidden",e.style.position="relative",j.subtractsBorderForOverflowNotVisible=g.offsetTop===-5,j.doesNotIncludeMarginInBodyOffset=u.offsetTop!==m,a.getComputedStyle&&(p.style.marginTop="1%",b.pixelMargin=(a.getComputedStyle(p,null)||{marginTop:0}).marginTop!=="1%"),typeof d.style.zoom!="undefined"&&(d.style.zoom=1),u.removeChild(d),l=p=d=null,f.extend(b,j))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e1,null,!1)},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){var d=2;typeof a!="string"&&(c=a,a="fx",d--);if(arguments.length1)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,f.prop,a,b,arguments.length>1)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.type]||f.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.type]||f.valHooks[g.nodeName.toLowerCase()];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h,i=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;i=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/(?:^|\s)hover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function( +a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler,g=p.selector),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;le&&j.push({elem:this,matches:d.slice(e)});for(k=0;k0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));o.match.globalPOS=p;var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h0)for(h=g;h=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/]","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div
","
"]),f.fn.extend({text:function(a){return f.access(this,function(a){return a===b?f.text(this):this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f +.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){return f.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1>");try{for(;d1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||f.isXMLDoc(a)||!bc.test("<"+a.nodeName+">")?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g,h,i,j=[];b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);for(var k=0,l;(l=a[k])!=null;k++){typeof l=="number"&&(l+="");if(!l)continue;if(typeof l=="string")if(!_.test(l))l=b.createTextNode(l);else{l=l.replace(Y,"<$1>");var m=(Z.exec(l)||["",""])[1].toLowerCase(),n=bg[m]||bg._default,o=n[0],p=b.createElement("div"),q=bh.childNodes,r;b===c?bh.appendChild(p):U(b).appendChild(p),p.innerHTML=n[1]+l+n[2];while(o--)p=p.lastChild;if(!f.support.tbody){var s=$.test(l),t=m==="table"&&!s?p.firstChild&&p.firstChild.childNodes:n[1]===""&&!s?p.childNodes:[];for(i=t.length-1;i>=0;--i)f.nodeName(t[i],"tbody")&&!t[i].childNodes.length&&t[i].parentNode.removeChild(t[i])}!f.support.leadingWhitespace&&X.test(l)&&p.insertBefore(b.createTextNode(X.exec(l)[0]),p.firstChild),l=p.childNodes,p&&(p.parentNode.removeChild(p),q.length>0&&(r=q[q.length-1],r&&r.parentNode&&r.parentNode.removeChild(r)))}var u;if(!f.support.appendChecked)if(l[0]&&typeof (u=l.length)=="number")for(i=0;i1)},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=by(a,"opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bu.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(by)return by(a,c)},swap:function(a,b,c){var d={},e,f;for(f in b)d[f]=a.style[f],a.style[f]=b[f];e=c.call(a);for(f in b)a.style[f]=d[f];return e}}),f.curCSS=f.css,c.defaultView&&c.defaultView.getComputedStyle&&(bz=function(a,b){var c,d,e,g,h=a.style;b=b.replace(br,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b))),!f.support.pixelMargin&&e&&bv.test(b)&&bt.test(c)&&(g=h.width,h.width=c,c=e.width,h.width=g);return c}),c.documentElement.currentStyle&&(bA=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f==null&&g&&(e=g[b])&&(f=e),bt.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),by=bz||bA,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0?bB(a,b,d):f.swap(a,bw,function(){return bB(a,b,d)})},set:function(a,b){return bs.test(b)?b+"px":b}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bq.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bp,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bp.test(g)?g.replace(bp,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){return f.swap(a,{display:"inline-block"},function(){return b?by(a,"margin-right"):a.style.marginRight})}})}),f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)}),f.each({margin:"",padding:"",border:"Width"},function(a,b){f.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bx[d]+b]=e[d]||e[d-2]||e[0];return f}}});var bC=/%20/g,bD=/\[\]$/,bE=/\r?\n/g,bF=/#.*$/,bG=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bH=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bI=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bJ=/^(?:GET|HEAD)$/,bK=/^\/\//,bL=/\?/,bM=/)<[^<]*)*<\/script>/gi,bN=/^(?:select|textarea)/i,bO=/\s+/,bP=/([?&])_=[^&]*/,bQ=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bR=f.fn.load,bS={},bT={},bU,bV,bW=["*/"]+["*"];try{bU=e.href}catch(bX){bU=c.createElement("a"),bU.href="",bU=bU.href}bV=bQ.exec(bU.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bR)return bR.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
").append(c.replace(bM,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bN.test(this.nodeName)||bH.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bE,"\r\n")}}):{name:b.name,value:c.replace(bE,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b$(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b$(a,b);return a},ajaxSettings:{url:bU,isLocal:bI.test(bV[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bW},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bY(bS),ajaxTransport:bY(bT),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?ca(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cb(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bG.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bF,"").replace(bK,bV[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bO),d.crossDomain==null&&(r=bQ.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bV[1]&&r[2]==bV[2]&&(r[3]||(r[1]==="http:"?80:443))==(bV[3]||(bV[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bZ(bS,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bJ.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bL.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bP,"$1_="+x);d.url=y+(y===d.url?(bL.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bW+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bZ(bT,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join("&").replace(bC,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cc++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=typeof b.data=="string"&&/^application\/x\-www\-form\-urlencoded/.test(b.contentType);if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n);try{m.text=h.responseText}catch(a){}try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,co,cp=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cq;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(ct("show",3),a,b,c);for(var g=0,h=this.length;g=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);f.fn[a]=function(e){return f.access(this,function(a,e,g){var h=cy(a);if(g===b)return h?c in h?h[c]:f.support.boxModel&&h.document.documentElement[e]||h.document.body[e]:a[e];h?h.scrollTo(d?f(h).scrollLeft():g,d?g:f(h).scrollTop()):a[e]=g},a,e,arguments.length,null)}}),f.each({Height:"height",Width:"width"},function(a,c){var d="client"+a,e="scroll"+a,g="offset"+a;f.fn["inner"+a]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,c,"padding")):this[c]():null},f.fn["outer"+a]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,c,a?"margin":"border")):this[c]():null},f.fn[c]=function(a){return f.access(this,function(a,c,h){var i,j,k,l;if(f.isWindow(a)){i=a.document,j=i.documentElement[d];return f.support.boxModel&&j||i.body&&i.body[d]||j}if(a.nodeType===9){i=a.documentElement;if(i[d]>=i[e])return i[d];return Math.max(a.body[e],i[e],a.body[g],i[g])}if(h===b){k=f.css(a,c),l=parseFloat(k);return f.isNumeric(l)?l:k}f(a).css(c,h)},c,a,arguments.length,null)}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window); diff --git a/indefero/www/media/idf/js/jquery.autocomplete.min.js b/indefero/www/media/idf/js/jquery.autocomplete.min.js new file mode 100644 index 0000000..c9ddfb2 --- /dev/null +++ b/indefero/www/media/idf/js/jquery.autocomplete.min.js @@ -0,0 +1,15 @@ +/* + * Autocomplete - jQuery plugin 1.0.2 + * + * Copyright (c) 2007 Dylan Verheul, Dan G. Switzer, Anjesh Tuladhar, Jörn Zaefferer + * + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + * Revision: $Id: jquery.autocomplete.js 5747 2008-06-25 18:30:55Z joern.zaefferer $ + * + */;(function($){$.fn.extend({autocomplete:function(urlOrData,options){var isUrl=typeof urlOrData=="string";options=$.extend({},$.Autocompleter.defaults,{url:isUrl?urlOrData:null,data:isUrl?null:urlOrData,delay:isUrl?$.Autocompleter.defaults.delay:10,max:options&&!options.scroll?10:150},options);options.highlight=options.highlight||function(value){return value;};options.formatMatch=options.formatMatch||options.formatItem;return this.each(function(){new $.Autocompleter(this,options);});},result:function(handler){return this.bind("result",handler);},search:function(handler){return this.trigger("search",[handler]);},flushCache:function(){return this.trigger("flushCache");},setOptions:function(options){return this.trigger("setOptions",[options]);},unautocomplete:function(){return this.trigger("unautocomplete");}});$.Autocompleter=function(input,options){var KEY={UP:38,DOWN:40,DEL:46,TAB:9,RETURN:13,ESC:27,COMMA:188,PAGEUP:33,PAGEDOWN:34,BACKSPACE:8};var $input=$(input).attr("autocomplete","off").addClass(options.inputClass);var timeout;var previousValue="";var cache=$.Autocompleter.Cache(options);var hasFocus=0;var lastKeyPressCode;var config={mouseDownOnSelect:false};var select=$.Autocompleter.Select(options,input,selectCurrent,config);var blockSubmit;$.browser.opera&&$(input.form).bind("submit.autocomplete",function(){if(blockSubmit){blockSubmit=false;return false;}});$input.bind(($.browser.opera?"keypress":"keydown")+".autocomplete",function(event){lastKeyPressCode=event.keyCode;switch(event.keyCode){case KEY.UP:event.preventDefault();if(select.visible()){select.prev();}else{onChange(0,true);}break;case KEY.DOWN:event.preventDefault();if(select.visible()){select.next();}else{onChange(0,true);}break;case KEY.PAGEUP:event.preventDefault();if(select.visible()){select.pageUp();}else{onChange(0,true);}break;case KEY.PAGEDOWN:event.preventDefault();if(select.visible()){select.pageDown();}else{onChange(0,true);}break;case options.multiple&&$.trim(options.multipleSeparator)==","&&KEY.COMMA:case KEY.TAB:case KEY.RETURN:if(selectCurrent()){event.preventDefault();blockSubmit=true;return false;}break;case KEY.ESC:select.hide();break;default:clearTimeout(timeout);timeout=setTimeout(onChange,options.delay);break;}}).focus(function(){hasFocus++;}).blur(function(){hasFocus=0;if(!config.mouseDownOnSelect){hideResults();}}).click(function(){if(hasFocus++>1&&!select.visible()){onChange(0,true);}}).bind("search",function(){var fn=(arguments.length>1)?arguments[1]:null;function findValueCallback(q,data){var result;if(data&&data.length){for(var i=0;i1){v=words.slice(0,words.length-1).join(options.multipleSeparator)+options.multipleSeparator+v;}v+=options.multipleSeparator;}$input.val(v);hideResultsNow();$input.trigger("result",[selected.data,selected.value]);return true;}function onChange(crap,skipPrevCheck){if(lastKeyPressCode==KEY.DEL){select.hide();return;}var currentValue=$input.val();if(!skipPrevCheck&¤tValue==previousValue)return;previousValue=currentValue;currentValue=lastWord(currentValue);if(currentValue.length>=options.minChars){$input.addClass(options.loadingClass);if(!options.matchCase)currentValue=currentValue.toLowerCase();request(currentValue,receiveData,hideResultsNow);}else{stopLoading();select.hide();}};function trimWords(value){if(!value){return[""];}var words=value.split(options.multipleSeparator);var result=[];$.each(words,function(i,value){if($.trim(value))result[i]=$.trim(value);});return result;}function lastWord(value){if(!options.multiple)return value;var words=trimWords(value);return words[words.length-1];}function autoFill(q,sValue){if(options.autoFill&&(lastWord($input.val()).toLowerCase()==q.toLowerCase())&&lastKeyPressCode!=KEY.BACKSPACE){$input.val($input.val()+sValue.substring(lastWord(previousValue).length));$.Autocompleter.Selection(input,previousValue.length,previousValue.length+sValue.length);}};function hideResults(){clearTimeout(timeout);timeout=setTimeout(hideResultsNow,200);};function hideResultsNow(){var wasVisible=select.visible();select.hide();clearTimeout(timeout);stopLoading();if(options.mustMatch){$input.search(function(result){if(!result){if(options.multiple){var words=trimWords($input.val()).slice(0,-1);$input.val(words.join(options.multipleSeparator)+(words.length?options.multipleSeparator:""));}else +$input.val("");}});}if(wasVisible)$.Autocompleter.Selection(input,input.value.length,input.value.length);};function receiveData(q,data){if(data&&data.length&&hasFocus){stopLoading();select.display(data,q);autoFill(q,data[0].value);select.show();}else{hideResultsNow();}};function request(term,success,failure){if(!options.matchCase)term=term.toLowerCase();var data=cache.load(term);if(data&&data.length){success(term,data);}else if((typeof options.url=="string")&&(options.url.length>0)){var extraParams={timestamp:+new Date()};$.each(options.extraParams,function(key,param){extraParams[key]=typeof param=="function"?param():param;});$.ajax({mode:"abort",port:"autocomplete"+input.name,dataType:options.dataType,url:options.url,data:$.extend({q:lastWord(term),limit:options.max},extraParams),success:function(data){var parsed=options.parse&&options.parse(data)||parse(data);cache.add(term,parsed);success(term,parsed);}});}else{select.emptyList();failure(term);}};function parse(data){var parsed=[];var rows=data.split("\n");for(var i=0;i]*)("+term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi,"\\$1")+")(?![^<>]*>)(?![^&;]+;)","gi"),"$1");},scroll:true,scrollHeight:180};$.Autocompleter.Cache=function(options){var data={};var length=0;function matchSubset(s,sub){if(!options.matchCase)s=s.toLowerCase();var i=s.indexOf(sub);if(i==-1)return false;return i==0||options.matchContains;};function add(q,value){if(length>options.cacheLength){flush();}if(!data[q]){length++;}data[q]=value;}function populate(){if(!options.data)return false;var stMatchSets={},nullData=0;if(!options.url)options.cacheLength=1;stMatchSets[""]=[];for(var i=0,ol=options.data.length;i0){var c=data[k];$.each(c,function(i,x){if(matchSubset(x.value,q)){csub.push(x);}});}}return csub;}else +if(data[q]){return data[q];}else +if(options.matchSubset){for(var i=q.length-1;i>=options.minChars;i--){var c=data[q.substr(0,i)];if(c){var csub=[];$.each(c,function(i,x){if(matchSubset(x.value,q)){csub[csub.length]=x;}});return csub;}}}return null;}};};$.Autocompleter.Select=function(options,input,select,config){var CLASSES={ACTIVE:"ac_over"};var listItems,active=-1,data,term="",needsInit=true,element,list;function init(){if(!needsInit)return;element=$("
").hide().addClass(options.resultsClass).css("position","absolute").appendTo(document.body);list=$("
    ").appendTo(element).mouseover(function(event){if(target(event).nodeName&&target(event).nodeName.toUpperCase()=='LI'){active=$("li",list).removeClass(CLASSES.ACTIVE).index(target(event));$(target(event)).addClass(CLASSES.ACTIVE);}}).click(function(event){$(target(event)).addClass(CLASSES.ACTIVE);select();input.focus();return false;}).mousedown(function(){config.mouseDownOnSelect=true;}).mouseup(function(){config.mouseDownOnSelect=false;});if(options.width>0)element.css("width",options.width);needsInit=false;}function target(event){var element=event.target;while(element&&element.tagName!="LI")element=element.parentNode;if(!element)return[];return element;}function moveSelect(step){listItems.slice(active,active+1).removeClass(CLASSES.ACTIVE);movePosition(step);var activeItem=listItems.slice(active,active+1).addClass(CLASSES.ACTIVE);if(options.scroll){var offset=0;listItems.slice(0,active).each(function(){offset+=this.offsetHeight;});if((offset+activeItem[0].offsetHeight-list.scrollTop())>list[0].clientHeight){list.scrollTop(offset+activeItem[0].offsetHeight-list.innerHeight());}else if(offset=listItems.size()){active=0;}}function limitNumberOfItems(available){return options.max&&options.max").html(options.highlight(formatted,term)).addClass(i%2==0?"ac_even":"ac_odd").appendTo(list)[0];$.data(li,"ac_data",data[i]);}listItems=list.find("li");if(options.selectFirst){listItems.slice(0,1).addClass(CLASSES.ACTIVE);active=0;}if($.fn.bgiframe)list.bgiframe();}return{display:function(d,q){init();data=d;term=q;fillList();},next:function(){moveSelect(1);},prev:function(){moveSelect(-1);},pageUp:function(){if(active!=0&&active-8<0){moveSelect(-active);}else{moveSelect(-8);}},pageDown:function(){if(active!=listItems.size()-1&&active+8>listItems.size()){moveSelect(listItems.size()-1-active);}else{moveSelect(8);}},hide:function(){element&&element.hide();listItems&&listItems.removeClass(CLASSES.ACTIVE);active=-1;},visible:function(){return element&&element.is(":visible");},current:function(){return this.visible()&&(listItems.filter("."+CLASSES.ACTIVE)[0]||options.selectFirst&&listItems[0]);},show:function(){var offset=$(input).offset();element.css({width:typeof options.width=="string"||options.width>0?options.width:$(input).width(),top:offset.top+input.offsetHeight,left:offset.left}).show();if(options.scroll){list.scrollTop(0);list.css({maxHeight:options.scrollHeight,overflow:'auto'});if($.browser.msie&&typeof document.body.style.maxHeight==="undefined"){var listHeight=0;listItems.each(function(){listHeight+=this.offsetHeight;});var scrollbarsVisible=listHeight>options.scrollHeight;list.css('height',scrollbarsVisible?options.scrollHeight:listHeight);if(!scrollbarsVisible){listItems.width(list.width()-parseInt(listItems.css("padding-left"))-parseInt(listItems.css("padding-right")));}}}},selected:function(){var selected=listItems&&listItems.filter("."+CLASSES.ACTIVE).removeClass(CLASSES.ACTIVE);return selected&&selected.length&&$.data(selected[0],"ac_data");},emptyList:function(){list&&list.empty();},unbind:function(){element&&element.remove();}};};$.Autocompleter.Selection=function(field,start,end){if(field.createTextRange){var selRange=field.createTextRange();selRange.collapse(true);selRange.moveStart("character",start);selRange.moveEnd("character",end);selRange.select();}else if(field.setSelectionRange){field.setSelectionRange(start,end);}else{if(field.selectionStart){field.selectionStart=start;field.selectionEnd=end;}}field.focus();};})(jQuery); \ No newline at end of file diff --git a/indefero/www/media/idf/js/jquery.bgiframe.min.js b/indefero/www/media/idf/js/jquery.bgiframe.min.js new file mode 100644 index 0000000..7faef4b --- /dev/null +++ b/indefero/www/media/idf/js/jquery.bgiframe.min.js @@ -0,0 +1,10 @@ +/* Copyright (c) 2006 Brandon Aaron (http://brandonaaron.net) + * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) + * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. + * + * $LastChangedDate: 2007-07-22 01:45:56 +0200 (Son, 22 Jul 2007) $ + * $Rev: 2447 $ + * + * Version 2.1.1 + */ +(function($){$.fn.bgIframe=$.fn.bgiframe=function(s){if($.browser.msie&&/6.0/.test(navigator.userAgent)){s=$.extend({top:'auto',left:'auto',width:'auto',height:'auto',opacity:true,src:'javascript:false;'},s||{});var prop=function(n){return n&&n.constructor==Number?n+'px':n;},html='
    + + + '; + } + + /** + * Get the form data from the reCaptcha fields. + * + * We need to get back two fields from the POST request + * 'recaptcha_challenge_field' and 'recaptcha_response_field'. + * + * They are hardcoded, so we do not even bother checking something + * else. + * + * @param string Name of the form + * @param array Submitted form data + * @return array Challenge and answer + */ + public function valueFromFormData($name, $data) + { + $res = array('', ''); + $res[0] = isset($data['recaptcha_challenge_field']) + ? $data['recaptcha_challenge_field'] : ''; + $res[1] = isset($data['recaptcha_response_field']) + ? $data['recaptcha_response_field'] : ''; + return $res; + } +} diff --git a/pluf/src/Pluf/Form/Widget/SelectInput.php b/pluf/src/Pluf/Form/Widget/SelectInput.php new file mode 100644 index 0000000..ef4d55f --- /dev/null +++ b/pluf/src/Pluf/Form/Widget/SelectInput.php @@ -0,0 +1,78 @@ +choices = $attrs['choices']; + unset($attrs['choices']); + parent::__construct($attrs); + } + + /** + * Renders the HTML of the input. + * + * @param string Name of the field. + * @param mixed Value for the field, can be a non valid value. + * @param array Extra attributes to add to the input form (array()) + * @param array Extra choices (array()) + * @return string The HTML string of the input. + */ + public function render($name, $value, $extra_attrs=array(), + $choices=array()) + { + $output = array(); + if ($value === null) { + $value = ''; + } + $final_attrs = $this->buildAttrs(array('name' => $name), $extra_attrs); + $output[] = ''; + $groups = $this->choices + $choices; + foreach($groups as $option_group => $c) { + if (!is_array($c)) { + $subchoices = array($option_group => $c); + } else { + $output[] = ''; + $subchoices = $c; + } + foreach ($subchoices as $option_label=>$option_value) { + $selected = ($option_value == $value) ? ' selected="selected"':''; + $output[] = sprintf('', + htmlspecialchars($option_value, ENT_COMPAT, 'UTF-8'), + $selected, + htmlspecialchars($option_label, ENT_COMPAT, 'UTF-8')); + } + if (is_array($c)) { + $output[] = ''; + } + } + $output[] = ''; + return new Pluf_Template_SafeString(implode("\n", $output), true); + } +} diff --git a/pluf/src/Pluf/Form/Widget/SelectMultipleInput.php b/pluf/src/Pluf/Form/Widget/SelectMultipleInput.php new file mode 100644 index 0000000..ae83801 --- /dev/null +++ b/pluf/src/Pluf/Form/Widget/SelectMultipleInput.php @@ -0,0 +1,79 @@ +choices = $attrs['choices']; + unset($attrs['choices']); + parent::__construct($attrs); + } + + /** + * Renders the HTML of the input. + * + * @param string Name of the field. + * @param array Value for the field, can be a non valid value. + * @param array Extra attributes to add to the input form (array()) + * @param array Extra choices (array()) + * @return string The HTML string of the input. + */ + public function render($name, $value, $extra_attrs=array(), + $choices=array()) + { + $output = array(); + if ($value === null) { + $value = array(); + } + $final_attrs = $this->buildAttrs(array('name' => $name.'[]'), + $extra_attrs); + $output[] = ''; + return new Pluf_Template_SafeString(implode("\n", $output), true); + } + + public function valueFromFormData($name, $data) + { + if (isset($data[$name]) and is_array($data[$name])) { + return $data[$name]; + } + return null; + } + +} \ No newline at end of file diff --git a/pluf/src/Pluf/Form/Widget/SelectMultipleInput/Checkbox.php b/pluf/src/Pluf/Form/Widget/SelectMultipleInput/Checkbox.php new file mode 100644 index 0000000..db522cb --- /dev/null +++ b/pluf/src/Pluf/Form/Widget/SelectMultipleInput/Checkbox.php @@ -0,0 +1,74 @@ +buildAttrs($extra_attrs); + $output[] = '
      '; + $choices = array_merge($this->choices, $choices); + $i=0; + $base_id = $final_attrs['id']; + foreach ($choices as $option_label=>$option_value) { + + $final_attrs['id'] = $base_id.'_'.$i; + $final_attrs['value'] = htmlspecialchars($option_value, ENT_COMPAT, 'UTF-8'); + $checkbox = new Pluf_Form_Widget_CheckboxInput($final_attrs); + $rendered = $checkbox->render($name.'[]', in_array($option_value, $value)); + + $output[] = sprintf('
    • ', $rendered, + htmlspecialchars($option_label, ENT_COMPAT, 'UTF-8')); + $i++; + } + $output[] = '
    '; + return new Pluf_Template_SafeString(implode("\n", $output), true); + } + + public function idForLabel($id) + { + if ($id) { + $id += '_0'; + } + return $id; + } + + +} \ No newline at end of file diff --git a/pluf/src/Pluf/Form/Widget/TextInput.php b/pluf/src/Pluf/Form/Widget/TextInput.php new file mode 100644 index 0000000..90995f5 --- /dev/null +++ b/pluf/src/Pluf/Form/Widget/TextInput.php @@ -0,0 +1,30 @@ +attrs = array_merge(array('cols' => '40', 'rows' => '10'), + $attrs); + } + + /** + * Renders the HTML of the input. + * + * @param string Name of the field. + * @param mixed Value for the field, can be a non valid value. + * @param array Extra attributes to add to the input form (array()) + * @return string The HTML string of the input. + */ + public function render($name, $value, $extra_attrs=array()) + { + if ($value === null) $value = ''; + $final_attrs = $this->buildAttrs(array('name' => $name), + $extra_attrs); + return new Pluf_Template_SafeString( + sprintf('%s', + Pluf_Form_Widget_Attrs($final_attrs), + htmlspecialchars($value, ENT_COMPAT, 'UTF-8')), + true); + } +} \ No newline at end of file diff --git a/pluf/src/Pluf/Form/Widget/TinyMCEInput.php b/pluf/src/Pluf/Form/Widget/TinyMCEInput.php new file mode 100644 index 0000000..51a0ddf --- /dev/null +++ b/pluf/src/Pluf/Form/Widget/TinyMCEInput.php @@ -0,0 +1,98 @@ + '70', + 'rows' => '20'); + $config = array('tinymce_url', 'mode', 'theme', 'include_tinymce'); + foreach ($config as $cfg) { + if (isset($attrs[$cfg])) { + $this->$cfg = $attrs[$cfg]; + unset($attrs[$cfg]); + } + } + $this->attrs = array_merge($defaults, $attrs); + } + + /** + * Renders the HTML of the input. + * + * @param string Name of the field. + * @param mixed Value for the field, can be a non valid value. + * @param array Extra attributes to add to the input form (array()) + * @return string The HTML string of the input. + */ + public function render($name, $value, $extra_attrs=array()) + { + if ($value === null) $value = ''; + $extra_config = ''; + if (isset($this->attrs['editor_config'])) { + $_ec = $this->attrs['editor_config']; + unset($this->attrs['editor_config']); + $_st = array(); + foreach ($_ec as $key=>$val) { + if (is_bool($val)) { + if ($val) { + $_st[] = $key.' : true'; + } else { + $_st[] = $key.' : false'; + } + } else { + $_st[] = $key.' : "'.$val.'"'; + } + } + if ($_st) { + $extra_config = ",\n".implode(",\n", $_st); + } + } + $final_attrs = $this->buildAttrs(array('name' => $name), + $extra_attrs); + // The special include for tinyMCE + $out = ''; + if ($this->include_tinymce) { + $out .= ''."\n"; + } + $out .=''; + return new Pluf_Template_SafeString( + $out.sprintf('%s', + Pluf_Form_Widget_Attrs($final_attrs), + htmlspecialchars($value, ENT_COMPAT, 'UTF-8')), + true); + } +} \ No newline at end of file diff --git a/pluf/src/Pluf/Group.php b/pluf/src/Pluf/Group.php new file mode 100644 index 0000000..63fa776 --- /dev/null +++ b/pluf/src/Pluf/Group.php @@ -0,0 +1,90 @@ +_a['verbose'] = __('group'); + $this->_a['table'] = 'groups'; + $this->_a['model'] = 'Pluf_Group'; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + //It is automatically added. + 'blank' => true, + ), + 'name' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 50, + 'verbose' => __('name'), + ), + 'description' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 250, + 'verbose' => __('description'), + ), + 'permissions' => + array( + 'type' => 'Pluf_DB_Field_Manytomany', + 'blank' => true, + 'model' => 'Pluf_Permission', + ), + ); + if (Pluf::f('pluf_custom_group',false)) $this->extended_init(); + } + + /** + * Hook for extended class + */ + function extended_init() + { + return; + } + + function __toString() + { + return $this->name; + } + + /** + * Predelete to drop the row level permissions. + */ + function preDelete() + { + if (Pluf::f('pluf_use_rowpermission', false)) { + $_rpt = Pluf::factory('Pluf_RowPermission')->getSqlTable(); + $sql = new Pluf_SQL('owner_class=%s AND owner_id=%s', + array($this->_a['model'], $this->_data['id'])); + $this->_con->execute('DELETE FROM '.$_rpt.' WHERE '.$sql->gen()); + } + } +} diff --git a/pluf/src/Pluf/HTTP.php b/pluf/src/Pluf/HTTP.php new file mode 100644 index 0000000..2a4d6f5 --- /dev/null +++ b/pluf/src/Pluf/HTTP.php @@ -0,0 +1,91 @@ + $v) { + if (is_array($v)) { + $result[$k] = Pluf_HTTP_handleMagicQuotes($v); + } else { + $result[$k] = stripslashes($v); + } + } + return $result; + } else { + return stripslashes($value); + } +} diff --git a/pluf/src/Pluf/HTTP/Error404.php b/pluf/src/Pluf/HTTP/Error404.php new file mode 100644 index 0000000..d9e1621 --- /dev/null +++ b/pluf/src/Pluf/HTTP/Error404.php @@ -0,0 +1,26 @@ +removeTheMagic(); + $this->POST =& $_POST; + $this->GET =& $_GET; + $this->REQUEST =& $_REQUEST; + $this->COOKIE =& $_COOKIE; + $this->FILES =& $_FILES; + $this->query = $query; + $this->method = $_SERVER['REQUEST_METHOD']; + $this->uri = $_SERVER['REQUEST_URI']; + $this->remote_addr = $_SERVER['REMOTE_ADDR']; + $this->http_host = (isset($_SERVER['HTTP_HOST'])) ? $_SERVER['HTTP_HOST'] : ''; + $this->SERVER =& $_SERVER; + $this->uid = $GLOBALS['_PX_uniqid']; + $this->time = (isset($_SERVER['REQUEST_TIME'])) ? $_SERVER['REQUEST_TIME'] : time(); + } +} diff --git a/pluf/src/Pluf/HTTP/Response.php b/pluf/src/Pluf/HTTP/Response.php new file mode 100644 index 0000000..0b5dfdb --- /dev/null +++ b/pluf/src/Pluf/HTTP/Response.php @@ -0,0 +1,174 @@ +headers['Content-Type'] = 'text/html; charset=utf-8'; + */ + public $headers = array(); + + /** + * Status code of the answer. + */ + public $status_code = 200; + + /** + * Cookies to send. + * + * $this->cookies['my_cookie'] = 'content of the cookie'; + */ + public $cookies = array(); + + /** + * Status code list. + * + * @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html + */ + public $status_code_list = array( + '100' => 'CONTINUE', + '101' => 'SWITCHING PROTOCOLS', + '200' => 'OK', + '201' => 'CREATED', + '202' => 'ACCEPTED', + '203' => 'NON-AUTHORITATIVE INFORMATION', + '204' => 'NO CONTENT', + '205' => 'RESET CONTENT', + '206' => 'PARTIAL CONTENT', + '300' => 'MULTIPLE CHOICES', + '301' => 'MOVED PERMANENTLY', + '302' => 'FOUND', + '303' => 'SEE OTHER', + '304' => 'NOT MODIFIED', + '305' => 'USE PROXY', + '306' => 'RESERVED', + '307' => 'TEMPORARY REDIRECT', + '400' => 'BAD REQUEST', + '401' => 'UNAUTHORIZED', + '402' => 'PAYMENT REQUIRED', + '403' => 'FORBIDDEN', + '404' => 'NOT FOUND', + '405' => 'METHOD NOT ALLOWED', + '406' => 'NOT ACCEPTABLE', + '407' => 'PROXY AUTHENTICATION REQUIRED', + '408' => 'REQUEST TIMEOUT', + '409' => 'CONFLICT', + '410' => 'GONE', + '411' => 'LENGTH REQUIRED', + '412' => 'PRECONDITION FAILED', + '413' => 'REQUEST ENTITY TOO LARGE', + '414' => 'REQUEST-URI TOO LONG', + '415' => 'UNSUPPORTED MEDIA TYPE', + '416' => 'REQUESTED RANGE NOT SATISFIABLE', + '417' => 'EXPECTATION FAILED', + '500' => 'INTERNAL SERVER ERROR', + '501' => 'NOT IMPLEMENTED', + '502' => 'BAD GATEWAY', + '503' => 'SERVICE UNAVAILABLE', + '504' => 'GATEWAY TIMEOUT', + '505' => 'HTTP VERSION NOT SUPPORTED' + ); + + + /** + * Constructor of the response. + * + * @param string Content of the response ('') + * @param string MimeType of the response (null) if not given will + * default to the one given in the configuration 'mimetype' + */ + function __construct($content='', $mimetype=null) + { + if (is_null($mimetype)) { + $mimetype = Pluf::f('mimetype', 'text/html').'; charset=utf-8'; + } + $this->content = $content; + $this->headers['Content-Type'] = $mimetype; + $this->headers['X-Powered-By'] = 'Pluf - http://pluf.org/'; + $this->status_code = 200; + $this->cookies = array(); + } + + /** + * Render a response object. + */ + function render($output_body=true) + { + if ($this->status_code >= 200 + && $this->status_code != 204 + && $this->status_code != 304) { + $this->headers['Content-Length'] = strlen($this->content); + } + $this->outputHeaders(); + if ($output_body) { + echo $this->content; + } + } + + /** + * Output headers. + */ + function outputHeaders() + { + if (!defined('IN_UNIT_TESTS')) { + header('HTTP/1.0 '.$this->status_code.' ' + .$this->status_code_list[$this->status_code], + true, $this->status_code); + foreach ($this->headers as $header => $ch) { + header($header.': '.$ch); + } + foreach ($this->cookies as $cookie => $data) { + // name, data, expiration, path, domain, secure, http only + $expire = (null == $data) ? time()-31536000 : time()+31536000; + $data = (null == $data) ? '' : $data; + setcookie($cookie, $data, $expire, + Pluf::f('cookie_path', '/'), + Pluf::f('cookie_domain', null), + Pluf::f('cookie_secure', false), + Pluf::f('cookie_httponly', true)); + } + } else { + $_COOKIE = array(); + foreach ($this->cookies as $cookie => $data) { + $_COOKIE[$cookie] = $data; + } + } + } +} diff --git a/pluf/src/Pluf/HTTP/Response/CommandPassThru.php b/pluf/src/Pluf/HTTP/Response/CommandPassThru.php new file mode 100644 index 0000000..03fc2c1 --- /dev/null +++ b/pluf/src/Pluf/HTTP/Response/CommandPassThru.php @@ -0,0 +1,54 @@ +outputHeaders(); + if ($output_body) { + passthru($this->content); + } + } +} diff --git a/pluf/src/Pluf/HTTP/Response/File.php b/pluf/src/Pluf/HTTP/Response/File.php new file mode 100644 index 0000000..cb436a9 --- /dev/null +++ b/pluf/src/Pluf/HTTP/Response/File.php @@ -0,0 +1,50 @@ +delete_file = $delete_file; + } + + /** + * Render a response object. + */ + function render($output_body=true) + { + $this->headers['Content-Length'] = (string)filesize($this->content); + $this->outputHeaders(); + if ($output_body) { + $fp = fopen($this->content, 'rb'); + fpassthru($fp); + fclose($fp); + } + if ($this->delete_file) { + @unlink($this->content); + } + } +} diff --git a/pluf/src/Pluf/HTTP/Response/Forbidden.php b/pluf/src/Pluf/HTTP/Response/Forbidden.php new file mode 100644 index 0000000..739cf20 --- /dev/null +++ b/pluf/src/Pluf/HTTP/Response/Forbidden.php @@ -0,0 +1,42 @@ + $request->query)); + $tmpl = new Pluf_Template('403.html'); + $content = $tmpl->render($context); + $mimetype = null; + } catch (Exception $e) { + $mimetype = 'text/plain'; + $content = 'You are not authorized to view this page. You do not have permission'."\n" + .'to view the requested directory or page using the credentials supplied.'."\n\n".'403 - Forbidden'; + } + parent::__construct($content, $mimetype); + $this->status_code = 403; + } +} \ No newline at end of file diff --git a/pluf/src/Pluf/HTTP/Response/Json.php b/pluf/src/Pluf/HTTP/Response/Json.php new file mode 100644 index 0000000..e96f07e --- /dev/null +++ b/pluf/src/Pluf/HTTP/Response/Json.php @@ -0,0 +1,36 @@ + $request->query)); + $tmpl = new Pluf_Template('503.html'); + $content = $tmpl->render($context); + $mimetype = null; + } catch (Exception $e) { + $mimetype = 'text/plain'; + $content = sprintf('The requested URL %s is not available at the moment.'."\n" + .'Please try again later.'."\n\n".'503 - Service Unavailable', + Pluf_esc($request->query)); + } + parent::__construct($content, $mimetype); + $this->status_code = 503; + $this->headers['Retry-After'] = 300; // retry after 5 minutes + } +} diff --git a/pluf/src/Pluf/HTTP/Response/NotFound.php b/pluf/src/Pluf/HTTP/Response/NotFound.php new file mode 100644 index 0000000..e3cfd34 --- /dev/null +++ b/pluf/src/Pluf/HTTP/Response/NotFound.php @@ -0,0 +1,43 @@ + $request->query)); + $tmpl = new Pluf_Template('404.html'); + $content = $tmpl->render($context); + $mimetype = null; + } catch (Exception $e) { + $mimetype = 'text/plain'; + $content = sprintf('The requested URL %s was not found on this server.'."\n" + .'Please check the URL and try again.'."\n\n".'404 - Not Found', + Pluf_esc($request->query)); + } + parent::__construct($content, $mimetype); + $this->status_code = 404; + } +} diff --git a/pluf/src/Pluf/HTTP/Response/Redirect.php b/pluf/src/Pluf/HTTP/Response/Redirect.php new file mode 100644 index 0000000..495837c --- /dev/null +++ b/pluf/src/Pluf/HTTP/Response/Redirect.php @@ -0,0 +1,39 @@ +Please, click here to be redirected.'), $url); + parent::__construct($content); + $this->headers['Location'] = $url; + $this->status_code = $code; + } +} diff --git a/pluf/src/Pluf/HTTP/Response/RedirectToLogin.php b/pluf/src/Pluf/HTTP/Response/RedirectToLogin.php new file mode 100644 index 0000000..12991df --- /dev/null +++ b/pluf/src/Pluf/HTTP/Response/RedirectToLogin.php @@ -0,0 +1,61 @@ +generate($loginurl, array('_redirect_after' => $request->uri), false); + $encoded = $murl->generate($loginurl, array('_redirect_after' => $request->uri)); + } else { + Pluf::loadFunction('Pluf_HTTP_URL_urlForView'); + $url = Pluf_HTTP_URL_urlForView(Pluf::f('login_view', 'login_view'), + array(), + array('_redirect_after' => $request->uri), false); + $encoded = Pluf_HTTP_URL_urlForView(Pluf::f('login_view', 'login_view'), + array(), + array('_redirect_after' => $request->uri)); + } + $content = sprintf(__('Please, click here to be redirected.'), $encoded); + parent::__construct($content); + $this->headers['Location'] = $url; + $this->status_code = 302; + } +} diff --git a/pluf/src/Pluf/HTTP/Response/ServerError.php b/pluf/src/Pluf/HTTP/Response/ServerError.php new file mode 100644 index 0000000..99c1b9a --- /dev/null +++ b/pluf/src/Pluf/HTTP/Response/ServerError.php @@ -0,0 +1,171 @@ + 0) { + // Get a nice stack trace and send it by emails. + $stack = Pluf_HTTP_Response_ServerError_Pretty($exception); + $subject = $exception->getMessage(); + $subject = substr(strip_tags(nl2br($subject)), 0, 50).'...'; + foreach ($admins as $admin) { + $email = new Pluf_Mail($admin[1], $admin[1], $subject); + $email->addTextMessage($stack); + $email->sendMail(); + } + } + try { + $context = new Pluf_Template_Context(array('message' => $exception->getMessage())); + $tmpl = new Pluf_Template('500.html'); + $content = $tmpl->render($context); + $mimetype = null; + } catch (Exception $e) { + $mimetype = 'text/plain'; + $content = 'The server encountered an unexpected condition which prevented it from fulfilling your request.'."\n\n" + .'An email has been sent to the administrators, we will correct this error as soon as possible. Thank you for your comprehension.' + ."\n\n".'500 - Internal Server Error'; + } + parent::__construct($content, $mimetype); + $this->status_code = 500; + } +} + +function Pluf_HTTP_Response_ServerError_Pretty($e) +{ + $sub = create_function('$f','$loc="";if(isset($f["class"])){ + $loc.=$f["class"].$f["type"];} + if(isset($f["function"])){$loc.=$f["function"];} + return $loc;'); + $parms = create_function('$f','$params=array();if(isset($f["function"])){ + try{if(isset($f["class"])){ + $r=new ReflectionMethod($f["class"]."::".$f["function"]);} + else{$r=new ReflectionFunction($f["function"]);} + return $r->getParameters();}catch(Exception $e){}} + return $params;'); + $src2lines = create_function('$file','$src=nl2br(highlight_file($file,TRUE)); + return explode("
    ",$src);'); + $clean = create_function('$line','return html_entity_decode(str_replace(" ", " ", $line));'); + $desc = get_class($e)." making ".$_SERVER['REQUEST_METHOD']." request to ".$_SERVER['REQUEST_URI']; + $out = $desc."\n"; + if ($e->getCode()) { + $out .= $e->getCode(). ' : '; + } + $out .= $e->getMessage()."\n\n"; + $out .= 'PHP: '.$e->getFile().', line '.$e->getLine()."\n"; + $out .= 'URI: '.$_SERVER['REQUEST_METHOD'].' '.$_SERVER['REQUEST_URI']."\n\n"; + $out .= '** Stacktrace **'."\n\n"; + $frames = $e->getTrace(); + foreach ($frames as $frame_id=>$frame) { + if (!isset($frame['file'])) { + $frame['file'] = 'No File'; + $frame['line'] = '0'; + } + $out .= '* '.$sub($frame).' + ['.$frame['file'].', line '.$frame['line'].'] *'."\n"; + if (is_readable($frame['file']) ) { + $out .= '* Src *'."\n"; + $lines = $src2lines($frame['file']); + $start = $frame['line'] < 5 ? + 0 : $frame['line'] -5; $end = $start + 10; + $out2 = ''; + $i = 0; + foreach ( $lines as $k => $line ) { + if ( $k > $end ) { break; } + $line = trim(strip_tags($line)); + if ( $k < $start && isset($frames[$frame_id+1]["function"]) + && preg_match('/function( )*'.preg_quote($frames[$frame_id+1]["function"]).'/', + $line) ) { + $start = $k; + } + if ( $k >= $start ) { + if ( $k != $frame['line'] ) { + $out2 .= ($start+$i).': '.$clean($line)."\n"; + } else { + $out2 .= '>> '.($start+$i).': '.$clean($line)."\n"; + } + $i++; + } + } + $out .= $out2; + } else { + $out .= 'No src available.'; + } + $out .= "\n"; + } + $out .= "\n\n\n\n"; + $out .= '** Request **'."\n\n"; + + if ( function_exists('apache_request_headers') ) { + $out .= '* Request (raw) *'."\n\n"; + $req_headers = apache_request_headers(); + $out .= 'HEADERS'."\n"; + if ( count($req_headers) > 0 ) { + foreach ($req_headers as $req_h_name => $req_h_val) { + $out .= $req_h_name.': '.$req_h_val."\n"; + } + $out .= "\n"; + } else { + $out .= 'No headers.'."\n"; + } + $req_body = file_get_contents('php://input'); + if ( strlen( $req_body ) > 0 ) { + $out .= 'Body'."\n"; + $out .= $req_body."\n"; + } + } + $out .= "\n".'* Request (parsed) *'."\n\n"; + $superglobals = array('$_GET','$_POST','$_COOKIE','$_SERVER','$_ENV'); + foreach ( $superglobals as $sglobal ) { + $sfn = create_function('','return '.$sglobal.';'); + $out .= $sglobal."\n"; + if ( count($sfn()) > 0 ) { + foreach ( $sfn() as $k => $v ) { + $out .= 'Variable: '.$k."\n"; + $out .= 'Value: '.print_r($v,TRUE)."\n"; + } + $out .= "\n"; + } else { + $out .= 'No data'."\n\n"; + } + } + if ( function_exists('headers_list') ) { + $out .= "\n\n\n\n"; + $out .= '** Response **'."\n\n"; + $out .= '* Headers *'."\n\n"; + $resp_headers = headers_list(); + if (count($resp_headers) > 0) { + foreach ( $resp_headers as $resp_h ) { + $out .= $resp_h."\n"; + } + $out .= "\n"; + } else { + $out .= 'No headers.'."\n"; + } + } + return $out; +} + diff --git a/pluf/src/Pluf/HTTP/Response/ServerErrorDebug.php b/pluf/src/Pluf/HTTP/Response/ServerErrorDebug.php new file mode 100644 index 0000000..63aa3c5 --- /dev/null +++ b/pluf/src/Pluf/HTTP/Response/ServerErrorDebug.php @@ -0,0 +1,376 @@ +status_code = 500; + $this->content = Pluf_HTTP_Response_ServerErrorDebug_Pretty($e); + } +} + +/** + * @credits http://www.sitepoint.com/blogs/2006/04/04/pretty-blue-screen/ + */ +function Pluf_HTTP_Response_ServerErrorDebug_Pretty($e) +{ + $o = create_function('$in','return htmlspecialchars($in);'); + $sub = create_function('$f','$loc="";if(isset($f["class"])){ + $loc.=$f["class"].$f["type"];} + if(isset($f["function"])){$loc.=$f["function"];} + if(!empty($loc)){$loc=htmlspecialchars($loc); + $loc="$loc";}return $loc;'); + $parms = create_function('$f','$params=array();if(isset($f["function"])){ + try{if(isset($f["class"])){ + $r=new ReflectionMethod($f["class"]."::".$f["function"]);} + else{$r=new ReflectionFunction($f["function"]);} + return $r->getParameters();}catch(Exception $e){}} + return $params;'); + $src2lines = create_function('$file','$src=nl2br(highlight_file($file,TRUE)); + return explode("
    ",$src);'); + $clean = create_function('$line','return trim(strip_tags($line));'); + $desc = get_class($e)." making ".$_SERVER['REQUEST_METHOD']." request to ". + $_SERVER['REQUEST_URI']; + $out = ' + + + + + + '.$o($desc).' + + + + + +
    +

    '.$o($desc).'

    +

    '; + if ($e->getCode()) { + $out .= $o($e->getCode()). ' : '; + } + $out .= ' '.$o($e->getMessage()).'

    +
+ + + + + + + + +
PHP'.$o($e->getFile()).', line '.$o($e->getLine()).'
URI'.$o($_SERVER['REQUEST_METHOD'].' '. + $_SERVER['REQUEST_URI']).'
+ + +
+

Stacktrace + +

+
    '; + $frames = $e->getTrace(); + foreach ($frames as $frame_id=>$frame) { + if (!isset($frame['file'])) { + $frame['file'] = 'No File'; + $frame['line'] = '0'; + } + $out .= '
  • '.$sub($frame).' + ['.$o($frame['file']).', line '.$o($frame['line']).']'; + if (isset($frame['args']) && count($frame['args']) > 0) { + $params = $parms($frame); + $out .= ' +
    + Args +
    + + + + + + + + + '; + foreach ($frame['args'] as $k => $v) { + $name = (isset($params[$k]) and isset($params[$k]->name)) ? '$'.$params[$k]->name : '?'; + $out .= ' + + + + + '; + } + $out .= '
    ArgNameValue
    '.$o($k).''.$o($name).' +
    '.Pluf_esc(print_r($v, true)).'
    +
    '; + } + if (is_readable($frame['file']) ) { + $out .= ' +
    + Src +
    +
    '; + $lines = $src2lines($frame['file']); + $start = $frame['line'] < 5 ? + 0 : $frame['line'] -5; $end = $start + 10; + $out2 = ''; + foreach ( $lines as $k => $line ) { + if ( $k > $end ) { break; } + $line = trim(strip_tags($line)); + if ( $k < $start && isset($frames[$frame_id+1]["function"]) + && preg_match('/function( )*'.preg_quote($frames[$frame_id+1]["function"]).'/', + $line) ) { + $start = $k; + } + if ( $k >= $start ) { + if ( $k != $frame['line'] ) { + $out2 .= '
  • '.$clean($line).'
  • '."\n"; } + else { + $out2 .= '
  • '. + $clean($line).'
  • '."\n"; } + } + } + $out .= "
      \n".$out2. "
    \n"; + $out .= '
'; + } else { + $out .= '
No src available
'; + } + $out .= ''; + } // End of foreach $frames + $out .= ' + + + + +
+

Request + +

+
'; + if ( function_exists('apache_request_headers') ) { + $out .= '

Request (raw)

'; + $req_headers = apache_request_headers(); + $out .= '

HEADERS

'; + if ( count($req_headers) > 0 ) { + $out .= '

'; + foreach ($req_headers as $req_h_name => $req_h_val) { + $out .= $o($req_h_name.': '.$req_h_val); + $out .= '
'; + } + $out .= '

'; + } else { + $out .= '

No headers.

'; + } + $req_body = file_get_contents('php://input'); + if ( strlen( $req_body ) > 0 ) { + $out .=' +

Body

+

+ '.$o($req_body).' +

'; + } + } + $out .= ' +

Request (parsed)

'; + $superglobals = array('$_GET','$_POST','$_COOKIE','$_SERVER','$_ENV'); + foreach ( $superglobals as $sglobal ) { + $sfn = create_function('','return '.$sglobal.';'); + $out .= '

'.$sglobal.'

'; + if ( count($sfn()) > 0 ) { + $out .= ' + + + + + + + + '; + foreach ( $sfn() as $k => $v ) { + $out .= ' + + + '; + } + $out .= ' + +
VariableValue
'.$o($k).' +
'.$o(print_r($v,TRUE)).'
+
'; + } else { + $out .= ' +

No data

'; + } + } + $out .= ' + +
+
'; + if ( function_exists('headers_list') ) { + $out .= ' +
+ +

Response + +

+ +
+ +

Headers

'; + $resp_headers = headers_list(); + if (count($resp_headers) > 0) { + $out .= ' +

'; + foreach ( $resp_headers as $resp_h ) { + $out .= $o($resp_h); + $out .= '
'; + } + $out .= '

'; + } else { + $out .= ' +

No headers.

'; + } + $out .= ' +
'; + } + $out .= ' + + +'; + return $out; +} + diff --git a/pluf/src/Pluf/HTTP/URL.php b/pluf/src/Pluf/HTTP/URL.php new file mode 100644 index 0000000..bed8138 --- /dev/null +++ b/pluf/src/Pluf/HTTP/URL.php @@ -0,0 +1,173 @@ +source = $source; + } + + /** + * Convert the image as a png file. + * + * @param string Output file. + */ + public function asPng($output) + { + $this->saveAs($output, 'png'); + } + + /** + * Convert the image as a given type. + * + * Types are 'gif', 'jpg' or 'png' + * + * @param string Output file. + * @param string Type. + */ + public function saveAs($output, $type='png') + { + $types = array('gif' => '1', + 'jpg' => '2', + 'png' => '3'); + $output_func = array('gif' => 'imagegif', + 'jpg' => 'imagejpeg', + 'png' => 'imagepng'); + if (!file_exists($this->source)) { + throw new Exception(sprintf('Image source "%s" unavailable.', + $this->source)); + } + if (($size = @getimagesize($this->source)) === false) { + throw new Exception(sprintf('Image source "%s" is not an image.', + $this->source)); + } + $source_type = $size[2]; + if ($source_type == $types[$type]) { + // Simply the source to the output. + if (false === @copy($this->source, $output)) { + throw new Exception(sprintf('Failed to copy %s to %s.', + $this->source, $output)); + + } + return; + } + if ($source_type == '1') { + $function = 'imagecreatefromgif'; + } elseif ($source_type == '2') { + $function = 'imagecreatefromjpeg'; + } elseif ($source_type == '3') { + $function = 'imagecreatefrompng'; + } else { + throw new Exception('The source image is not of a recognized type.'); + } + if (($img = @$function($this->source)) == false) { + throw new Exception('Cannot read the source image.'); + } + if (!@$output_func[$type]($img, $output)) { + throw new Exception('Cannot write the output image.'); + } + } +} \ No newline at end of file diff --git a/pluf/src/Pluf/Image/Thumbnail.php b/pluf/src/Pluf/Image/Thumbnail.php new file mode 100644 index 0000000..cec741c --- /dev/null +++ b/pluf/src/Pluf/Image/Thumbnail.php @@ -0,0 +1,260 @@ +exists()) { + * $thumbnail_filename = $thumbnail->generate(); + * } + * + */ +class Pluf_Image_Thumbnail +{ + protected $dir = ''; /**< Path to the thumbnail folder. */ + protected $filename = ''; /**< Filename of the last created thumbnail. */ + public $source = ''; /**< Full path to the source file. */ + public $size = array(120, 120); /** Max width and heigth of the thumb. */ + + /** + * Init the thumbnail class. + */ + public function __construct($dir, $source='') + { + $this->dir = $dir; + $this->source = $source; + } + + /** + * Get the name of a thumbnail from the image name, the image + * name can include a path this is just a md5() operation. + * If the height and the width are given, the info is used to + * generate the name, else not. + * + * @param array Optional size. + * @return string Filename of the thumbnail. + */ + public function getName($size=null) + { + $name = md5($this->source); + if ($size === null) { + $size = $this->size; + } + return $name.'-'.$size[0].'-'.$size[1].'.png'; + } + + /** + * Get the full path to the thumbnail. + */ + function getPath() + { + return $this->dir.'/'.$this->getName(); + } + + /** + * Check if the thumbnail exists. + */ + function exists() + { + return file_exists($this->getPath()); + } + + /** + * Get the size of the last created thumbnail + * return the same results as the builtin getimagesize PHP function. + */ + function getSize() + { + if (file_exists($this->getPath())) { + return getimagesize($this->getPath()); + } else { + return false; + } + } + + /** + * Create thumbnail of an image, proportions are kept. + * + * @return mixed Filename or false. + */ + function generate() + { + if (!file_exists($this->source)) { + return false; + } + + if (($size = @getimagesize($this->source)) === false) { + return false; + } + list($w, $h) = $this->size; + $type = $size[2]; + $H = $size[1]; + $W = $size[0]; + + if ($type == '1') { + $function = 'imagecreatefromgif'; + } elseif ($type == '2') { + $function = 'imagecreatefromjpeg'; + } elseif ($type == '3') { + $function = 'imagecreatefrompng'; + } else { + return false; + } + if (!function_exists($function)) { + return false; + } + if (($img = @$function($this->source)) == false) { + return false; + } + // get the zoom factors and the thumbnail height and width + $rB = $H/$W; + $rS = $h/$w; + if (($H > $h) && ($W > $w)) { + if ($rB > $rS) { + $height = $h; + $width = $height/$rB; + } else { + $width = $w; + $height = $width*$rB; + } + } elseif ($H > $h) { + $height = $h; + $width = $height/$rB; + } elseif ($W > $w) { + $width = $w; + $height = $width*$rB; + } else { + $height = $H; + $width = $W; + } + $zx = $W/$width; + $zy = $H/$height; + + if (Pluf_Image_Thumbnail::gd_version() >= 2) { + if (($img2=imagecreatetruecolor(round($width),round($height)))===false) { + return false; + } + } else { + if (($img2=ImageCreate(round($width),round($height)))===false) { + return false; + } + } + $this->resampleBicubic($img2,$img,0,0,0,0,$width,$height,$zx,$zy); + if (@imagepng($img2,$this->getPath(),9) === false) { + return false; + } + imagedestroy($img2); + if (@file_exists($this->getPath())) { + return $this->getPath(); + } else { + return false; + } + } + + /** + * Get the current GD version. Need the output buffering functions. + */ + public static function gd_version() + { + static $gd_version_number = null; + if ($gd_version_number === null) { + // Use output buffering to get results from phpinfo() + // without disturbing the page we're in. Output + // buffering is "stackable" so we don't even have to + // worry about previous or encompassing buffering. + ob_start(); + phpinfo(8); + $module_info = ob_get_contents(); + ob_end_clean(); + if (preg_match("/\bgd\s+version\b[^\d\n\r]+?([\d\.]+)/i", + $module_info,$matches)) { + $gd_version_number = $matches[1]; + } else { + $gd_version_number = '0'; + } + } + return $gd_version_number; + + } + + /* ======================================================================== + * Private functions, should not be called from outside of the class. + * ======================================================================== + */ + + /** + * Resample the image + * http://www.php.net/manual/en/function.imagecopyresized.php + */ + protected function resampleBicubic(&$dst, &$src, $dstx, $dsty, $srcx, + $srcy, $w, $h, $zoomX, $zoomY='') + { + if (!$zoomY) { + $zoomY = $zoomX; + } + $palsize = ImageColorsTotal($src); + for ($i = 0; $i<$palsize; $i++) { + $colors = ImageColorsForIndex($src, $i); + ImageColorAllocate($dst, $colors['red'], $colors['green'], + $colors['blue']); + } + $zoomX2 = (int)($zoomX/2); + $zoomY2 = (int)($zoomY/2); + $dstX = imagesx($dst); + $dstY = imagesy($dst); + $srcX = imagesx($src); + $srcY = imagesy($src); + + for ($j=0; $j<($h-$dsty); $j++) { + $sY = (int)($j*$zoomY) + $srcy; + $y13 = $sY+$zoomY2; + $dY = $j+$dsty; + + if (($sY >= $srcY) or ($dY >= $dstY) or ($y13 >= $srcY)) { + break 1; + } + for ($i=0; $i<($w-$dstx); $i++) { + $sX = (int)($i*$zoomX)+$srcx; + $x34 = $sX+$zoomX2; + $dX = $i+$dstx; + if (($sX >= $srcX) or ($dX >= $dstX) or ($x34 >= $srcX)) { + break 1; + } + $c1 = ImageColorsForIndex($src, ImageColorAt($src, $sX, $y13)); + $c2 = ImageColorsForIndex($src, ImageColorAt($src, $sX, $sY)); + $c3 = ImageColorsForIndex($src, ImageColorAt($src, $x34, $y13)); + $c4 = ImageColorsForIndex($src, ImageColorAt($src, $x34, $sY)); + + $r = ($c1['red']+$c2['red']+$c3['red']+$c4['red'])/4; + $g = ($c1['green']+$c2['green']+$c3['green']+$c4['green'])/4; + $b = ($c1['blue']+$c2['blue']+$c3['blue']+$c4['blue'])/4; + + ImageSetPixel($dst, $dX, $dY, ImageColorClosest($dst, $r, + $g, $b)); + } + } + } +} \ No newline at end of file diff --git a/pluf/src/Pluf/L10n.php b/pluf/src/Pluf/L10n.php new file mode 100644 index 0000000..83c2240 --- /dev/null +++ b/pluf/src/Pluf/L10n.php @@ -0,0 +1,839 @@ +locale_folder = dirname(__FILE__).'/locale'; + } + $this->loadDomain($lang, $domain); + } + + /** + * Load a domain file. + * A domain file is a .lang file in the main locale folder of plume. + * + * @param string Language ('en') + * @param string Domain, without the .lang ('pluf') + * @return bool Success + */ + function loadDomain($lang='en', $domain='pluf') + { + if ('en' == $lang) { + return true; + } + return $this->loadFile($this->locale_folder.$lang.'/'.$domain.'.lang'); + } + + /** + * Load a locale file + * + * @param string Complete path to the locale file + * @return bool Success + */ + function loadFile($file) + { + if (!empty($GLOBALS['_PX_locale_files'][$file])) { + return true; + } + if (!file_exists($file)) { + return false; + } + if (!isset($GLOBALS['_PX_locale'])) { + $GLOBALS['_PX_locale'] = array(); + } + // Load optimized file if available + if ('' != Pluf::f('tmp_folder')) { + $phpfile = Pluf::f('tmp_folder').'/Pluf_L10n-' + .str_replace(DIRECTORY_SEPARATOR, '_', substr($file, 0, -5)) + .'.php'; + if (file_exists($phpfile) + && (@filemtime($file) < @filemtime($phpfile))) { + $l = include $phpfile; + $GLOBALS['_PX_locale'] = array_merge($GLOBALS['_PX_locale'], $l); + $GLOBALS['_PX_locale_files'][$file] = 'optimized'; + return true; + } + } + $lines = file($file); + $count = count($lines); + for ($i=1; $i<$count; $i++) { + $tmp = (!empty($lines[$i+1])) ? trim($lines[$i+1]) : ''; + if (!empty($tmp) && ';' == substr($lines[$i],0,1)) { + $GLOBALS['_PX_locale'][trim(substr($lines[$i],1))] = $tmp; + $i++; + } + } + $GLOBALS['_PX_locale_files'][$file] = true; + return true; + } + + /** + * Optimize a locale. Convert the .lang in a .php file + * ready to be included. The optimized file is encoded + * with the current encoding. + * + * @param string Locale file to optimize + * @return bool Success + */ + function optimizeLocale($file) + { + if (!file_exists($file)) { + return false; + } + $phpfile = Pluf::f('tmp_folder').'/Pluf_L10n-' + .str_replace(DIRECTORY_SEPARATOR, '_', substr($file, 0, -5)) + .'.php'; + $lines = file($file); + $out = ''; + file_put_contents($phpfile, $out, LOCK_EX); + @chmod($phpfile, 0777); + return true; + } + + /** + * Get the available locales for a domain. + * + * @param string Domain ('') + * @return array List of 2 letter iso codes + */ + function getAvailableLocales($domain='') + { + $rootdir = $this->locale_folder.'/'; + $locales = array(); + $locales[] = 'en'; //English is always available + $current_dir = opendir($rootdir); + if (!empty($domain)) { + $domain .= '.lang'; + } + while($entryname = readdir($current_dir)) { + if (is_dir($rootdir.$entryname.'/') + and ($entryname != '.' and $entryname!='..') + and (2 == strlen($entryname)) + ) { + $entryname = strtolower($entryname); + if (empty($domain)) { + $locales[] = $entryname; + } elseif (is_file($rootdir.$entryname.'/'.$domain)) { + $locales[] = $entryname; + } + } + } + closedir($current_dir); + sort($locales); + reset($locales); + return $locales; + } + + /** + * Return the "best" accepted language from the list of available + * languages. + * + * Use $_SERVER['HTTP_ACCEPT_LANGUAGE'] if the accepted language is empty + * + * @param array Available languages in the system + * @param string String of comma separated accepted languages ('') + * @return string Language 2 letter iso code, default is 'en' + */ + function getAcceptedLanguage($available, $accepted ='') + { + if (empty($accepted)) { + if (!empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { + $accepted = $_SERVER['HTTP_ACCEPT_LANGUAGE']; + } else { + return 'en'; + } + } + $acceptedlist = explode(',', $accepted); + foreach ($acceptedlist as $lang) { + //for the fr-FR en-US cases + $lang = strtolower(substr($lang, 0, 2)); + if (in_array($lang, $available)) { + return $lang; + } + } + //no match found, English + return 'en'; + } + + /** + * Returns iso codes. + * + * @param bool Is the language the key in the array (false) + * @return array The key is either the language or the iso code + */ + function getIsoCodes($lang=false) + { + $res = array('aa' => 'Afar', + 'ab' => 'Abkhazian', + 'af' => 'Afrikaans', + 'am' => 'Amharic', + 'ar' => 'Arabic', + 'as' => 'Assamese', + 'ay' => 'Aymara', + 'az' => 'Azerbaijani', + 'ba' => 'Bashkir', + 'be' => 'Byelorussian', + 'bg' => 'Bulgarian', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bn' => 'Bengali', + 'bo' => 'Tibetan', + 'br' => 'Breton', + 'ca' => 'Catalan', + 'co' => 'Corsican', + 'cs' => 'Czech', + 'cy' => 'Welsh', + 'da' => 'Danish', + 'de' => 'German', + 'dz' => 'Bhutani', + 'el' => 'Greek', + 'en' => 'English', + 'eo' => 'Esperanto', + 'es' => 'Spanish', + 'et' => 'Estonian', + 'eu' => 'Basque', + 'fa' => 'Persian', + 'fi' => 'Finnish', + 'fj' => 'Fiji', + 'fo' => 'Faroese', + 'fr' => 'French', + 'fy' => 'Frisian', + 'ga' => 'Irish', + 'gd' => 'Scots gaelic', + 'gl' => 'Galician', + 'gn' => 'Guarani', + 'gu' => 'Gujarati', + 'ha' => 'Hausa', + 'he' => 'Hebrew', + 'hi' => 'Hindi', + 'hr' => 'Croatian', + 'hu' => 'Hungarian', + 'hy' => 'Armenian', + 'ia' => 'Interlingua', + 'ie' => 'Interlingue', + 'ik' => 'Inupiak', + 'id' => 'Indonesian', + 'is' => 'Icelandic', + 'it' => 'Italian', + 'iu' => 'Inuktitut', + 'ja' => 'Japanese', + 'jv' => 'Javanese', + 'ka' => 'Georgian', + 'kk' => 'Kazakh', + 'kl' => 'Greenlandic', + 'km' => 'Cambodian', + 'kn' => 'Kannada', + 'ko' => 'Korean', + 'ks' => 'Kashmiri', + 'ku' => 'Kurdish', + 'ky' => 'Kirghiz', + 'la' => 'Latin', + 'ln' => 'Lingala', + 'lo' => 'Laothian', + 'lt' => 'Lithuanian', + 'lv' => 'Latvian;lettish', + 'mg' => 'Malagasy', + 'mi' => 'Maori', + 'mk' => 'Macedonian', + 'ml' => 'Malayalam', + 'mn' => 'Mongolian', + 'mo' => 'Moldavian', + 'mr' => 'Marathi', + 'ms' => 'Malay', + 'mt' => 'Maltese', + 'my' => 'Burmese', + 'na' => 'Nauru', + 'ne' => 'Nepali', + 'nl' => 'Dutch', + 'no' => 'Norwegian', + 'oc' => 'Occitan', + 'om' => 'Afan (oromo)', + 'or' => 'Oriya', + 'pa' => 'Punjabi', + 'pl' => 'Polish', + 'ps' => 'Pashto;pushto', + 'pt' => 'Portuguese', + 'qu' => 'Quechua', + 'rm' => 'Rhaeto-romance', + 'rn' => 'Kurundi', + 'ro' => 'Romanian', + 'ru' => 'Russian', + 'rw' => 'Kinyarwanda', + 'sa' => 'Sanskrit', + 'sd' => 'Sindhi', + 'sg' => 'Sangho', + 'sh' => 'Serbo-croatian', + 'si' => 'Singhalese', + 'sk' => 'Slovak', + 'sl' => 'Slovenian', + 'sm' => 'Samoan', + 'sn' => 'Shona', + 'so' => 'Somali', + 'sq' => 'Albanian', + 'sr' => 'Serbian', + 'ss' => 'Siswati', + 'st' => 'Sesotho', + 'su' => 'Sundanese', + 'sv' => 'Swedish', + 'sw' => 'Swahili', + 'ta' => 'Tamil', + 'te' => 'Telugu', + 'tg' => 'Tajik', + 'th' => 'Thai', + 'ti' => 'Tigrinya', + 'tk' => 'Turkmen', + 'tl' => 'Tagalog', + 'tn' => 'Setswana', + 'to' => 'Tonga', + 'tr' => 'Turkish', + 'ts' => 'Tsonga', + 'tt' => 'Tatar', + 'tw' => 'Twi', + 'ug' => 'Uigur', + 'uk' => 'Ukrainian', + 'ur' => 'Urdu', + 'uz' => 'Uzbek', + 'vi' => 'Vietnamese', + 'vo' => 'Volapuk', + 'wo' => 'Wolof', + 'xh' => 'Xhosa', + 'yi' => 'Yiddish', + 'yo' => 'Yoruba', + 'za' => 'Zhuang', + 'zh' => 'Chinese', + 'zu' => 'Zulu'); + if ($lang) { + $res = array_flip($res); + ksort($res); //order by lang + } + return $res; + } + + /** + * Get the country codes. + * + * @param Indexed by code (false) + * @return array English name indexed country code or reverse + */ + public static function getCountryCodes($idx_by_code=false) + { + $ctr = array( + 'Andorra' => 'AD', + 'United Arab Emirates' => 'AE', + 'Afghanistan' => 'AF', + 'Antigua & Barbuda' => 'AG', + 'Anguilla' => 'AI', + 'Albania' => 'AL', + 'Armenia' => 'AM', + 'Netherlands Antilles' => 'AN', + 'Angola' => 'AO', + 'Antarctica' => 'AQ', + 'Argentina' => 'AR', + 'American Samoa' => 'AS', + 'Austria' => 'AT', + 'Australia' => 'AU', + 'Aruba' => 'AW', + 'Azerbaijan' => 'AZ', + 'Bosnia and Herzegovina' => 'BA', + 'Barbados' => 'BB', + 'Bangladesh' => 'BD', + 'Belgium' => 'BE', + 'Burkina Faso' => 'BF', + 'Bulgaria' => 'BG', + 'Bahrain' => 'BH', + 'Burundi' => 'BI', + 'Benin' => 'BJ', + 'Bermuda' => 'BM', + 'Brunei Darussalam' => 'BN', + 'Bolivia' => 'BO', + 'Brazil' => 'BR', + 'Bahama' => 'BS', + 'Bhutan' => 'BT', + 'Bouvet Island' => 'BV', + 'Botswana' => 'BW', + 'Belarus' => 'BY', + 'Belize' => 'BZ', + 'Canada' => 'CA', + 'Cocos (Keeling) Islands' => 'CC', + 'Central African Republic' => 'CF', + 'Congo' => 'CG', + 'Switzerland' => 'CH', + 'Côte D\'ivoire (Ivory Coast)' => 'CI', + 'Cook Iislands' => 'CK', + 'Chile' => 'CL', + 'Cameroon' => 'CM', + 'China' => 'CN', + 'Colombia' => 'CO', + 'Costa Rica' => 'CR', + 'Cuba' => 'CU', + 'Cape Verde' => 'CV', + 'Christmas Island' => 'CX', + 'Cyprus' => 'CY', + 'Czech Republic' => 'CZ', + 'Germany' => 'DE', + 'Djibouti' => 'DJ', + 'Denmark' => 'DK', + 'Dominica' => 'DM', + 'Dominican Republic' => 'DO', + 'Algeria' => 'DZ', + 'Ecuador' => 'EC', + 'Estonia' => 'EE', + 'Egypt' => 'EG', + 'Western Sahara' => 'EH', + 'Eritrea' => 'ER', + 'Spain' => 'ES', + 'Ethiopia' => 'ET', + 'Finland' => 'FI', + 'Fiji' => 'FJ', + 'Falkland Islands (Malvinas)' => 'FK', + 'Micronesia' => 'FM', + 'Faroe Islands' => 'FO', + 'France' => 'FR', + 'France, Metropolitan' => 'FX', + 'Gabon' => 'GA', + 'United Kingdom (Great Britain)' => 'GB', + 'Grenada' => 'GD', + 'Georgia' => 'GE', + 'French Guiana' => 'GF', + 'Ghana' => 'GH', + 'Gibraltar' => 'GI', + 'Greenland' => 'GL', + 'Gambia' => 'GM', + 'Guinea' => 'GN', + 'Guadeloupe' => 'GP', + 'Equatorial Guinea' => 'GQ', + 'Greece' => 'GR', + 'South Georgia and the South Sandwich Islands' => 'GS', + 'Guatemala' => 'GT', + 'Guam' => 'GU', + 'Guinea-Bissau' => 'GW', + 'Guyana' => 'GY', + 'Hong Kong' => 'HK', + 'Heard & McDonald Islands' => 'HM', + 'Honduras' => 'HN', + 'Croatia' => 'HR', + 'Haiti' => 'HT', + 'Hungary' => 'HU', + 'Indonesia' => 'ID', + 'Ireland' => 'IE', + 'Israel' => 'IL', + 'India' => 'IN', + 'British Indian Ocean Territory' => 'IO', + 'Iraq' => 'IQ', + 'Iran, Islamic Republic of' => 'IR', + 'Iceland' => 'IS', + 'Italy' => 'IT', + 'Jamaica' => 'JM', + 'Jordan' => 'JO', + 'Japan' => 'JP', + 'Kenya' => 'KE', + 'Kyrgyzstan' => 'KG', + 'Cambodia' => 'KH', + 'Kiribati' => 'KI', + 'Comoros' => 'KM', + 'St. Kitts and Nevis' => 'KN', + 'Korea, Democratic People\'s Republic of' => 'KP', + 'Korea, Republic of' => 'KR', + 'Kuwait' => 'KW', + 'Cayman Islands' => 'KY', + 'Kazakhstan' => 'KZ', + 'Lao People\'s Democratic Republic' => 'LA', + 'Lebanon' => 'LB', + 'Saint Lucia' => 'LC', + 'Liechtenstein' => 'LI', + 'Sri Lanka' => 'LK', + 'Liberia' => 'LR', + 'Lesotho' => 'LS', + 'Lithuania' => 'LT', + 'Luxembourg' => 'LU', + 'Latvia' => 'LV', + 'Libyan Arab Jamahiriya' => 'LY', + 'Morocco' => 'MA', + 'Monaco' => 'MC', + 'Moldova, Republic of' => 'MD', + 'Montenegro' => 'ME', + 'Madagascar' => 'MG', + 'Marshall Islands' => 'MH', + 'Macedonia, Republic of' => 'MK', + 'Mali' => 'ML', + 'Mongolia' => 'MN', + 'Myanmar' => 'MM', + 'Macau' => 'MO', + 'Northern Mariana Islands' => 'MP', + 'Martinique' => 'MQ', + 'Mauritania' => 'MR', + 'Monserrat' => 'MS', + 'Malta' => 'MT', + 'Mauritius' => 'MU', + 'Maldives' => 'MV', + 'Malawi' => 'MW', + 'Mexico' => 'MX', + 'Malaysia' => 'MY', + 'Mozambique' => 'MZ', + 'Namibia' => 'NA', + 'New Caledonia' => 'NC', + 'Niger' => 'NE', + 'Norfolk Island' => 'NF', + 'Nigeria' => 'NG', + 'Nicaragua' => 'NI', + 'Netherlands' => 'NL', + 'Norway' => 'NO', + 'Nepal' => 'NP', + 'Nauru' => 'NR', + 'Niue' => 'NU', + 'New Zealand' => 'NZ', + 'Oman' => 'OM', + 'Panama' => 'PA', + 'Peru' => 'PE', + 'French Polynesia' => 'PF', + 'Papua New Guinea' => 'PG', + 'Philippines' => 'PH', + 'Pakistan' => 'PK', + 'Poland' => 'PL', + 'St. Pierre & Miquelon' => 'PM', + 'Pitcairn' => 'PN', + 'Puerto Rico' => 'PR', + 'Portugal' => 'PT', + 'Palau' => 'PW', + 'Paraguay' => 'PY', + 'Qatar' => 'QA', + 'Réunion' => 'RE', + 'Romania' => 'RO', + 'Serbia' => 'RS', + 'Russian Federation' => 'RU', + 'Rwanda' => 'RW', + 'Saudi Arabia' => 'SA', + 'Solomon Islands' => 'SB', + 'Seychelles' => 'SC', + 'Sudan' => 'SD', + 'Sweden' => 'SE', + 'Singapore' => 'SG', + 'St. Helena' => 'SH', + 'Slovenia' => 'SI', + 'Svalbard & Jan Mayen Islands' => 'SJ', + 'Slovakia' => 'SK', + 'Sierra Leone' => 'SL', + 'San Marino' => 'SM', + 'Senegal' => 'SN', + 'Somalia' => 'SO', + 'Suriname' => 'SR', + 'Sao Tome & Principe' => 'ST', + 'El Salvador' => 'SV', + 'Syrian Arab Republic' => 'SY', + 'Swaziland' => 'SZ', + 'Turks & Caicos Islands' => 'TC', + 'Chad' => 'TD', + 'French Southern Territories' => 'TF', + 'Togo' => 'TG', + 'Thailand' => 'TH', + 'Tajikistan' => 'TJ', + 'Tokelau' => 'TK', + 'Turkmenistan' => 'TM', + 'Tunisia' => 'TN', + 'Tonga' => 'TO', + 'East Timor' => 'TP', + 'Turkey' => 'TR', + 'Trinidad & Tobago' => 'TT', + 'Tuvalu' => 'TV', + 'Taiwan' => 'TW', + 'Tanzania, United Republic of' => 'TZ', + 'Ukraine' => 'UA', + 'Uganda' => 'UG', + 'United States Minor Outlying Islands' => 'UM', + 'United States of America' => 'US', + 'Uruguay' => 'UY', + 'Uzbekistan' => 'UZ', + 'Vatican City State (Holy See)' => 'VA', + 'St. Vincent & the Grenadines' => 'VC', + 'Venezuela' => 'VE', + 'British Virgin Islands' => 'VG', + 'United States Virgin Islands' => 'VI', + 'Viet Nam' => 'VN', + 'Vanuatu' => 'VU', + 'Wallis & Futuna Islands' => 'WF', + 'Samoa' => 'WS', + 'Yemen' => 'YE', + 'Mayotte' => 'YT', + 'South Africa' => 'ZA', + 'Zambia' => 'ZM', + 'Zaire' => 'ZR', + 'Zimbabwe' => 'ZW', + 'Unknown or unspecified country' => 'ZZ' + ); + if ($idx_by_code) { + $ctr = array_flip($ctr); + } + ksort($ctr); + return $ctr; + } + + /** + * Returns iso codes. + * + * @param bool Is the language the key in the array (false) + * @return array The key is either the language or the iso code + */ + public static function getNativeLanguages($lang=false) + { + $res = array( + 'ab' => 'Аҧсуа', + 'aa' => 'Afaraf', + 'af' => 'Afrikaans', + 'ak' => 'Akan', + 'am' => 'አማርኛ', + 'ar' => 'العربية', + 'an' => 'Aragonés', + 'as' => 'অসমীয়া', + 'av' => 'авар мацӀ', + 'ae' => 'avesta', + 'ay' => 'aymar aru', + 'az' => 'Azərbaycanca', + 'bm' => 'bamanankan', + 'ba' => 'башҡорт теле', + 'be' => 'Беларуская мова', + 'bn' => 'বাংলা', + 'bh' => 'Bihari', + 'bi' => 'Bislama', + 'bs' => 'bosanski jezik', + 'br' => 'brezhoneg', + 'bg' => 'български език', + 'ca' => 'català', + 'ch' => 'Chamoru', + 'ce' => 'нохчийн мотт', + 'ny' => 'chiCheŵa', + 'cu' => 'чӑваш чӗлхи', + 'kw' => 'Kernewek', + 'co' => 'corsu', + 'cr' => 'ᓀᐦᐃᔭᐍᐏᐣ', + 'hr' => 'hrvatski jezik', + 'cs' => 'čeština', + 'da' => 'dansk', + 'dv' => 'ދިވެހިބަސ', + 'dz' => 'རྫོང་ཁ', + 'en' => 'English', + 'eo' => 'Esperanto', + 'et' => 'eesti keel', + 'ee' => 'Ɛʋɛgbɛ', + 'fo' => 'føroyskt', + 'fj' => 'vosa Vakaviti', + 'fi' => 'suomi', + 'fr' => 'français', + 'fy' => 'frysk', + 'ff' => 'Fulfulde, Pulaar, Pular', + 'gl' => 'Galego', + 'lg' => 'Luganda', + 'ka' => 'ქართული ენა', + 'de' => 'Deutsch', + 'el' => 'Ελληνικά', + 'kl' => 'kalaallisut', + 'gn' => 'Avañe\'ẽ', + 'gu' => 'ગુજરાતી', + 'ht' => 'Kreyòl ayisyen', + 'ha' => 'Hausancī', + 'he' => 'עִבְרִית', + 'hz' => 'Otjiherero', + 'hi' => 'हिन्दी', + 'ho' => 'Hiri Motu', + 'hu' => 'magyar', + 'is' => 'íslenska', + 'io' => 'Ido', + 'ig' => 'Igbo', + 'id' => 'Bahasa Indonesia', + 'ia' => 'interlingua', + 'ie' => 'Interlingue', + 'iu' => 'ᐃᓄᒃᑎᑐᑦ', + 'ik' => 'Iñupiaq', + 'ga' => 'Gaeilge', + 'it' => 'italiano', + 'ja' => '日本語 (にほんご)', + 'jv' => 'basa Jawa', + 'kn' => 'ಕನ್ನಡ', + 'kr' => 'कॉशुर', + 'kk' => 'Қазақ тілі', + 'km' => 'Central Khmer', + 'ki' => 'Gĩkũyũ', + 'rw' => 'kinyaRwanda', + 'ky' => 'кыргыз тили', + 'kv' => 'коми кыв', + 'kg' => 'Kikongo', + 'ko' => '한국어 (韓國語)', + 'kj' => 'Kurdish', + 'lo' => 'ພາສາລາວ', + 'la' => 'latine', + 'lv' => 'latviešu valoda', + 'li' => 'Limburgs', + 'ln' => 'lingala', + 'lt' => 'lietuvių kalba', + 'lu' => 'Luxembourgish', + 'mg' => 'Malagasy fiteny', + 'ms' => 'bahasa Melayu', + 'ml' => 'മലയാളം', + 'mt' => 'Malti', + 'gv' => 'Gaelg', + 'mi' => 'te reo Māori', + 'mr' => 'मराठी', + 'mh' => 'Kajin M̧ajeļ', + 'mn' => 'монгол хэл', + 'na' => 'Ekakairũ Naoero', + 'nv' => 'Diné bizaad', + 'nd' => 'isiNdebele', + 'nr' => 'isiNdebele', + 'ng' => 'Owambo', + 'ne' => 'नेपाली', + 'se' => 'sámi', + 'no' => 'Norsk', + 'nb' => 'Norsk bokmål', + 'nn' => 'Norsk nynorsk', + 'oc' => 'Occitan', + 'oj' => 'ᐊᓂᔑᓇᐯᒧᐏᐣ (Anishinaabemowin)', + 'or' => 'ଓଡ଼ିଆ', + 'om' => 'Afaan Oromoo', + 'os' => 'ирон ӕвзаг', + 'pi' => 'पालि', + 'fa' => 'فارسی', + 'pl' => 'polski', + 'pt' => 'português', + 'pa' => 'ਪੰਜਾਬੀ', + 'ps' => 'پښتو', + 'qu' => 'Runa Simi', + 'rm' => 'rumantsch grischun', + 'rn' => 'kiRundi', + 'ru' => 'русский язык', + 'sm' => 'gagana fa\'a Samoa', + 'sg' => 'yângâ tî sängö', + 'sa' => 'संस्कृतम्', + 'sc' => 'sardu', + 'gd' => 'Gàidhlig', + 'sr' => 'српски језик', + 'sn' => 'chiShona', + 'ii' => 'ꆇꉙ', + 'sd' => 'سنڌي، سندھی', + 'si' => 'සිංහල', + 'sk' => 'slovenčina', + 'sl' => 'slovenščina', + 'so' => 'Soomaaliga', + 'st' => 'Sesotho', + 'es' => 'español', + 'su' => 'basa Sunda', + 'sw' => 'kiswahili', + 'ss' => 'siSwati', + 'sv' => 'Svenska', + 'tl' => 'Tagalog', + 'ty' => 'te reo Tahiti', + 'tg' => 'тоҷикӣ', + 'ta' => 'தமிழ்', + 'tt' => 'татарча', + 'te' => 'తెలుగు', + 'th' => 'ภาษาไทย', + 'bo' => 'བོད་ཡིག', + 'ti' => 'ትግርኛ', + 'to' => 'faka-Tonga', + 'ts' => 'Xitsonga', + 'tn' => 'Setswana', + 'tr' => 'Türkçe', + 'tk' => 'Түркмен', + 'tw' => 'Twi', + 'ug' => 'Uyƣurqə', + 'uk' => 'українська мова', + 'ur' => 'اردو', + 'uz' => 'O\'zbek', + 've' => 'Tshivenḓa', + 'vi' => 'Tiếng Việt', + 'vo' => 'Volapük', + 'wa' => 'walon', + 'cy' => 'Cymraeg', + 'wo' => 'Wolof', + 'xh' => 'isiXhosa', + 'yi' => 'ייִדיש', + 'yo' => 'Yorùbá', + 'za' => 'Saɯ cueŋƅ', + 'zu' => 'isiZulu', + ); + if ($lang) { + $res = array_flip($res); + ksort($res); //order by lang + } + return $res; + } + + public static function getInstalledLanguages() + { + $l = array(); + $nl = self::getNativeLanguages(); + foreach (Pluf::f('languages', array('en')) as $lang) { + $lang2 = substr($lang, 0, 2); + $l[mb_convert_case($nl[$lang2], MB_CASE_TITLE, 'UTF-8')] = $lang; + } + return $l; + } +} diff --git a/pluf/src/Pluf/L10n/Tag.php b/pluf/src/Pluf/L10n/Tag.php new file mode 100644 index 0000000..0e57958 --- /dev/null +++ b/pluf/src/Pluf/L10n/Tag.php @@ -0,0 +1,48 @@ + 'ALL', + 3 => 'DEBUG', + 4 => 'INFO', + 5 => 'PERF', + 6 => 'EVENT', + 7 => 'WARN', + 8 => 'ERROR', + 9 => 'FATAL'); + + /** + * Current log level. + * + * By default, logging is not enabled. + */ + public static $level = 10; + + /** + * Current message in the assert log. + */ + public static $assert_mess = null; + + /** + * Current level of the message in the assert log. + */ + public static $assert_level = 10; + + /** + * Log the information in the stack. + * + * Flush the information if needed. + * + * @param $level Level to log + * @param $message Message to log + */ + private static function _log($level, $message) + { + + if (self::$level <= $level and self::$level != 10) { + self::$stack[] = array(microtime(true), $level, $message); + if (!Pluf::f('log_delayed', false)) { + self::flush(); + } + } + } + + /** + * Base assert logger. + * + * The assert logging is a two step process as one need to go + * through the assertion callback. + * + * @param $level Level to log + * @param $message Message to log + * @return bool false + */ + private static function _alog($level, $message) + { + self::$assert_level = $level; + self::$assert_mess = $message; + return false; // This will trigger the assert handler. + } + + /** + * Log at the ALL level. + * + * @param $message Message to log + */ + public static function log($message) + { + return self::_log(self::ALL, $message); + } + + /** + * Log at the DEBUG level. + * + * @param $message Message to log + */ + public static function debug($message) + { + self::_log(self::DEBUG, $message); + } + + public static function info($message) + { + self::_log(self::INFO, $message); + } + + public static function perf($message) + { + self::_log(self::PERF, $message); + } + + public static function event($message) + { + self::_log(self::EVENT, $message); + } + + public static function warn($message) + { + self::_log(self::WARN, $message); + } + + public static function error($message) + { + self::_log(self::ERROR, $message); + } + + public static function fatal($message) + { + self::_log(self::FATAL, $message); + } + + /** + * Assert log at the ALL level. + * + * @param $message Message to log + */ + public static function alog($message) + { + return self::_alog(self::ALL, $message); + } + + /** + * Assert log at the DEBUG level. + * + * @param $message Message to log + */ + public static function adebug($message) + { + self::_alog(self::DEBUG, $message); + } + + public static function ainfo($message) + { + self::_alog(self::INFO, $message); + } + + public static function aperf($message) + { + self::_alog(self::PERF, $message); + } + + public static function aevent($message) + { + self::_alog(self::EVENT, $message); + } + + public static function awarn($message) + { + self::_alog(self::WARN, $message); + } + + public static function aerror($message) + { + self::_alog(self::ERROR, $message); + } + + public static function afatal($message) + { + self::_alog(self::FATAL, $message); + } + + /** + * Flush the data to the writer. + * + * This reset the stack. + */ + public static function flush() + { + $writer = Pluf::f('log_handler', 'Pluf_Log_File'); + call_user_func(array($writer, 'write'), self::$stack); + self::$stack = array(); + } + + /** + * Signal handler to flush the log. + * + * The name of the signal and the parameters are not used. + * + * @param $signal Name of the signal + * @param &$params Parameters + */ + public static function flushHandler($signal, &$params) + { + self::flush(); + } + + /** + * Activation of the low impact logging. + * + * When called, it enabled the assertions for debugging. + */ + public static function activeAssert() + { + assert_options(ASSERT_ACTIVE, 1); + assert_options(ASSERT_WARNING, 0); + assert_options(ASSERT_QUIET_EVAL, 1); + assert_options(ASSERT_CALLBACK, 'Pluf_Log_assert'); + } + + /** + * Increment a key in the store. + * + * It automatically creates the key as needed. + * + * @param $key Key to increment + * @param $amount Amount to increase (1) + */ + public static function inc($key, $amount=1) + { + if (!isset(Pluf_Log::$store[$key])) { + Pluf_Log::$store[$key] = 0; + } + Pluf_Log::$store[$key] += $amount; + } + + /** + * Set a key in the store. + * + * @param $key Key to set + * @param $value Value to set + */ + public static function set($key, $value) + { + Pluf_Log::$store[$key] = $value; + } + + /** + * Get a key from the store. + * + * @param $key Key to set + * @param $value Default value (null) + */ + public static function get($key, $value=null) + { + return (isset(Pluf_Log::$store[$key])) + ? Pluf_Log::$store[$key] : $value; + } + + /** + * Start the time to track. + * + * @param $key Tracker + */ + public static function stime($key) + { + Pluf_Log::$store['time_tracker_'.$key] = microtime(true); + } + + /** + * End the time to track. + * + * @param $key Tracker + * @param $total Tracker to store the total (null) + * @return float Time for this track + */ + public static function etime($key, $total=null) + { + $t = microtime(true) - Pluf_Log::$store['time_tracker_'.$key]; + if ($total) { + Pluf_Log::inc('time_tracker_'.$total, $t); + } + return $t; + } +} + +/** + * Assertion handler. + * + * @param $file Name of the file where the assert is called + * @param $line Line number of the file where the assert is called + * @param $code Code evaluated by the assert call + */ +function Pluf_Log_assert($file, $line, $code) +{ + if (Pluf_Log::$level <= Pluf_Log::$assert_level and + Pluf_Log::$level != 10) { + Pluf_Log::$stack[] = array( + microtime(true), + Pluf_Log::$assert_level, + Pluf_Log::$assert_mess, + $file, $line, $code); + if (!Pluf::f('log_delayed', false)) { + Pluf_Log::flush(); + } + + } + Pluf_Log::$assert_level = 6; + Pluf_Log::$assert_mess = null; +} \ No newline at end of file diff --git a/pluf/src/Pluf/Log/File.php b/pluf/src/Pluf/Log/File.php new file mode 100644 index 0000000..32725cc --- /dev/null +++ b/pluf/src/Pluf/Log/File.php @@ -0,0 +1,58 @@ +Pluf_Log
class. + * + * The only required static method of a log writer is + * write, which takes the stack to write as parameter. + * + * The only configuration variable of the file writer is the path to + * the log file 'pluf_log_file'. By default it creates a + * pluf.log in the configured tmp folder. + * + */ +class Pluf_Log_File +{ + /** + * Flush the stack to the disk. + * + * @param $stack Array + */ + public static function write($stack) + { + $file = Pluf::f('pluf_log_file', + Pluf::f('tmp_folder', '/tmp').'/pluf.log'); + $out = array(); + foreach ($stack as $elt) { + $out[] = date(DATE_ISO8601, (int) $elt[0]).' '. + Pluf_Log::$reverse[$elt[1]].': '. + json_encode($elt[2]); + } + file_put_contents($file, implode(PHP_EOL, $out).PHP_EOL, FILE_APPEND); + } +} diff --git a/pluf/src/Pluf/Log/Remote.php b/pluf/src/Pluf/Log/Remote.php new file mode 100644 index 0000000..3deaaca --- /dev/null +++ b/pluf/src/Pluf/Log/Remote.php @@ -0,0 +1,64 @@ +$val) { + $out .= $key.': '.$val."\r\n"; + } + $out.= 'Connection: Close'."\r\n\r\n"; + $out.= $payload; + $fp = fsockopen(Pluf::f('log_remote_server', 'localhost'), + Pluf::f('log_remote_port', 8000), + $errno, $errstr, 5); + fwrite($fp, $out); + fclose($fp); + } +} diff --git a/pluf/src/Pluf/Mail.php b/pluf/src/Pluf/Mail.php new file mode 100644 index 0000000..a1addd7 --- /dev/null +++ b/pluf/src/Pluf/Mail.php @@ -0,0 +1,205 @@ + + * $email = new Pluf_Mail('from_email@example.com', 'to_email@example.com', + * 'Subject of the message'); + * $img_id = $email->addAttachment('/var/www/html/img/pic.jpg', 'image/jpg'); + * $email->addTextMessage('Hello world!'); + * $email->addHtmlMessage('Hello world!'); + * $email->sendMail(); + *
+ * + * The configuration parameters are the one for Mail::factory with the + * 'mail_' prefix not to conflict with the other parameters. + * + * @see http://pear.php.net/manual/en/package.mail.mail.factory.php + * + * 'mail_backend' - 'mail', 'smtp' or 'sendmail' (default 'mail'). + * + * List of parameter for the backends: + * + * mail backend + * -------------- + * + * If safe mode is disabled, an array with all the 'mail_*' parameters + * excluding 'mail_backend' will be passed as the fifth argument to + * the PHP mail() function. The elements will be joined as a + * space-delimited string. + * + * sendmail backend + * ------------------ + * + * 'mail_sendmail_path' - The location of the sendmail program on the + * filesystem. Default is /usr/bin/sendmail + * 'sendmail_args' - Additional parameters to pass to the + * sendmail. Default is -i + * + * smtp backend + * -------------- + * + * 'mail_host' - The server to connect. Default is localhost + * 'mail_port' - The port to connect. Default is 25 + * 'mail_auth' - Whether or not to use SMTP authentication. Default is + * FALSE + * + * 'mail_username' - The username to use for SMTP authentication. + * 'mail_password' - The password to use for SMTP authentication. + * 'mail_localhost' - The value to give when sending EHLO or + * HELO. Default is localhost + * 'mail_timeout' - The SMTP connection timeout. Default is NULL (no + * timeout) + * 'mail_verp' - Whether to use VERP or not. Default is FALSE + * 'mail_debug' - Whether to enable SMTP debug mode or not. Default is + * FALSE + * 'mail_persist' - Indicates whether or not the SMTP connection + * should persist over multiple calls to the send() + * method. + * + * If you are doing some testing, you should use the smtp backend + * together with fakemail: http://www.lastcraft.com/fakemail.php + */ +class Pluf_Mail +{ + public $headers = array(); + public $message; + public $encoding = 'utf-8'; + public $to_address = ''; + + /** + * Construct the base email. + * + * @param string The email of the sender. + * @param string The destination email. + * @param string The subject of the message. + * @param string Encoding of the message ('UTF-8') + * @param string End of line type ("\n") + */ + function __construct($src, $dest, $subject, $encoding='UTF-8', $crlf="\n") + { + // Note that the Pluf autoloader will correctly load this PEAR + // object. + $this->message = new Mail_mime($crlf); + $this->message->_build_params['html_charset'] = $encoding; + $this->message->_build_params['text_charset'] = $encoding; + $this->message->_build_params['head_charset'] = $encoding; + $this->message->_build_params['ignore-iconv'] = true; + + + $this->to_address = $dest; + $this->headers = array('From' => $src, + 'To' => $dest, + 'Date' => date(DATE_RFC2822), + 'Subject' => $subject, + ); + } + + /** + * Add the base plain text message to the email. + * + * @param string The message + */ + function addTextMessage($msg) + { + $this->message->setTXTBody($msg); + } + + /** + * Set the return path for the email. + * + * @param string Email + */ + function setReturnPath($email) + { + $this->headers['Return-Path'] = $email; + } + + /** + * Add headers to an email. + * + * @param array Array of headers + */ + function addHeaders($hdrs) + { + $this->headers = array_merge($this->headers, $hdrs); + } + + /** + * Add the alternate HTML message to the email. + * + * @param string The HTML message + */ + function addHtmlMessage($msg) + { + $this->message->setHTMLBody($msg); + } + + /** + * Add an attachment to the message. + * + * The file to attach must be available on disk and you need to + * provide the mimetype of the attachment manually. + * + * @param string Path to the file to be added. + * @param string Mimetype of the file to be added ('text/plain'). + * @return bool True. + */ + function addAttachment($file, $ctype='text/plain') + { + $this->message->addAttachment($file, $ctype); + } + + /** + * Effectively sends the email. + */ + function sendMail() + { + $body = $this->message->get(); + $hdrs = $this->message->headers($this->headers); + + $params = Pluf::pf('mail_', true); // strip the prefix 'mail_' + unset($params['backend']); + $gmail = new Mail(); + $mail = $gmail->factory(Pluf::f('mail_backend', 'mail'), + $params); + if (Pluf::f('send_emails', true)) { + $mail->send($this->to_address, $hdrs, $body); + } + if (defined('IN_UNIT_TESTS')) { + $GLOBALS['_PX_UNIT_TESTS']['emails'][] = array($this->to_address, $hdrs, $body); + } + } +} diff --git a/pluf/src/Pluf/Mail/Batch.php b/pluf/src/Pluf/Mail/Batch.php new file mode 100644 index 0000000..843aab4 --- /dev/null +++ b/pluf/src/Pluf/Mail/Batch.php @@ -0,0 +1,233 @@ + + * $email = new Pluf_Mail_Batch('from_email@example.com'); + * foreach($emails as $m) { + * $email->setSubject($m['subject']); + * $email->setTo($m['to']); + * $img_id = $email->addAttachment('/var/www/html/img/pic.jpg', 'image/jpg'); + * $email->addTextMessage($m['content']); + * $email->sendMail(); + * } + * $email->close(); + * + * + * The configuration parameters are the one for Mail::factory with the + * 'mail_' prefix not to conflict with the other parameters. + * + * @see http://pear.php.net/manual/en/package.mail.mail.factory.php + * + * 'mail_backend' - 'mail', 'smtp' or 'sendmail' (default 'mail'). + * + * List of parameter for the backends: + * + * mail backend + * -------------- + * + * If safe mode is disabled, an array with all the 'mail_*' parameters + * excluding 'mail_backend' will be passed as the fifth argument to + * the PHP mail() function. The elements will be joined as a + * space-delimited string. + * + * sendmail backend + * ------------------ + * + * 'mail_sendmail_path' - The location of the sendmail program on the + * filesystem. Default is /usr/bin/sendmail + * 'sendmail_args' - Additional parameters to pass to the + * sendmail. Default is -i + * + * smtp backend + * -------------- + * + * 'mail_host' - The server to connect. Default is localhost + * 'mail_port' - The port to connect. Default is 25 + * 'mail_auth' - Whether or not to use SMTP authentication. Default is + * FALSE + * + * 'mail_username' - The username to use for SMTP authentication. + * 'mail_password' - The password to use for SMTP authentication. + * 'mail_localhost' - The value to give when sending EHLO or + * HELO. Default is localhost + * 'mail_timeout' - The SMTP connection timeout. Default is NULL (no + * timeout) + * 'mail_verp' - Whether to use VERP or not. Default is FALSE + * 'mail_debug' - Whether to enable SMTP debug mode or not. Default is + * FALSE + * 'mail_persist' - Will automatically be set to true. + * + * If you are doing some testing, you should use the smtp backend + * together with fakemail: http://www.lastcraft.com/fakemail.php + */ +class Pluf_Mail_Batch +{ + public $headers = array(); + public $message; + public $encoding = 'utf-8'; + public $crlf = "\n"; + public $from = ''; + protected $backend = null; + + /** + * Construct the base email. + * + * @param string The email of the sender. + * @param string Encoding of the message ('UTF-8') + * @param string End of line type ("\n") + */ + function __construct($src, $encoding='UTF-8', $crlf="\n") + { + // Note that the Pluf autoloader will correctly load this PEAR + // object. + $this->message = new Mail_mime($crlf); + $this->message->_build_params['html_charset'] = $encoding; + $this->message->_build_params['text_charset'] = $encoding; + $this->message->_build_params['head_charset'] = $encoding; + $this->headers = array('From' => $src); + $this->encoding = $encoding; + $this->crlf = $crlf; + $this->from = $src; + } + + /** + * Set the subject of the email. + * + * @param string Subject + */ + function setSubject($subject) + { + $this->headers['Subject'] = $subject; + } + + /** + * Set the recipient of the email. + * + * @param string Recipient email + */ + function setTo($email) + { + $this->headers['To'] = $email; + } + + /** + * Add the base plain text message to the email. + * + * @param string The message + */ + function addTextMessage($msg) + { + $this->message->setTXTBody($msg); + } + + /** + * Set the return path for the email. + * + * @param string Email + */ + function setReturnPath($email) + { + $this->headers['Return-Path'] = $email; + } + + /** + * Add headers to an email. + * + * @param array Array of headers + */ + function addHeaders($hdrs) + { + $this->headers = array_merge($this->headers, $hdrs); + } + + /** + * Add the alternate HTML message to the email. + * + * @param string The HTML message + */ + function addHtmlMessage($msg) + { + $this->message->setHTMLBody($msg); + } + + /** + * Add an attachment to the message. + * + * The file to attach must be available on disk and you need to + * provide the mimetype of the attachment manually. + * + * @param string Path to the file to be added. + * @param string Mimetype of the file to be added ('text/plain'). + * @return bool True. + */ + function addAttachment($file, $ctype='text/plain') + { + $this->message->addAttachment($file, $ctype); + } + + /** + * Effectively sends the email. + */ + function sendMail() + { + if ($this->backend === null) { + $params = Pluf::pf('mail_', true); // strip the prefix 'mail_' + unset($params['backend']); + $gmail = new Mail(); + if (Pluf::f('mail_backend') == 'smtp') { + $params['persist'] = true; + } + $this->backend = $gmail->factory(Pluf::f('mail_backend', 'mail'), + $params); + } + $body = $this->message->get(); + $hdrs = $this->message->headers($this->headers); + if (Pluf::f('send_emails', true)) { + $this->backend->send($this->headers['To'], $hdrs, $body); + } + $this->message = new Mail_mime($this->crlf); + $this->message->_build_params['html_charset'] = $this->encoding; + $this->message->_build_params['text_charset'] = $this->encoding; + $this->message->_build_params['head_charset'] = $this->encoding; + $this->headers = array('From' => $this->from); + } + + function close() + { + unset($this->backend); + $this->backend = null; + } +} diff --git a/pluf/src/Pluf/Message.php b/pluf/src/Pluf/Message.php new file mode 100644 index 0000000..71a7984 --- /dev/null +++ b/pluf/src/Pluf/Message.php @@ -0,0 +1,59 @@ +_a['table'] = 'messages'; + $this->_a['model'] = 'Pluf_Message'; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + //It is automatically added. + 'blank' => true, + ), + 'user' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => Pluf::f('pluf_custom_user','Pluf_User'), + 'blank' => false, + 'verbose' => __('user'), + ), + 'message' => + array( + 'type' => 'Pluf_DB_Field_Text', + 'blank' => false, + ), + ); + } + + function __toString() + { + return $this->message; + } +} diff --git a/pluf/src/Pluf/Middleware/Csrf.php b/pluf/src/Pluf/Middleware/Csrf.php new file mode 100644 index 0000000..ea166b2 --- /dev/null +++ b/pluf/src/Pluf/Middleware/Csrf.php @@ -0,0 +1,124 @@ +method != 'POST') { + return false; + } + $cookie_name = Pluf::f('session_cookie_id', 'sessionid'); + if (!isset($request->COOKIE[$cookie_name])) { + // no session, nothing to do + return false; + } + try { + $data = Pluf_Middleware_Session::_decodeData($request->COOKIE[$cookie_name]); + } catch (Exception $e) { + // no valid session + return false; + } + if (!isset($data['Pluf_Session_key'])) { + // no session key + return false; + } + $token = self::makeToken($data['Pluf_Session_key']); + if (!isset($request->POST['csrfmiddlewaretoken'])) { + return new Pluf_HTTP_Response_Forbidden($request); + } + if ($request->POST['csrfmiddlewaretoken'] != $token) { + return new Pluf_HTTP_Response_Forbidden($request); + } + return false; + } + + /** + * Process the response of a view. + * + * If we find a POST form, add the token to it. + * + * @param Pluf_HTTP_Request The request + * @param Pluf_HTTP_Response The response + * @return Pluf_HTTP_Response The response + */ + function process_response($request, $response) + { + $cookie_name = Pluf::f('session_cookie_id', 'sessionid'); + if (!isset($request->COOKIE[$cookie_name])) { + // no session, nothing to do + return $response; + } + if (!isset($response->headers['Content-Type'])) { + return $response; + } + try { + $data = Pluf_Middleware_Session::_decodeData($request->COOKIE[$cookie_name]); + } catch (Exception $e) { + // no valid session + return $response; + } + if (!isset($data['Pluf_Session_key'])) { + // no session key + return $response; + } + $ok = false; + $cts = array('text/html', 'application/xhtml+xml'); + foreach ($cts as $ct) { + if (false !== strripos($response->headers['Content-Type'], $ct)) { + $ok = true; + break; + } + } + if (!$ok) { + return $response; + } + $token = self::makeToken($data['Pluf_Session_key']); + $extra = '
'; + $response->content = preg_replace('/(]*\bmethod=(\'|"|)POST(\'|"|)\b[^>]*>)/i', '$1'.$extra, $response->content); + return $response; + } +} \ No newline at end of file diff --git a/pluf/src/Pluf/Middleware/Debug.php b/pluf/src/Pluf/Middleware/Debug.php new file mode 100644 index 0000000..d91ac98 --- /dev/null +++ b/pluf/src/Pluf/Middleware/Debug.php @@ -0,0 +1,132 @@ +status_code, + array(200, 201, 202, 203, 204, 205, 206, 404, 501))) { + return $response; + } + $ok = false; + $cts = array('text/html', 'text/html', 'application/xhtml+xml'); + foreach ($cts as $ct) { + if (false !== strripos($response->headers['Content-Type'], $ct)) { + $ok = true; + break; + } + } + if ($ok == false) { + return $response; + } + $js = ''; + $text = '
';
+        $text .= 'Peak mem: '.(int)(memory_get_peak_usage()/1024).'kB'."\n";
+        $text .= 'Exec time: '.sprintf('%.5f', (microtime(true) - $GLOBALS['_PX_starttime'])).'s'."\n";
+        $included_files = get_included_files();
+        sort($included_files);
+        $text .= '';
+        $text .= 'Included files #: '.count($included_files);
+        $text .= '
'."\n"; + $text .= $js.'
';
+        foreach ($included_files as $filename) {
+            $text .= htmlspecialchars($filename)."\n";
+        }
+        $text .= '
'; + if (isset($GLOBALS['_PX_debug_data']['sql_queries'])) { + $text .= '
';            
+            $text .= '';
+            $text .= 'DB query #: '.count($GLOBALS['_PX_debug_data']['sql_queries']);
+            $text .= ''."\n\n";
+            $text .= '
'; + $text .= '
';
+            foreach ($GLOBALS['_PX_debug_data']['sql_queries'] as $q) {
+                $text .= htmlspecialchars($q)."\n";
+            }
+            $text .= '
'; + } else { + $text .= ''; + } + $text .= ''; + + $response->content = str_replace('', $text.'', $response->content); + return $response; + } +} diff --git a/pluf/src/Pluf/Middleware/GoogleAnalytics.php b/pluf/src/Pluf/Middleware/GoogleAnalytics.php new file mode 100644 index 0000000..0a1a9a7 --- /dev/null +++ b/pluf/src/Pluf/Middleware/GoogleAnalytics.php @@ -0,0 +1,72 @@ +status_code, + array(200, 201, 202, 203, 204, 205, 206, 404, 501))) { + return $response; + } + $ok = false; + $cts = array('text/html', 'text/html', 'application/xhtml+xml'); + foreach ($cts as $ct) { + if (false !== strripos($response->headers['Content-Type'], $ct)) { + $ok = true; + break; + } + } + if ($ok == false) { + return $response; + } + $js = ' +'; + $response->content = str_replace('', $js.'', $response->content); + return $response; + } +} diff --git a/pluf/src/Pluf/Middleware/Maintenance.php b/pluf/src/Pluf/Middleware/Maintenance.php new file mode 100644 index 0000000..8535802 --- /dev/null +++ b/pluf/src/Pluf/Middleware/Maintenance.php @@ -0,0 +1,57 @@ +query, Pluf::f('maintenance_root')) && file_exists(Pluf::f('tmp_folder').'/MAINTENANCE')) { + $res = new Pluf_HTTP_Response('Server in maintenance'."\n\n".'We are upgrading the system to make it better for you, please try again later...', 'text/plain'); + $res->status_code = 503; + return $res; + } + return false; + } +} diff --git a/pluf/src/Pluf/Middleware/ReadOnly.php b/pluf/src/Pluf/Middleware/ReadOnly.php new file mode 100644 index 0000000..d903eb1 --- /dev/null +++ b/pluf/src/Pluf/Middleware/ReadOnly.php @@ -0,0 +1,107 @@ + + * $cfg['middleware_classes'] = array( + * 'Pluf_Middleware_ReadOnly', + * 'Pluf_Middleware_Csrf', + * 'Pluf_Middleware_Session', + * 'Pluf_Middleware_Translation', + * ); + * $cfg['read_only_mode_message'] = 'The server is in read only mode the ' + * .'time to be migrated on another host.' + * .'Thank you for your patience.'; + * + * + * You can put HTML in your message. + * + */ +class Pluf_Middleware_ReadOnly +{ + /** + * Process the request. + * + * @param Pluf_HTTP_Request The request + * @return bool false + */ + function process_request(&$request) + { + if ($request->method == 'POST') { + $res = new Pluf_HTTP_Response('Server in read only mode'."\n\n".'We are upgrading the system to make it better for you, please try again later...', 'text/plain'); + $res->status_code = 503; + return $res; + } + return false; + } + + /** + * Process the response of a view. + * + * If configured, add the message to inform that the website is in + * read only mode. + * + * @param Pluf_HTTP_Request The request + * @param Pluf_HTTP_Response The response + * @return Pluf_HTTP_Response The response + */ + function process_response($request, $response) + { + if (!Pluf::f('read_only_mode_message', false)) { + return $response; + } + if (!in_array($response->status_code, + array(200, 201, 202, 203, 204, 205, 206, 404, 501))) { + return $response; + } + $ok = false; + $cts = array('text/html', 'application/xhtml+xml'); + foreach ($cts as $ct) { + if (false !== strripos($response->headers['Content-Type'], $ct)) { + $ok = true; + break; + } + } + if ($ok == false) { + return $response; + } + $message = Pluf::f('read_only_mode_message'); + $response->content = str_replace('', '
'.$message.'
', $response->content); + return $response; + } + +} diff --git a/pluf/src/Pluf/Middleware/Session.php b/pluf/src/Pluf/Middleware/Session.php new file mode 100644 index 0000000..4367a3e --- /dev/null +++ b/pluf/src/Pluf/Middleware/Session.php @@ -0,0 +1,197 @@ +user. + * + * FIXME: We should logout everybody when the session table is emptied. + * + * @param Pluf_HTTP_Request The request + * @return bool false + */ + function process_request(&$request) + { + $session = new Pluf_Session(); + $user_model = Pluf::f('pluf_custom_user','Pluf_User'); + $user = new $user_model(); + if (!isset($request->COOKIE[$session->cookie_name])) { + // No session is defined. We set an empty user and empty + // session. + $request->user = $user; + $request->session = $session; + if (isset($request->COOKIE[$request->session->test_cookie_name])) { + $request->session->test_cookie = $request->COOKIE[$request->session->test_cookie_name]; + } + return false; + } + try { + $data = self::_decodeData($request->COOKIE[$session->cookie_name]); + } catch (Exception $e) { + $request->user = $user; + $request->session = $session; + if (isset($request->COOKIE[$request->session->test_cookie_name])) { + $request->session->test_cookie = $request->COOKIE[$request->session->test_cookie_name]; + } + return false; + } + $set_lang = false; + if (isset($data[$user->session_key])) { + // We can get the corresponding user + $found_user = new $user_model($data[$user->session_key]); + if ($found_user->id == $data[$user->session_key]) { + // User found! + $request->user = $found_user; + // If the last login is from 12h or more, set it to + // now. + Pluf::loadFunction('Pluf_Date_Compare'); + if (43200 < Pluf_Date_Compare($request->user->last_login)) { + $request->user->last_login = gmdate('Y-m-d H:i:s'); + $request->user->update(); + } + $set_lang = $found_user->language; + } else { + $request->user = $user; + } + } else { + $request->user = $user; + } + if (isset($data['Pluf_Session_key'])) { + $sql = new Pluf_SQL('session_key=%s' ,$data['Pluf_Session_key']); + $found_session = Pluf::factory('Pluf_Session')->getList(array('filter' => $sql->gen())); + if (isset($found_session[0])) { + $request->session = $found_session[0]; + } else { + $request->session = $session; + } + } else { + $request->session = $session; + } + if ($set_lang and false == $request->session->getData('pluf_language', false)) { + $request->session->setData('pluf_language', $set_lang); + } + if (isset($request->COOKIE[$request->session->test_cookie_name])) { + $request->session->test_cookie = $request->COOKIE[$request->session->test_cookie_name]; + } + return false; + } + + /** + * Process the response of a view. + * + * If the session has been modified save it into the database. + * Add the session cookie to the response. + * + * @param Pluf_HTTP_Request The request + * @param Pluf_HTTP_Response The response + * @return Pluf_HTTP_Response The response + */ + function process_response($request, $response) + { + if ($request->session->touched) { + if ($request->session->id > 0) { + $request->session->update(); + } else { + $request->session->create(); + } + $data = array(); + if ($request->user->id > 0) { + $data[$request->user->session_key] = $request->user->id; + } + $data['Pluf_Session_key'] = $request->session->session_key; + $response->cookies[$request->session->cookie_name] = self::_encodeData($data); + } + if ($request->session->set_test_cookie != false) { + $response->cookies[$request->session->test_cookie_name] = $request->session->test_cookie_value; + } + return $response; + } + + /** + * Encode the cookie data and create a check with the secret key. + * + * @param mixed Data to encode + * @return string Encoded data ready for the cookie + */ + public static function _encodeData($data) + { + if ('' == ($key = Pluf::f('secret_key'))) { + throw new Exception('Security error: "secret_key" is not set in the configuration file.'); + } + $data = serialize($data); + return base64_encode($data).md5(base64_encode($data).$key); + } + + /** + * Decode the data and check that the data have not been tampered. + * + * If the data have been tampered an exception is raised. + * + * @param string Encoded data + * @return mixed Decoded data + */ + public static function _decodeData($encoded_data) + { + $check = substr($encoded_data, -32); + $base64_data = substr($encoded_data, 0, strlen($encoded_data)-32); + if (md5($base64_data.Pluf::f('secret_key')) != $check) { + throw new Exception('The session data may have been tampered.'); + } + return unserialize(base64_decode($base64_data)); + } + + public static function processContext($signal, &$params) + { + $params['context'] = array_merge($params['context'], + Pluf_Middleware_Session_ContextPreProcessor($params['request'])); + } +} + +/** + * Context preprocessor. + * + * Set the $user key. + * + * @param Pluf_HTTP_Request Request object + * @return array Array to merge with the context + */ +function Pluf_Middleware_Session_ContextPreProcessor($request) +{ + return array('user' => $request->user); +} + +Pluf_Signal::connect('Pluf_Template_Context_Request::construct', + array('Pluf_Middleware_Session', 'processContext')); \ No newline at end of file diff --git a/pluf/src/Pluf/Middleware/Stats.php b/pluf/src/Pluf/Middleware/Stats.php new file mode 100644 index 0000000..d52f1b0 --- /dev/null +++ b/pluf/src/Pluf/Middleware/Stats.php @@ -0,0 +1,67 @@ +status_code, + array(200, 201, 202, 203, 204, 205, 206, 404, 501))) { + return $response; + } + $ok = false; + $cts = array('text/html', 'text/html', 'application/xhtml+xml'); + foreach ($cts as $ct) { + if (false !== strripos($response->headers['Content-Type'], $ct)) { + $ok = true; + break; + } + } + if ($ok == false) { + return $response; + } + if (Pluf::f('db_debug')) + $text = "Page rendered in " . sprintf('%.5f', (microtime(true) - $GLOBALS['_PX_starttime'])) . "s using " . count($GLOBALS['_PX_debug_data']['sql_queries']) . " queries."; + else + $text = "Page rendered in " . sprintf('%.5f', (microtime(true) - $GLOBALS['_PX_starttime'])) . "s."; + $response->content = str_replace('', $text.'', $response->content); + return $response; + } +} diff --git a/pluf/src/Pluf/Middleware/Tidy.php b/pluf/src/Pluf/Middleware/Tidy.php new file mode 100644 index 0000000..eec9a6a --- /dev/null +++ b/pluf/src/Pluf/Middleware/Tidy.php @@ -0,0 +1,86 @@ +status_code, + array(200, 201, 202, 203, 204, 205, 206, 404, 501))) { + return $response; + } + $ok = false; + $cts = array('text/html', 'application/xhtml+xml'); + foreach ($cts as $ct) { + if (false !== strripos($response->headers['Content-Type'], $ct)) { + $ok = true; + break; + } + } + if ($ok == false) { + return $response; + } + $content = escapeshellarg($response->content); + $res = array(); + $rval = 0; + exec('(echo '.$content.'| tidy -e -utf8 -q 3>&2 2>&1 1>&3) ', $res, $rval); + if (empty($res)) { + return $response; + } + $only_char_encoding_issue = Pluf::f('tidy_skip_encoding_errors', true); + foreach ($res as $line) { + if (false === strpos($line, 'invalid character code')) { + $only_char_encoding_issue = false; + break; + } + } + if ($only_char_encoding_issue == true) { + return $response; + } + $response->content = str_replace('', '
'.htmlspecialchars(join("\n", $res)).'
', $response->content); + return $response; + } +} diff --git a/pluf/src/Pluf/Middleware/Translation.php b/pluf/src/Pluf/Middleware/Translation.php new file mode 100644 index 0000000..b9c072a --- /dev/null +++ b/pluf/src/Pluf/Middleware/Translation.php @@ -0,0 +1,87 @@ +session)) { + $lang = $request->session->getData('pluf_language', false); + if ($lang and !in_array($lang, Pluf::f('languages', array('en')))) { + $lang = false; + } + } + if ($lang === false and !empty($request->COOKIE[Pluf::f('lang_cookie', 'pluf_language')])) { + $lang = $request->COOKIE[Pluf::f('lang_cookie', 'pluf_language')]; + if ($lang and !in_array($lang, Pluf::f('languages', array('en')))) { + $lang = false; + } + } + if ($lang === false) { + // will default to 'en' + $lang = Pluf_Translation::getAcceptedLanguage(Pluf::f('languages', array('en'))); + } + Pluf_Translation::loadSetLocale($lang); + $request->language_code = $lang; + return false; + } + + /** + * Process the response of a view. + * + * @param Pluf_HTTP_Request The request + * @param Pluf_HTTP_Response The response + * @return Pluf_HTTP_Response The response + */ + function process_response($request, $response) + { + $vary_h = array(); + if (!empty($response->headers['Vary'])) { + $vary_h = preg_split('/\s*,\s*/', $response->headers['Vary'], + -1, PREG_SPLIT_NO_EMPTY); + } + if (!in_array('accept-language', $vary_h)) { + $vary_h[] = 'accept-language'; + } + $response->headers['Vary'] = implode(', ', $vary_h); + $response->headers['Content-Language'] = $request->language_code; + return $response; + } +} \ No newline at end of file diff --git a/pluf/src/Pluf/Migration.php b/pluf/src/Pluf/Migration.php new file mode 100644 index 0000000..fd778db --- /dev/null +++ b/pluf/src/Pluf/Migration.php @@ -0,0 +1,362 @@ + + * $m = new Pluf_Migration('MyApp'); + * $m->migrate(); + * + * // Install the application MyApp + * $m = new Pluf_Migration('MyApp'); + * $m->install(); + * // Uninstall the application MyApp + * $m->unInstall(); + * + * $m = new Pluf_Migration(); + * $m->migrate(); // migrate all the installed app to the newest version. + * + * $m = new Pluf_Migration(); + * $m->migrate(3); // migrate (upgrade or downgrade) to version 3 + * + * + */ +class Pluf_Migration +{ + protected $app = ''; /**< Application beeing migrated. */ + public $apps = array(); /**< Applications which are going to be migrated. */ + public $to_version = null; /**< Target version for the migration. */ + public $dry_run = false; /**< Set to true to not act. */ + public $display = false; /**< Display on the console what is done. */ + + /** + * Create a new migration. + * + * @param mixed Application or array of applications to migrate. + */ + public function __construct($app=null) + { + if (!is_null($app)) { + if (is_array($app)) { + $this->apps = $app; + } else { + $this->apps = array($app); + } + } else { + $this->apps = Pluf::f('installed_apps'); + } + } + + + /** + * Install the application. + * + * Basically run the base install function for each application + * and then set the version to the latest migration. + */ + public function install() + { + foreach ($this->apps as $app) { + $this->installApp($app); + } + return true; + } + + /** + * Uninstall the application. + */ + public function unInstall() + { + $apps = array_reverse($this->apps); + foreach ($apps as $app) { + $this->installApp($app, true); + } + } + + /** + * Backup the application. + * + * @param string Path to the backup folder + * @param string Backup name (null) + */ + public function backup($path, $name=null) + { + foreach ($this->apps as $app) { + $func = $app.'_Migrations_Backup_run'; + Pluf::loadFunction($func); + if ($this->display) { + echo($func."\n"); + } + if (!$this->dry_run) { + $ret = $func($path, $name); + } + } + return true; + } + + /** + * Restore the application. + * + * @param string Path to the backup folder + * @param string Backup name + */ + public function restore($path, $name) + { + foreach ($this->apps as $app) { + $func = $app.'_Migrations_Backup_restore'; + Pluf::loadFunction($func); + if ($this->display) { + echo($func."\n"); + } + if (!$this->dry_run) { + $ret = $func($path, $name); + } + } + return true; + } + + /** + * Run the migration. + * + */ + public function migrate($to_version=null) + { + $this->to_version = $to_version; + foreach ($this->apps as $app) { + $this->app = $app; + $migrations = $this->findMigrations(); + // The run will throw an exception in case of error. + $this->runMigrations($migrations); + } + return true; + } + + /** + * Un/Install the given application. + * + * @param string Application to install. + * @param bool Uninstall (false) + */ + public function installApp($app, $uninstall=false) + { + if ($uninstall) { + $func = $app.'_Migrations_Install_teardown'; + } else { + $func = $app.'_Migrations_Install_setup'; + } + $ret = true; + Pluf::loadFunction($func); + if ($this->display) { + echo($func."\n"); + } + if (!$this->dry_run) { + $ret = $func(); // Run the install/uninstall + if (!$uninstall) { + // + $this->app = $app; + $migrations = $this->findMigrations(); + if (count($migrations) > 0) { + $to_version = max(array_keys($migrations)); + } else { + $to_version = 0; + } + $this->setAppVersion($app, $to_version); + } else { + if ($app != 'Pluf') { + // If Pluf we do not have the schema info table + // anymore + $this->delAppInfo($app); + } + } + } + return $ret; + } + + + /** + * Find the migrations for the current app. + * + * @return array Migrations names indexed by order. + */ + public function findMigrations() + { + $migrations = array(); + if (false !== ($mdir = Pluf::fileExists($this->app.'/Migrations'))) { + $dir = new DirectoryIterator($mdir); + foreach($dir as $file) { + $matches = array(); + if (!$file->isDot() && !$file->isDir() + && preg_match('#^(\d+)#', $file->getFilename(), $matches)) { + $info = pathinfo($file->getFilename()); + $migrations[(int)$matches[1]] = $info['filename']; + } + } + } + return $migrations; + } + + /** + * Run the migrations. + * + * From an array of possible migrations, it will first get the + * current version of the app and then based on $this->to_version + * will run the migrations in the right order or do nothing if + * nothing to be done. + * + * @param array Possible migrations. + */ + public function runMigrations($migrations) + { + if (empty($migrations)) { + return; + } + $current = $this->getAppVersion($this->app); + if ($this->to_version === null) { + $to_version = max(array_keys($migrations)); + } else { + $to_version = $this->to_version; + } + if ($to_version == $current) { + return; // Nothing to do + } + $the_way = 'up'; // Tribute to Pat Metheny + if ($to_version > $current) { + // upgrade + $min = $current + 1; + $max = $to_version; + } else { + // downgrade + $the_way = 'do'; + $max = $current; + $min = $to_version + 1; + } + // Filter the migrations + $to_run = array(); + foreach ($migrations as $order=>$name) { + if ($order < $min or $order > $max) { + continue; + } + if ($the_way == 'up') { + $to_run[] = array($order, $name); + } else { + array_unshift($to_run, array($order, $name)); + } + } + asort($to_run); + // Run the migrations + foreach ($to_run as $migration) { + $this->runMigration($migration, $the_way); + } + } + + /** + * Run the given migration. + */ + public function runMigration($migration, $the_way='up') + { + $target_version = ($the_way == 'up') ? $migration[0] : $migration[0]-1; + if ($this->display) { + echo($migration[0].' '.$migration[1].' '.$the_way."\n"); + } + if (!$this->dry_run) { + if ($the_way == 'up') { + $func = $this->app.'_Migrations_'.$migration[1].'_up'; + } else { + $func = $this->app.'_Migrations_'.$migration[1].'_down'; + } + Pluf::loadFunction($func); + $func(); // Real migration run + $this->setAppVersion($this->app, $target_version); + } + } + + /** + * Set the application version. + * + * @param string Application + * @param int Version + * @return true + */ + public function setAppVersion($app, $version) + { + $gschema = new Pluf_DB_SchemaInfo(); + $sql = new Pluf_SQL('application=%s', $app); + $appinfo = $gschema->getList(array('filter' => $sql->gen())); + if ($appinfo->count() == 1) { + $appinfo[0]->version = $version; + $appinfo[0]->update(); + } else { + $schema = new Pluf_DB_SchemaInfo(); + $schema->application = $app; + $schema->version = $version; + $schema->create(); + } + return true; + } + + /** + * Remove the application information. + * + * @param string Application + * @return true + */ + public function delAppInfo($app) + { + $gschema = new Pluf_DB_SchemaInfo(); + $sql = new Pluf_SQL('application=%s', $app); + $appinfo = $gschema->getList(array('filter' => $sql->gen())); + if ($appinfo->count() == 1) { + $appinfo[0]->delete(); + } + return true; + } + + + + /** + * Get the current version of the app. + * + * @param string Application. + * @return int Version. + */ + public function getAppVersion($app) + { + try { + $db =& Pluf::db(); + $res = $db->select('SELECT version FROM '.$db->pfx.'schema_info WHERE application='.$db->esc($app)); + return (int) $res[0]['version']; + } catch (Exception $e) { + // We should not be here, only in the case of nothing + // installed. I am not sure if this is a good way to + // handle this border case anyway. Maybe better to have an + // 'install' method to run all the migrations in order. + return 0; + } + } +} \ No newline at end of file diff --git a/pluf/src/Pluf/Migrations/1Setup.php b/pluf/src/Pluf/Migrations/1Setup.php new file mode 100644 index 0000000..3c0f51a --- /dev/null +++ b/pluf/src/Pluf/Migrations/1Setup.php @@ -0,0 +1,38 @@ +begin(); // Start a transaction + try { + $schema = new Pluf_DB_Schema($db); + $schema->model = new Pluf_RowPermission(); + $schema->createTables(); + } catch (Exception $e) { + $db->rollback(); + throw $e; + } + $db->commit(); +} + +function Pluf_Migrations_2RowPermission_down($params=null) +{ + $db = Pluf::db(); + $db->begin(); // Start a transaction + try { + $schema = new Pluf_DB_Schema($db); + $schema->model = new Pluf_RowPermission(); + $schema->dropTables(); + } catch (Exception $e) { + $db->rollback(); + throw $e; + } + $db->commit(); +} \ No newline at end of file diff --git a/pluf/src/Pluf/Migrations/3SearchEngine.php b/pluf/src/Pluf/Migrations/3SearchEngine.php new file mode 100644 index 0000000..4a0bd60 --- /dev/null +++ b/pluf/src/Pluf/Migrations/3SearchEngine.php @@ -0,0 +1,60 @@ +begin(); // Start a transaction + try { + $schema = new Pluf_DB_Schema($db); + foreach (array('Pluf_Search_Word', 'Pluf_Search_Occ') as $model) { + $schema->model = new $model(); + $schema->createTables(); + } + } catch (Exception $e) { + $db->rollback(); + throw $e; + } + $db->commit(); +} + +function Pluf_Migrations_3SearchEngine_down($params=null) +{ + $db = Pluf::db(); + $db->begin(); // Start a transaction + try { + $schema = new Pluf_DB_Schema($db); + foreach (array('Pluf_Search_Occ', 'Pluf_Search_Word') as $model) { + $schema->model = new $model(); + $schema->dropTables(); + } + } catch (Exception $e) { + $db->rollback(); + throw $e; + } + $db->commit(); +} \ No newline at end of file diff --git a/pluf/src/Pluf/Migrations/4QueueStats.php b/pluf/src/Pluf/Migrations/4QueueStats.php new file mode 100644 index 0000000..c8cc8d8 --- /dev/null +++ b/pluf/src/Pluf/Migrations/4QueueStats.php @@ -0,0 +1,60 @@ +begin(); // Start a transaction + try { + $schema = new Pluf_DB_Schema($db); + foreach (array('Pluf_Search_Stats', 'Pluf_Queue') as $model) { + $schema->model = new $model(); + $schema->createTables(); + } + } catch (Exception $e) { + $db->rollback(); + throw $e; + } + $db->commit(); +} + +function Pluf_Migrations_4QueueStats_down($params=null) +{ + $db = Pluf::db(); + $db->begin(); // Start a transaction + try { + $schema = new Pluf_DB_Schema($db); + foreach (array('Pluf_Queue', 'Pluf_Search_Stats') as $model) { + $schema->model = new $model(); + $schema->dropTables(); + } + } catch (Exception $e) { + $db->rollback(); + throw $e; + } + $db->commit(); +} \ No newline at end of file diff --git a/pluf/src/Pluf/Migrations/5UserDetails.php b/pluf/src/Pluf/Migrations/5UserDetails.php new file mode 100644 index 0000000..43fad26 --- /dev/null +++ b/pluf/src/Pluf/Migrations/5UserDetails.php @@ -0,0 +1,65 @@ +begin(); // Start a transaction + try { + // Add 2 new fields. + $user_model = Pluf::f('pluf_custom_user','Pluf_User'); + $guser = new $user_model(); + $table = $guser->getSqlTable(); + $sql = 'ALTER TABLE '.$table."\n" + .'ADD COLUMN language VARCHAR(5) DEFAULT \'en\','."\n" + .'ADD COLUMN timezone VARCHAR(50) DEFAULT \'Europe/Berlin\''."\n"; + $db->execute($sql); + } catch (Exception $e) { + $db->rollback(); + throw $e; + } + $db->commit(); +} + +function Pluf_Migrations_5UserDetails_down($params=null) +{ + $db = Pluf::db(); + $db->begin(); // Start a transaction + try { + $user_model = Pluf::f('pluf_custom_user','Pluf_User'); + $guser = new $user_model(); + $table = $guser->getSqlTable(); + $sql = 'ALTER TABLE '.$table."\n" + .'DROP COLUMN language,'."\n" + .'DROP COLUMN timezone'."\n"; + $db->execute($sql); + } catch (Exception $e) { + $db->rollback(); + throw $e; + } + $db->commit(); +} \ No newline at end of file diff --git a/pluf/src/Pluf/Migrations/Backup.php b/pluf/src/Pluf/Migrations/Backup.php new file mode 100644 index 0000000..6f71b88 --- /dev/null +++ b/pluf/src/Pluf/Migrations/Backup.php @@ -0,0 +1,94 @@ +model = new $model(); + $schema->createTables(); + } + $full_data = json_decode(file_get_contents(sprintf('%s/%s-Pluf.json', $folder, $name)), true); + foreach ($full_data as $model => $data) { + Pluf_Test_Fixture::load($data, false); + } + return true; +} \ No newline at end of file diff --git a/pluf/src/Pluf/Migrations/Install.php b/pluf/src/Pluf/Migrations/Install.php new file mode 100644 index 0000000..b10dee0 --- /dev/null +++ b/pluf/src/Pluf/Migrations/Install.php @@ -0,0 +1,72 @@ +model = new $model(); + $schema->createTables(); + } +} + +function Pluf_Migrations_Install_teardown($params=null) +{ + $models = array('Pluf_Queue', + 'Pluf_Search_Stats', + 'Pluf_Search_Occ', + 'Pluf_Search_Word', + 'Pluf_RowPermission', + 'Pluf_Permission', + 'Pluf_Message', + Pluf::f('pluf_custom_group','Pluf_Group'), + Pluf::f('pluf_custom_user','Pluf_User'), + 'Pluf_Session', + 'Pluf_DB_SchemaInfo', + ); + $db = Pluf::db(); + $schema = new Pluf_DB_Schema($db); + foreach ($models as $model) { + $schema->model = new $model(); + $schema->dropTables(); + } +} \ No newline at end of file diff --git a/pluf/src/Pluf/Model.php b/pluf/src/Pluf/Model.php new file mode 100644 index 0000000..16aef10 --- /dev/null +++ b/pluf/src/Pluf/Model.php @@ -0,0 +1,1064 @@ + 'model', + 'model' => 'Pluf_Model', + 'cols' => array(), + 'idx' => array(), + 'views' => array(), + ); + + /** Storage of the data. + * + * The object data are stored in an associative array. Each key + * corresponds to a column and stores a Pluf_DB_Field_* variable. + */ + protected $_data = array(); + + /** + * Storage cached data for methods_get + */ + protected $_cache = array(); // We should use a global cache. + + /** List of the foreign keys. + * + * Set by the init() method from the definition of the columns. + */ + protected $_fk = array(); + + /** + * Methods available, this array is dynamically populated by init + * method. + */ + protected $_m = array('list' => array(), // get_*_list methods + 'many' => array(), // many to many + 'get' => array(), // foreign keys + 'extra' => array(), // added by some fields + ); + + function __construct($pk=null, $values=array()) + { + $this->_init(); + if ((int) $pk > 0) { + $this->get($pk); //Should not have a side effect + } + } + + + function init() + { + // Define it yourself. + } + + /** + * Define the list of methods for the model from the available + * model relationship. + */ + function _init() + { + $this->_getConnection(); + if (isset($GLOBALS['_PX_models_init_cache'][$this->_model])) { + $init_cache = $GLOBALS['_PX_models_init_cache'][$this->_model]; + $this->_cache = $init_cache['cache']; + $this->_m = $init_cache['m']; + $this->_a = $init_cache['a']; + $this->_fk = $init_cache['fk']; + $this->_data = $init_cache['data']; + return; + } + $this->init(); + foreach ($this->_a['cols'] as $col => $val) { + $field = new $val['type']('', $col); + $col_lower = strtolower($col); + + $type = 'foreignkey'; + if ($type === $field->type) { + $this->_m['get']['get_'.$col_lower] = array($val['model'], $col); + $this->_cache['fk'][$col] = $type; + $this->_fk[$col] = $type; + } + + $type = 'manytomany'; + if ($type === $field->type) { + $this->_m['list']['get_'.$col_lower.'_list'] = $val['model']; + $this->_m['many'][$val['model']] = $type; + } + + foreach ($field->methods as $method) { + $this->_m['extra'][$method[0]] = array($col_lower, $method[1]); + } + + if (array_key_exists('default', $val)) { + $this->_data[$col] = $val['default']; + } else { + $this->_data[$col] = ''; + } + } + + $this->_setupAutomaticListMethods('foreignkey'); + $this->_setupAutomaticListMethods('manytomany'); + + $GLOBALS['_PX_models_init_cache'][$this->_model] = array( + 'cache' => $this->_cache, + 'm' => $this->_m, + 'a' => $this->_a, + 'fk' => $this->_fk, + 'data' => $this->_data, + ); + } + + /** + * Retrieve key relationships of a given model. + * + * @param string $model + * @param string $type Relation type: 'foreignkey' or 'manytomany'. + * @return array Key relationships. + */ + public function getRelationKeysToModel($model, $type) + { + $keys = array(); + foreach ($this->_a['cols'] as $col => $val) { + if (isset($val['model']) && $model === $val['model']) { + $field = new $val['type'](); + if ($type === $field->type) { + $keys[$col] = $val; + } + } + } + + return $keys; + } + + /** + * Get the foreign keys relating to a given model. + * + * @deprecated Use {@link self::getRelationKeysToModel()} instead. + * @param string Model + * @return array Foreign keys + */ + function getForeignKeysToModel($model) + { + return $this->getRelationKeysToModel($model, 'foreignkey'); + } + + /** + * Get the raw data of the object. + * + * For the many to many relations, the value is an array of ids. + * + * @return array Associative array of the data. + */ + function getData() + { + foreach ($this->_a['cols'] as $col=>$val) { + $field = new $val['type'](); + if ($field->type == 'manytomany') { + $this->_data[$col] = array(); + $method = 'get_'.strtolower($col).'_list'; + foreach ($this->$method() as $item) { + $this->_data[$col][] = $item->id; + } + } + } + return $this->_data; + } + + /** + * Set the association of a model to another in many to many. + * + * @param object Object to associate to the current object + */ + function setAssoc($model) + { + if (!$this->delAssoc($model)) { + return false; + } + $hay = array(strtolower($model->_a['model']), strtolower($this->_a['model'])); + sort($hay); + $table = $hay[0].'_'.$hay[1].'_assoc'; + $req = 'INSERT INTO '.$this->_con->pfx.$table."\n"; + $req .= '('.$this->_con->qn(strtolower($this->_a['model']).'_id').', ' + .$this->_con->qn(strtolower($model->_a['model']).'_id').') VALUES '."\n"; + $req .= '('.$this->_toDb($this->_data['id'], 'id').', '; + $req .= $this->_toDb($model->id, 'id').')'; + $this->_con->execute($req); + return true; + } + + /** + * Set the association of a model to another in many to many. + * + * @param object Object to associate to the current object + */ + function delAssoc($model) + { + + //check if ok to make the association + //current model has a many to many key with $model + //$model has a many to many key with current model + if (!isset($this->_m['many'][$model->_a['model']]) + or strlen($this->_data['id']) == 0 + or strlen($model->id) == 0) { + return false; + } + $hay = array(strtolower($model->_a['model']), strtolower($this->_a['model'])); + sort($hay); + $table = $hay[0].'_'.$hay[1].'_assoc'; + $req = 'DELETE FROM '.$this->_con->pfx.$table.' WHERE'."\n"; + $req .= $this->_con->qn(strtolower($this->_a['model']).'_id').' = '.$this->_toDb($this->_data['id'], 'id'); + $req .= ' AND '.$this->_con->qn(strtolower($model->_a['model']).'_id').' = '.$this->_toDb($model->id, 'id'); + $this->_con->execute($req); + return true; + } + + /** + * Bulk association of models to the current one. + * + * @param string Model name + * @param array Ids of Model name + * @return bool Success + */ + function batchAssoc($model_name, $ids) + { + $currents = $this->getRelated($model_name); + foreach ($currents as $cur) { + $this->delAssoc($cur); + } + foreach ($ids as $id) { + $m = new $model_name($id); + if ($m->id == $id) { + $this->setAssoc($m); + } + } + return true; + } + + /** + * Get a database connection. + */ + function _getConnection() + { + static $con = null; + if ($this->_con !== null) { + return $this->_con; + } + if ($con !== null) { + $this->_con = $con; + return $this->_con; + } + $this->_con = &Pluf::db($this); + $con = $this->_con; + return $this->_con; + } + + /** + * Get a database connection. + */ + function getDbConnection() + { + return $this->_getConnection(); + } + + /** + * Get the table of the model. + * + * Avoid doing the concatenation of the prefix and the table + * manually. + */ + function getSqlTable() + { + return $this->_con->pfx.$this->_a['table']; + } + + /** + * Overloading of the get method. + * + * @param string Property to get + */ + function __get($prop) + { + return (array_key_exists($prop, $this->_data)) ? + $this->_data[$prop] : $this->__call($prop, array()); + } + + /** + * Overloading of the set method. + * + * @param string Property to set + * @param mixed Value to set + */ + function __set($prop, $val) + { + if (null !== $val and isset($this->_cache['fk'][$prop])) { + $this->_data[$prop] = $val->id; + unset($this->_cache['get_'.$prop]); + } else { + $this->_data[$prop] = $val; + } + } + + /** + * Overloading of the method call. + * + * @param string Method + * @param array Arguments + */ + function __call($method, $args) + { + // The foreign keys of the current object. + if (isset($this->_m['get'][$method])) { + if (isset($this->_cache[$method])) { + return $this->_cache[$method]; + } else { + $this->_cache[$method] = Pluf::factory($this->_m['get'][$method][0], $this->_data[$this->_m['get'][$method][1]]); + if ($this->_cache[$method]->id == '') $this->_cache[$method] = null; + return $this->_cache[$method]; + } + } + // Many to many or foreign keys on the other objects. + if (isset($this->_m['list'][$method])) { + if (is_array($this->_m['list'][$method])) { + $model = $this->_m['list'][$method][0]; + } else { + $model = $this->_m['list'][$method]; + } + $args = array_merge(array($model, $method), $args); + return call_user_func_array(array($this, 'getRelated'), $args); + } + // Extra methods added by fields + if (isset($this->_m['extra'][$method])) { + $args = array_merge(array($this->_m['extra'][$method][0], $method, $this), $args); + Pluf::loadFunction($this->_m['extra'][$method][1]); + return call_user_func_array($this->_m['extra'][$method][1], $args); + } + throw new Exception(sprintf('Method "%s" not available.', $method)); + } + + /** + * Get a given item. + * + * @param int Id of the item. + * @return mixed Item or false if not found. + */ + function get($id) + { + $req = 'SELECT * FROM '.$this->getSqlTable().' WHERE id='.$this->_toDb($id, 'id'); + if (false === ($rs = $this->_con->select($req))) { + throw new Exception($this->_con->getError()); + } + if (count($rs) == 0) { + return false; + } + foreach ($this->_a['cols'] as $col => $val) { + $field = new $val['type'](); + if ($field->type != 'manytomany' && array_key_exists($col, $rs[0])) { + $this->_data[$col] = $this->_fromDb($rs[0][$col], $col); + } + } + $this->restore(); + return $this; + } + + /** + * Get one item. + * + * The parameters are the same as the ones of the getList method, + * but, the return value is either: + * + * - The object + * - null if no match + * - Exception if the match results in more than one item. + * + * Usage: + * + *
+     * $m = Pluf::factory('My_Model')->getOne(array('filter' => 'id=1'));
+     * 
+ *
+     * $m = Pluf::factory('My_Model')->getOne('id=1');
+     * 
+ * + * @param array|string Filter string or array given to getList + * @see self::getList + */ + public function getOne($p=array()) + { + if (!is_array($p)) { + $p = array('filter' => $p); + } + $items = $this->getList($p); + if ($items->count() == 1) { + return $items[0]; + } + if ($items->count() == 0) { + return null; + } + throw new Exception(__('Error: More than one matching item found.')); + } + + /** + * Get a list of items. + * + * The filter should be used only for simple filtering. If you want + * a complex query, you should create a new view. + * Both filter and order accept an array or a string in case of multiple + * parameters: + * Filter: + * array('col1=toto', 'col2=titi') will be used in a AND query + * or simply 'col1=toto' + * Order: + * array('col1 ASC', 'col2 DESC') or 'col1 ASC' + * + * This is modelled on the DB_Table pear module interface. + * + * @param array Associative array with the possible following + * keys: + * 'view': The view to use + * 'filter': The where clause to use + * 'order': The ordering of the result set + * 'start': The number of skipped rows in the result set + * 'nb': The number of items to get in the result set + * 'count': Run a count query and not a select if set to true + * @return ArrayObject of items or through an exception if + * database failure + */ + function getList($p=array()) + { + $default = array('view' => null, + 'filter' => null, + 'order' => null, + 'start' => null, + 'select' => null, + 'nb' => null, + 'count' => false); + $p = array_merge($default, $p); + if (!is_null($p['view']) && !isset($this->_a['views'][$p['view']])) { + throw new Exception(sprintf(__('The view "%s" is not defined.'), $p['view'])); + } + $query = array( + 'select' => $this->getSelect(), + 'from' => $this->_a['table'], + 'join' => '', + 'where' => '', + 'group' => '', + 'having' => '', + 'order' => '', + 'limit' => '', + 'props' => array(), + ); + if (!is_null($p['view'])) { + $query = array_merge($query, $this->_a['views'][$p['view']]); + } + if (!is_null($p['select'])) { + $query['select'] = $p['select']; + } + if (!is_null($p['filter'])) { + if (is_array($p['filter'])) { + $p['filter'] = implode(' AND ', $p['filter']); + } + if (strlen($query['where']) > 0) { + $query['where'] .= ' AND '; + } + $query['where'] .= ' ('.$p['filter'].') '; + } + if (!is_null($p['order'])) { + if (is_array($p['order'])) { + $p['order'] = implode(', ', $p['order']); + } + if (strlen($query['order']) > 0 and strlen($p['order']) > 0) { + $query['order'] .= ', '; + } + $query['order'] .= $p['order']; + } + if (!is_null($p['start']) && is_null($p['nb'])) { + $p['nb'] = 10000000; + } + if (!is_null($p['start'])) { + if ($p['start'] != 0) { + $p['start'] = (int) $p['start']; + } + $p['nb'] = (int) $p['nb']; + $query['limit'] = 'LIMIT '.$p['nb'].' OFFSET '.$p['start']; + } + if (!is_null($p['nb']) && is_null($p['start'])) { + $p['nb'] = (int) $p['nb']; + $query['limit'] = 'LIMIT '.$p['nb']; + } + if ($p['count'] == true) { + if (isset($query['select_count'])) { + $query['select'] = $query['select_count']; + } else { + $query['select'] = 'COUNT(*) as nb_items'; + } + $query['order'] = ''; + $query['limit'] = ''; + } + $req = 'SELECT '.$query['select'].' FROM ' + .$this->_con->pfx.$query['from'].' '.$query['join']; + if (strlen($query['where'])) { + $req .= "\n".'WHERE '.$query['where']; + } + if (strlen($query['group'])) { + $req .= "\n".'GROUP BY '.$query['group']; + } + if (strlen($query['having'])) { + $req .= "\n".'HAVING '.$query['having']; + } + if (strlen($query['order'])) { + $req .= "\n".'ORDER BY '.$query['order']; + } + if (strlen($query['limit'])) { + $req .= "\n".$query['limit']; + } + if (false === ($rs=$this->_con->select($req))) { + throw new Exception($this->_con->getError()); + } + if (count($rs) == 0) { + return new ArrayObject(); + } + if ($p['count'] == true) { + return $rs; + } + $res = new ArrayObject(); + foreach ($rs as $row) { + $this->_reset(); + foreach ($this->_a['cols'] as $col => $val) { + if (isset($row[$col])) $this->_data[$col] = $this->_fromDb($row[$col], $col); + } + // FIXME: The associated properties need to be converted too. + foreach ($query['props'] as $prop => $key) { + $this->_data[$key] = (isset($row[$prop])) ? $row[$prop] : null; + } + $this->restore(); + $res[] = clone($this); + } + return $res; + } + + /** + * Get the number of items. + * + * @see getList() for definition of the keys + * + * @param array with associative keys 'view' and 'filter' + * @return int The number of items + */ + function getCount($p=array()) + { + $p['count'] = true; + $count = $this->getList($p); + if (empty($count) or count($count) == 0) { + return 0; + } else { + return (int) $count[0]['nb_items']; + } + } + + /** + * Get a list of related items. + * + * See the getList() method for usage of the view and filters. + * + * @param string Class of the related items + * @param string Method call in a many to many related + * @param array Parameters, see getList() for the definition of + * the keys + * @return array Array of items + */ + function getRelated($model, $method=null, $p=array()) + { + $default = array('view' => null, + 'filter' => null, + 'order' => null, + 'start' => null, + 'nb' => null, + 'count' => false); + $p = array_merge($default, $p); + if ('' == $this->_data['id']) { + return new ArrayObject(); + } + $m = new $model(); + if (isset($this->_m['list'][$method]) + and is_array($this->_m['list'][$method])) { + $foreignkey = $this->_m['list'][$method][1]; + if (strlen($foreignkey) == 0) { + throw new Exception(sprintf(__('No matching foreign key found in model: %s for model %s'), $model, $this->_a['model'])); + } + if (!is_null($p['filter'])) { + if (is_array($p['filter'])) { + $p['filter'] = implode(' AND ', $p['filter']); + } + $p['filter'] .= ' AND '; + } else { + $p['filter'] = ''; + } + $p['filter'] .= $this->_con->qn($foreignkey).'='.$this->_toDb($this->_data['id'], 'id'); + } else { + // Many to many: We generate a special view that is making + // the join + $hay = array(strtolower(Pluf::factory($model)->_a['model']), + strtolower($this->_a['model'])); + sort($hay); + $table = $hay[0].'_'.$hay[1].'_assoc'; + if (isset($m->_a['views'][$p['view']])) { + $m->_a['views'][$p['view'].'__manytomany__'] = $m->_a['views'][$p['view']]; + if (!isset($m->_a['views'][$p['view'].'__manytomany__']['join'])) { + $m->_a['views'][$p['view'].'__manytomany__']['join'] = ''; + } + if (!isset($m->_a['views'][$p['view'].'__manytomany__']['where'])) { + $m->_a['views'][$p['view'].'__manytomany__']['where'] = ''; + } + } else { + $m->_a['views']['__manytomany__'] = array('join' => '', + 'where' => ''); + $p['view'] = ''; + } + $m->_a['views'][$p['view'].'__manytomany__']['join'] .= + ' LEFT JOIN '.$this->_con->pfx.$table.' ON ' + .$this->_con->qn(strtolower($m->_a['model']).'_id').' = '.$this->_con->pfx.$m->_a['table'].'.id'; + + $m->_a['views'][$p['view'].'__manytomany__']['where'] = $this->_con->qn(strtolower($this->_a['model']).'_id').'='.$this->_data['id']; + $p['view'] = $p['view'].'__manytomany__'; + } + return $m->getList($p); + } + + /** + * Generate the SQL select from the columns + */ + function getSelect() + { + if (isset($this->_cache['getSelect'])) return $this->_cache['getSelect']; + $select = array(); + $table = $this->getSqlTable(); + foreach ($this->_a['cols'] as $col=>$val) { + if ($val['type'] != 'Pluf_DB_Field_Manytomany') { + $select[] = $table.'.'.$this->_con->qn($col).' AS '.$this->_con->qn($col); + } + } + $this->_cache['getSelect'] = implode(', ', $select); + return $this->_cache['getSelect']; + } + + /** + * Update the model into the database. + * + * If no where clause is provided, the index definition is used to + * find the sequence. These are used to limit the update + * to the current model. + * + * @param string Where clause to update specific items. ('') + * @return bool Success + */ + function update($where='') + { + $this->preSave(); + $req = 'UPDATE '.$this->getSqlTable().' SET'."\n"; + $fields = array(); + $assoc = array(); + foreach ($this->_a['cols'] as $col=>$val) { + $field = new $val['type'](); + if ($col == 'id') { + continue; + } elseif ($field->type == 'manytomany') { + if (is_array($this->$col)) { + $assoc[$val['model']] = $this->$col; + } + continue; + } + $fields[] = $this->_con->qn($col).' = '.$this->_toDb($this->$col, $col); + } + $req .= implode(','."\n", $fields); + if (strlen($where) > 0) { + $req .= ' WHERE '.$where; + } else { + $req .= ' WHERE id = '.$this->_toDb($this->_data['id'], 'id'); + } + $this->_con->execute($req); + if (false === $this->get($this->_data['id'])) { + return false; + } + foreach ($assoc as $model=>$ids) { + $this->batchAssoc($model, $ids); + } + $this->postSave(); + return true; + } + + /** + * Create the model into the database. + * + * If raw insert is requested, the preSave/postSave methods are + * not called and the current id of the object is directly + * used. This is particularily used when doing backup/restore of + * data. + * + * @param bool Raw insert (false) + * @return bool Success + */ + function create($raw=false) + { + if (!$raw) { + $this->preSave(true); + } + $req = 'INSERT INTO '.$this->getSqlTable()."\n"; + $icols = array(); + $ivals = array(); + $assoc = array(); + foreach ($this->_a['cols'] as $col=>$val) { + $field = new $val['type'](); + if ($col == 'id' and !$raw) { + continue; + } elseif ($field->type == 'manytomany') { + // If is a defined array, we need to associate. + if (is_array($this->_data[$col])) { + $assoc[$val['model']] = $this->_data[$col]; + } + continue; + } + $icols[] = $this->_con->qn($col); + $ivals[] = $this->_toDb($this->_data[$col], $col); + } + $req .= '('.implode(', ', $icols).') VALUES '; + $req .= '('.implode(','."\n", $ivals).')'; + $this->_con->execute($req); + if (!$raw) { + if (false === ($id=$this->_con->getLastID())) { + throw new Exception($this->_con->getError()); + } + $this->_data['id'] = $id; + } + foreach ($assoc as $model=>$ids) { + $this->batchAssoc($model, $ids); + } + if (!$raw) { + $this->postSave(true); + } + return true; + } + + /** + * Get models affected by delete. + * + * @return array Models deleted if deleting current model. + */ + function getDeleteSideEffect() + { + $affected = array(); + foreach ($this->_m['list'] as $method=>$details) { + if (is_array($details)) { + // foreignkey + $related = $this->$method(); + $affected = array_merge($affected, (array) $related); + foreach ($related as $rel) { + if ($details[0] == $this->_a['model'] + and $rel->id == $this->_data['id']) { + continue; // $rel == $this + } + $affected = array_merge($affected, (array) $rel->getDeleteSideEffect()); + } + } + } + return Pluf_Model_RemoveDuplicates($affected); + } + + /** + * Delete the current model from the database. + * + * If another model link to the current model through a foreign + * key, find it and delete it. If this model is linked to other + * through a many to many, delete the association. + * + * FIXME: No real test of circular references. It can break. + */ + function delete() + { + if (false === $this->get($this->_data['id'])) { + return false; + } + $this->preDelete(); + // Drop the row level permissions if we are using them + if (Pluf::f('pluf_use_rowpermission', false)) { + $_rpt = Pluf::factory('Pluf_RowPermission')->getSqlTable(); + $sql = new Pluf_SQL('model_class=%s AND model_id=%s', + array($this->_a['model'], $this->_data['id'])); + $this->_con->execute('DELETE FROM '.$_rpt.' WHERE '.$sql->gen()); + } + // Find the models linking to the current one through a foreign key. + foreach ($this->_m['list'] as $method=>$details) { + if (is_array($details)) { + // foreignkey + $related = $this->$method(); + foreach ($related as $rel) { + if ($details[0] == $this->_a['model'] + and $rel->id == $this->_data['id']) { + continue; // $rel == $this + } + // We do not really control if it can be deleted + // as we can find many times the same to delete. + $rel->delete(); + } + } else { + // manytomany + $related = $this->$method(); + foreach ($related as $rel) { + $this->delAssoc($rel); + } + } + } + $req = 'DELETE FROM '.$this->getSqlTable().' WHERE id = '.$this->_toDb($this->_data['id'], 'id'); + $this->_con->execute($req); + $this->_reset(); + return true; + } + + /** + * Reset the fields to default values. + */ + function _reset() + { + foreach ($this->_a['cols'] as $col => $val) { + if (isset($val['default'])) { + $this->_data[$col] = $val['default']; + } elseif (isset($val['is_null'])) { + $this->_data[$col] = null; + } else { + $this->_data[$col] = ''; + } + } + } + + + /** + * Represents the model in auto generated lists. + * + * You need to overwrite this method to have a nice display of + * your objects in the select boxes, logs. + */ + function __toString() + { + return $this->_a['model'].'('.$this->_data['id'].')'; + } + + + /** + * Hook run just after loading a model from the database. + * + * Just overwrite it into your model to perform custom actions. + */ + function restore() + { + } + + /** + * Hook run just before saving a model in the database. + * + * Just overwrite it into your model to perform custom actions. + * + * @param bool Create. + */ + function preSave($create=false) + { + } + + function postSave($create=false) + { + } + + /** + * Hook run just before deleting a model from the database. + * + * Just overwrite it into your model to perform custom actions. + */ + function preDelete() + { + } + + /** + * Set the values from form data. + */ + function setFromFormData($cleaned_values) + { + foreach ($cleaned_values as $key=>$val) { + $this->_data[$key] = $val; + } + } + + /** + * Set a view. + * + * @param string Name of the view. + * @param array Definition of the view. + */ + function setView($view, $def) + { + $this->_a['views'][$view] = $def; + } + + /** + * Prepare the value to be put in the DB. + * + * @param mixed Value. + * @param string Column name. + * @return string SQL ready string. + */ + function _toDb($val, $col) + { + $m = $this->_con->type_cast[$this->_a['cols'][$col]['type']][1]; + return $m($val, $this->_con); + } + + /** + * Get the value from the DB. + * + * @param mixed Value. + * @param string Column name. + * @return mixed Value. + */ + function _fromDb($val, $col) + { + $m = $this->_con->type_cast[$this->_a['cols'][$col]['type']][0]; + return ($m == 'Pluf_DB_IdentityFromDb') ? $val : $m($val); + } + + /** + * Display value. + * + * When you have a list of choices for a field and you want to get + * the display value of the current stored value. + * + * @param string Field to display the value. + * @return mixed Display value, if not available default to the value. + */ + function displayVal($col) + { + if (!isset($this->_a['cols'][$col]['choices'])) { + return $this->_data[$col]; // will on purposed failed if not set + } + $val = array_search($this->_data[$col], $this->_a['cols'][$col]['choices']); + if ($val !== false) { + return $val; + } + return $this->_data[$col]; + } + + /** + * Build the automatic methods for the relations of given type. + * + * Adds the get_xx_list method when the methods of the model + * contains custom names. + * + * @param string $type Relation type: 'foreignkey' or 'manytomany'. + */ + protected function _setupAutomaticListMethods($type) + { + $current_model = $this->_a['model']; + if (isset($GLOBALS['_PX_models_related'][$type][$current_model])) { + $relations = $GLOBALS['_PX_models_related'][$type][$current_model]; + foreach ($relations as $related) { + if ($related != $current_model) { + $model = new $related(); + } else $model = clone $this; + $fkeys = $model->getRelationKeysToModel($current_model, $type); + foreach ($fkeys as $fkey => $val) { + $mname = (isset($val['relate_name'])) ? $val['relate_name'] : $related; + $mname = 'get_'.strtolower($mname).'_list'; + if ('foreignkey' === $type) { + $this->_m['list'][$mname] = array($related, $fkey); + } else { + $this->_m['list'][$mname] = $related; + $this->_m['many'][$related] = $type; + } + } + } + } + } + +} + + +/** + * Check if a model is already in an array of models. + * + * It is not possible to override the == function in PHP to directly + * use in_array. + * + * @param Pluf_Model The model to test + * @param Array The models + * @return bool + */ +function Pluf_Model_InArray($model, $array) +{ + if ($model->id == '') { + return false; + } + foreach ($array as $modelin) { + if ($modelin->_a['model'] == $model->_a['model'] + and $modelin->id == $model->id) { + return true; + } + } + return false; +} + +/** + * Return a list of unique models. + * + * @param array Models with duplicates + * @return array Models with duplicates. + */ +function Pluf_Model_RemoveDuplicates($array) +{ + $res = array(); + foreach ($array as $model) { + if (!Pluf_Model_InArray($model, $res)) { + $res[] = $model; + } + } + return $res; +} + diff --git a/pluf/src/Pluf/Model/Set.php b/pluf/src/Pluf/Model/Set.php new file mode 100644 index 0000000..5ccb27c --- /dev/null +++ b/pluf/src/Pluf/Model/Set.php @@ -0,0 +1,141 @@ + 'MyApp_Item', + * 'model_id' => 32, + * 'foo' => 'bingo plus'), + * (object) array('model_class' => 'MyApp_Bong', + * 'model_id' => 12, + * 'foo' => 'youpla'), + * (object) array('model_class' => 'MyApp_Item', + * 'model_id' => 14, + * 'foo' => 'bingo'), + * ); + * + * You can do: + * $set = new Pluf_Model_Set($data, array('foo' => '_Foo')); + * foreach ($set as $res) { + * echo $res; // Will be the loaded model based on the class and id. + * echo $res->_Foo; // will contain the value foo of the $data array. + * } + * + */ +class Pluf_Model_Set implements Iterator, ArrayAccess +{ + protected $data = array(); + protected $keys = array(); + + public function __construct($data, $keys=array()) + { + $this->data = $data; + $this->keys = $keys; + reset($this->data); + } + + /** + * Get the current item. + */ + public function current() + { + $i = current($this->data); + $item = Pluf::factory($i->model_class, $i->model_id); + foreach ($this->keys as $key => $val) { + $item->$val = $i->$key; + } + return $item; + } + + public function key() + { + return key($this->data); + } + + public function next() + { + next($this->data); + } + + public function rewind() + { + reset($this->data); + } + + public function valid() + { + // We know that the boolean false will not be stored as a + // field, so we can test against false to check if valid or + // not. + return (false !== current($this->data)); + } + + public function count() + { + return count($this->data); + } + + public function offsetUnset($index) + { + unset($this->data[$index]); + } + + public function offsetSet($index, $value) + { + if (!is_object($value) or + is_subclass_of($value, 'Pluf_Model')) { + throw new Exception('Must be a subclass of Pluf_Model: '.$value); + } + $res = array('model_class' => $value->_model, + 'model_id' => $value->id); + foreach ($this->keys as $key => $name) { + $res[$key] = (isset($value->$name)) ? $value->$name : null; + } + $this->data[$index] = (object) $res; + } + + public function offsetGet($index) + { + if (!isset($this->data[$index])) { + throw new Exception('Undefined index: '.$index); + } + $i = $this->data[$index]; + $item = Pluf::factory($i->model_class, $i->model_id); + foreach ($this->keys as $key => $val) { + $item->$val = $i->$key; + } + return $item; + } + + public function offsetExists($index) + { + return (isset($this->data[$index])); + } +} \ No newline at end of file diff --git a/pluf/src/Pluf/Paginator.php b/pluf/src/Pluf/Paginator.php new file mode 100644 index 0000000..c6c8902 --- /dev/null +++ b/pluf/src/Pluf/Paginator.php @@ -0,0 +1,835 @@ + + * $model = new Pluf_Permission(); + * $pag = new Pluf_Paginator($model); + * // Set the action to the page listing the permissions + * $pag->action = 'view_name'; + * // Get the paginator parameters from the request + * $pag->setFromRequest($request); + * print $pag->render(); + * + * + * This example shows the fast way. That means that the items will be + * shown according to the default values of the paginator or with the + * details given in the admin definition of the model. + */ +class Pluf_Paginator +{ + /** + * The model being paginated. + */ + protected $model; + + /** + * The items being paginated. If no model is given when creating + * the paginator, it will use the items to list them. + */ + public $items = null; + + /** + * Extra property/value for the items. + * + * This can be practical if you want some values for the edit + * action which are not available in the model data. + */ + public $item_extra_props = array(); + + /** + * The fields being shown. + * + * If no fields are given, the __toString representation of the + * item will be used to show the item. + * + * If an item in the list_display is an array the format is the + * following: + * array('field', 'Custom_Function_ToApply', 'custom header name') + * + * The signature of the the Custom_Function_ToApply is: + * string = Custom_Function_ToApply('field', $item); + * + * By using for example 'id' as field with a custom header name + * you can create new columns in the table. + */ + protected $list_display = array(); + + /** + * List filter. + * + * Allow the generation of filtering options for the list. If you + * provide a list of fields having a "choices" option, you will be + * able to filter on the choice values. + */ + public $list_filters = array(); + + /** + * Extra classes that will be applied to the td of each cell of + * each column. + * + * If you have 3 columns and put array('one', '', 'foo') all the + * td of the first column will have the class 'one' set and the + * tds of the last column will have the 'foo' class set. + */ + public $extra_classes = array(); + + /** + * The fields being searched. + */ + protected $search_fields = array(); + + /** + * The where clause from the search. + */ + protected $where_clause = null; + + /** + * The forced where clause on top of the search. + */ + public $forced_where = null; + + /** + * View of the model to be used. + */ + public $model_view = null; + + /** + * Maximum number of items per page. + */ + public $items_per_page = 50; + + /** + * Current page. + */ + public $current_page = 1; + + /** + * Number of pages. + */ + public $page_number = 1; + + /** + * Search string. + */ + public $search_string = ''; + + /** + * Text to display when no results are found. + */ + public $no_results_text = 'No items found'; + + /** + * Which fields of the model can be used to sort the dataset. To + * be useable these fields must be in the $list_display so that + * the sort links can be shown for the user to click on them and + * sort the list. + */ + public $sort_fields = array(); + + /** + * Current sort order. An array with first value the field and + * second the order of the sort. + */ + public $sort_order = array(); + + /** + * Keys where the sort is reversed. Let say, you have a column + * using a timestamp but displaying the information as an age. If + * you sort "ASC" you espect to get the youngest first, but as the + * timestamp is used, you get the oldest. But the key here and the + * sort will be reverted. + */ + public $sort_reverse_order = array(); + + /** + * + * Do not add the little sort links but directly make the title of + * the column a link to sort. + */ + public $sort_link_title = false; + + /** + * Edit action. + * + */ + public $edit_action = ''; + + /** + * Action for search/next/previous. + */ + public $action = ''; + + /** + * Id/class of the generated table. + */ + public $id = ''; + public $class = ''; + + /** + * Extra parameters for the modification function call. + */ + public $extra = null; + + /** + * Summary for the table. + */ + public $summary = ''; + + /** + * Total number of items. + * + * Available only after the rendering of the paginator. + */ + public $nb_items = 0; + + protected $active_list_filter = array(); + + /** + * Maximum number of pages to be displayed + * + * Instead of showing by default unlimited number of pages, + * limit to this value. + * 0 is unlimited (default). + * + * Ex: max_number_pages = 3 will produce + * Prev 1 ... 498 499 500 ... 1678 Next + */ + public $max_number_pages = 0; + public $max_number_pages_separator = '...'; + + public $custom_max_items = false; + + /** + * First, Previous, Next and Last page display + * Default First = 1, Last = last page num + * Prev and Next are initialized to null. In the footer() we will + * set Prev = __('Prev') and Next = __('Next') if not set + * Last has to be set during render if not set so that we know + * the number of pages + */ + public $symbol_first = '1'; + public $symbol_last = null; + public $symbol_prev = null; + public $symbol_next = null; + + /** + * Construct the paginator for a model. + * + * @param object Model to paginate (null). + * @param array List of the headers to show (array()). + * @param array List of the fields to search (array()). + */ + function __construct($model=null, $list_display=array(), + $search_fields=array()) + { + $this->model = $model; + $this->configure($list_display, $search_fields); + } + + /** + * Configure the paginator. + * + * @param array List of the headers to show. + * @param array List of the fields to search (array()) + * @param array List of the fields to sort the data set (array()) + */ + function configure($list_display, $search_fields=array(), $sort_fields=array()) + { + if (is_array($list_display)) { + $this->list_display = array(); + foreach ($list_display as $key=>$col) { + if (!is_array($col) && !is_null($this->model) && isset($this->model->_a['cols'][$col]['verbose'])) { + $this->list_display[$col] = $this->model->_a['cols'][$col]['verbose']; + } elseif (!is_array($col)) { + if (is_numeric($key)) { + $this->list_display[$col] = $col; + } else { + $this->list_display[$key] = $col; + } + } else { + if (count($col) == 2 + && !is_null($this->model) + && isset($this->model->_a['cols'][$col[0]]['verbose'])) { + $col[2] = $this->model->_a['cols'][$col[0]]['verbose']; + } elseif (count($col) == 2 ) { + $col[2] = $col[0]; + } + $this->list_display[] = $col; + } + } + } + //print_r($this->list_display); + if (is_array($search_fields)) { + $this->search_fields = $search_fields; + } + if (is_array($sort_fields)) { + $this->sort_fields = $sort_fields; + } + } + + /** + * Set the parameters from the request. + * + * Possible parameters are: + * _px_q : Query string to search. + * _px_p : Current page. + * _px_sk : Sort key. + * _px_so : Sort order. + * _px_fk : Filter key. + * _px_fv : Filter value. + * + * @param Pluf_HTTP_Request The request + */ + function setFromRequest($request) + { + if (isset($request->REQUEST['_px_q'])) { + $this->search_string = $request->REQUEST['_px_q']; + } + if (isset($request->REQUEST['_px_p'])) { + $this->current_page = (int) $request->REQUEST['_px_p']; + $this->current_page = max(1, $this->current_page); + } + if (isset($request->REQUEST['_px_sk']) + and in_array($request->REQUEST['_px_sk'], $this->sort_fields)) { + $this->sort_order[0] = $request->REQUEST['_px_sk']; + $this->sort_order[1] = 'ASC'; + if (isset($request->REQUEST['_px_so']) + and ($request->REQUEST['_px_so'] == 'd')) { + $this->sort_order[1] = 'DESC'; + } + } + if (isset($request->REQUEST['_px_fk']) + and in_array($request->REQUEST['_px_fk'], $this->list_filters) + and isset($request->REQUEST['_px_fv'])) { + // We add a forced where query + $sql = new Pluf_SQL($request->REQUEST['_px_fk'].'=%s', + $request->REQUEST['_px_fv']); + if (!is_null($this->forced_where)) { + $this->forced_where->SAnd($sql); + } else { + $this->forced_where = $sql; + } + $this->active_list_filter = array($request->REQUEST['_px_fk'], + $request->REQUEST['_px_fv']); + } + } + + + /** + * Render the complete table. + * + * When an id is provided, the generated table receive this id. + * + * @param string Table id ('') + */ + function render($id='') + { + $this->id = $id; + $_sum = ''; + if (strlen($this->summary)) { + $_sum = ' summary="'.htmlspecialchars($this->summary).'"'; + } + $out = 'class) ? ' class="'.$this->class.'"' : '').(($this->id) ? ' id="'.$this->id.'">' : '>')."\n"; + $out .= ''."\n"; + $out .= $this->searchField(); + $out .= $this->colHeaders(); + $out .= ''."\n"; + // Opt: Generate the footer of the table with the next/previous links + $out .= $this->footer(); + // Generate the body of the table with the items + $out .= $this->body(); + $out .= ''."\n"; + return new Pluf_Template_SafeString($out, true); + } + + /** + * Render as array. + * + * An array rendering do not honor the limits, that is, all the + * items are returned. Also, the output is not formatted values + * from the db are directly returned. This is perfect to then use + * the values in a JSON response. + * + * @return Array. + */ + function render_array() + { + if (count($this->sort_order) != 2) { + $order = null; + } else { + $s = $this->sort_order[1]; + if (in_array($this->sort_order[0], $this->sort_reverse_order)) { + $s = ($s == 'ASC') ? 'DESC' : 'ASC'; + } + $order = $this->sort_order[0].' '.$s; + } + if (!is_null($this->model)) { + $items = $this->model->getList(array('view' => $this->model_view, + 'filter' => $this->filter(), + 'order' => $order, + )); + } else { + $items = $this->items; + } + $out = array(); + foreach ($items as $item) { + $idata = array(); + if (!empty($this->list_display)) { + $i = 0; + foreach ($this->list_display as $key=>$col) { + if (!is_array($col)) { + $idata[$key] = $item->$key; + } else { + $_col = $col[0]; + $idata[$col[0]] = $item->$_col; + } + } + } else { + $idata = $item->id; + } + $out[] = $idata; + } + return $out; + } + + /** + * Generate the footer of the table. + */ + function footer() + { + // depending on the search string, the result set can be + // limited. So we need first to count the total number of + // corresponding items. Then get a slice of them in the + // generation of the body. + if (!is_null($this->model)) { + $nb_items = $this->model->getCount(array('view' => $this->model_view, 'filter' => $this->filter())); + } else { + $nb_items = $this->items->count(); + } + $this->nb_items = $nb_items; + if ($nb_items <= $this->items_per_page) { + return ''; + } + $this->page_number = ceil($nb_items / $this->items_per_page); + if ($this->current_page > $this->page_number) { + $this->current_page = 1; + } + $params = array(); + if (!empty($this->search_fields)) { + $params['_px_q'] = $this->search_string; + $params['_px_p'] = $this->current_page; + } + if (!empty($this->sort_order)) { + $params['_px_sk'] = $this->sort_order[0]; + $params['_px_so'] = ($this->sort_order[1] == 'ASC') ? 'a' : 'd'; + } + // Add the filtering + if (!empty($this->active_list_filter)) { + $params['_px_fk'] = $this->active_list_filter[0]; + $params['_px_fv'] = $this->active_list_filter[1]; + } + $out = ''."\n"; + if ($this->current_page != 1) { + $params['_px_p'] = $this->current_page - 1; + $url = $this->getUrl($params); + $this->symbol_prev = ($this->symbol_prev ==null) ?__('Prev') : $this->symbol_prev; + $out .= ''.$this->symbol_prev.' '; + } + // Always display the link to Page#1 + $i=1; + $params['_px_p'] = $i; + $class = ($i == $this->current_page) ? ' class="px-current-page"' : ''; + $url = $this->getUrl($params); + $out .= ''.$this->symbol_first.' '; + // Display the number of pages given $this->max_number_pages + if ($this->max_number_pages > 0) { + $nb_pa = floor($this->max_number_pages/2); + $imin = $this->current_page - $nb_pa; + $imax = $this->current_page + $nb_pa; + // We put the separator if $imin is at leat greater than 2 + if ($imin > 2) $out .= ' '.$this->max_number_pages_separator.' '; + if ($imin <= 1) $imin=2; + if ($imax >= $this->page_number) $imax = $this->page_number - 1; + } else { + $imin = 2; + $imax = $this->page_number - 1; + } + for ($i=$imin; $i<=$imax; $i++) { + $params['_px_p'] = $i; + $class = ($i == $this->current_page) ? ' class="px-current-page"' : ''; + $url = $this->getUrl($params); + $out .= ''.$i.' '; + } + if (($this->max_number_pages > 0) && $imax < ($this->page_number - 1)) { + $out .= ' '.$this->max_number_pages_separator.' '; + } + // Always display the link to last Page + $i = $this->page_number; + $params['_px_p'] = $i; + $class = ($i == $this->current_page) ? ' class="px-current-page"' : ''; + $url = $this->getUrl($params); + if ($this->symbol_last == null) $this->symbol_last=$i; + $out .= ''.$this->symbol_last.' '; + if ($this->current_page != $this->page_number) { + $params['_px_p'] = $this->current_page + 1; + $url = $this->getUrl($params); + $this->symbol_next = ($this->symbol_next == null) ? __('Next') : $this->symbol_next; + $out .= ''.$this->symbol_next.' '; + } + $out .= ''."\n"; + return $out; + } + + /** + * Generate the body of the list. + */ + function body() + { + $st = ($this->current_page-1) * $this->items_per_page; + if (count($this->sort_order) != 2) { + $order = null; + } else { + $s = $this->sort_order[1]; + if (in_array($this->sort_order[0], $this->sort_reverse_order)) { + $s = ($s == 'ASC') ? 'DESC' : 'ASC'; + } + $order = $this->sort_order[0].' '.$s; + } + if (!is_null($this->model)) { + $items = $this->model->getList(array('view' => $this->model_view, + 'filter' => $this->filter(), + 'order' => $order, + 'start' => $st, + 'nb' => $this->items_per_page)); + } else { + $items = $this->items; + } + $out = ''; + $total = $items->count(); + $count = 1; + foreach ($items as $item) { + $item->_paginator_count = $count; + $item->_paginator_total_page = $total; + foreach ($this->item_extra_props as $key=>$val) { + $item->$key = $val; + } + $out .= $this->bodyLine($item); + $count++; + } + if (strlen($out) == 0) { + $out = ''.$this->no_results_text + .''."\n"; + } + return ''.$out.''."\n"; + } + + /** + * Generate a standard "line" of the body + */ + function bodyLine($item) + { + $out = ''; + if (!empty($this->list_display)) { + $i = 0; + foreach ($this->list_display as $key=>$col) { + $text = ''; + if (!is_array($col)) { + $text = Pluf_esc($item->$key); + } else { + if (is_null($this->extra)) { + $text = $col[1]($col[0], $item); + } else { + $text = $col[1]($col[0], $item, $this->extra); + } + } + if ($i == 0) { + $text = $this->getEditAction($text, $item); + } + $class = (isset($this->extra_classes[$i]) and $this->extra_classes[$i] != '') ? ' class="'.$this->extra_classes[$i].'"' : ''; + $out.=''.$text.''; + $i++; + } + } else { + $out.=''.$this->getEditAction(Pluf_esc($item), $item).''; + } + $out .= ''."\n"; + return $out; + } + + /** + * Get the edit action. + * + * @param string Text to put in the action. + * No escaping of the text is performed. + * @param object Model for the action. + * @return string Ready to use string. + */ + function getEditAction($text, $item) + { + $edit_action = $this->edit_action; + if (!empty($edit_action)) { + if (!is_array($edit_action)) { + $params = array($edit_action, $item->id); + } else { + $params = array(array_shift($edit_action)); + foreach ($edit_action as $field) { + $params[] = $item->$field; + } + } + $view = array_shift($params); + $url = Pluf_HTTP_URL_urlForView($view, $params); + return ''.$text.''; + } else { + return $text; + } + } + + /** + * Generate the where clause. + * + * @return string The ready to use where clause. + */ + function filter() + { + if (strlen($this->where_clause) > 0) { + return $this->where_clause; + } + if (!is_null($this->forced_where) + or (strlen($this->search_string) > 0 + && !empty($this->search_fields))) { + $lastsql = new Pluf_SQL(); + $keywords = $lastsql->keywords($this->search_string); + foreach ($keywords as $key) { + $sql = new Pluf_SQL(); + foreach ($this->search_fields as $field) { + $sqlor = new Pluf_SQL(); + $sqlor->Q($field.' LIKE %s', '%'.$key.'%'); + $sql->SOr($sqlor); + } + $lastsql->SAnd($sql); + } + if (!is_null($this->forced_where)) { + $lastsql->SAnd($this->forced_where); + } + $this->where_clause = $lastsql->gen(); + if (strlen($this->where_clause) == 0) + $this->where_clause = null; + } + return $this->where_clause; + } + + /** + * Generate the column headers for the table. + */ + function colHeaders() + { + if (empty($this->list_display)) { + return ''.__('Name').''."\n"; + } else { + $out = ''; + foreach ($this->list_display as $key=>$col) { + if (is_array($col)) { + $field = $col[0]; + $name = $col[2]; + Pluf::loadFunction($col[1]); + } else { + $name = $col; + $field = $key; + } + //print_r($this->list_display); + if (!$this->sort_link_title) { + $out .= ''.Pluf_esc(ucfirst($name)).''.$this->headerSortLinks($field).''; + } else { + $out .= ''.$this->headerSortLinks($field, Pluf_esc(ucfirst($name))).''; + } + } + $out .= ''."\n"; + return $out; + } + } + + /** + * Generate the little text on the header to allow sorting if + * available. + * + * If the title is set, the link is directly made on the title. + * + * @param string Name of the field + * @param string Title ('') + * @return string HTML fragment with the links to + * sort ASC/DESC on this field. + */ + function headerSortLinks($field, $title='') + { + if (!in_array($field, $this->sort_fields)) { + return $title; + } + $params = array(); + if (!empty($this->search_fields)) { + $params['_px_q'] = $this->search_string; + } + if (!empty($this->active_list_filter)) { + $params['_px_fk'] = $this->active_list_filter[0]; + $params['_px_fv'] = $this->active_list_filter[1]; + } + $params['_px_sk'] = $field; + $out = ''.__('Sort').' %s/%s'; + $params['_px_so'] = 'a'; + $aurl = $this->getUrl($params); + $asc = ''.__('asc').''; + $params['_px_so'] = 'd'; + $durl = $this->getUrl($params); + $desc = ''.__('desc').''; + if (strlen($title)) { + if (count($this->sort_order) == 2 + and $this->sort_order[0] == $field + and $this->sort_order[1] == 'ASC') { + return ''.$title.''; + } + return ''.$title.''; + } + return sprintf($out, $asc, $desc); + } + + /** + * Get the search field XHTML. + */ + function searchField() + { + if (empty($this->search_fields)) { + return ''; + } + $url = $this->getUrl(); + return '' + .'
' + .' ' + .'' + .'' + .'
'."\n"; + + } + + /** + * Using $this->action and the $get_params array, generate the URL + * with the data. + * + * @param array Get parameters (array()). + * @param bool Encoded to be put in href="" (true). + * @return string Url. + */ + function getUrl($get_params=array(), $encoded=true) + { + // Default values + $params = array(); + $by_name = false; + $view = ''; + if (is_array($this->action)) { + $view = $this->action[0]; + if (isset($this->action[1])) { + $params = $this->action[1]; + } + } else { + $view = $this->action; + } + return Pluf_HTTP_URL_urlForView($view, $params, $get_params, $encoded); + } + + /** + * Overloading of the get method. + * + * @param string Property to get + */ + function __get($prop) + { + if ($prop == 'render') return $this->render(); + return $this->$prop; + } + +} + +/** + * Returns the string representation of an item. + * + * @param string Field (not used) + * @param Object Item + * @return string Representation of the item + */ +function Pluf_Paginator_ToString($field, $item) +{ + return Pluf_esc($item); +} + +/** + * Returns the item referenced as foreign key as a string. + */ +function Pluf_Paginator_FkToString($field, $item) +{ + $method = 'get_'.$field; + $fk = $item->$method(); + return Pluf_esc($fk); +} + +function Pluf_Paginator_DateYMDHMS($field, $item) +{ + Pluf::loadFunction('Pluf_Template_dateFormat'); + return Pluf_Template_dateFormat($item->$field, '%Y-%m-%d %H:%M:%S'); +} + +function Pluf_Paginator_DateYMDHM($field, $item) +{ + Pluf::loadFunction('Pluf_Template_dateFormat'); + return Pluf_Template_dateFormat($item->$field, '%Y-%m-%d %H:%M'); +} + +function Pluf_Paginator_DateYMD($field, $item) +{ + Pluf::loadFunction('Pluf_Template_dateFormat'); + return Pluf_Template_dateFormat($item->$field, '%Y-%m-%d'); +} + +function Pluf_Paginator_DisplayVal($field, $item) +{ + return $item->displayVal($field); +} + +function Pluf_Paginator_DateAgo($field, $item) +{ + Pluf::loadFunction('Pluf_Date_Easy'); + Pluf::loadFunction('Pluf_Template_dateFormat'); + $date = Pluf_Template_dateFormat($item->$field, '%Y-%m-%d %H:%M:%S'); + return Pluf_Date_Easy($date, null, 2, __('now')); +} diff --git a/pluf/src/Pluf/Permission.php b/pluf/src/Pluf/Permission.php new file mode 100644 index 0000000..d5d5d6f --- /dev/null +++ b/pluf/src/Pluf/Permission.php @@ -0,0 +1,120 @@ +_a['verbose'] = __('permission'); + $this->_a['table'] = 'permissions'; + $this->_a['model'] = 'Pluf_Permission'; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + //It is automatically added. + 'blank' => true, + ), + 'name' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 50, + 'verbose' => __('name'), + ), + 'code_name' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 100, + 'verbose' => __('code name'), + 'help_text' => __('The code name must be unique for each application. Standard permissions to manage a model in the interface are "Model_Name-create", "Model_Name-update", "Model_Name-list" and "Model_Name-delete".'), + ), + 'description' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 250, + 'verbose' => __('description'), + ), + 'application' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'size' => 150, + 'blank' => false, + 'verbose' => __('application'), + 'help_text' => __('The application using this permission, for example "YourApp", "CMS" or "SView".'), + ), + ); + $this->_a['idx'] = array( + 'code_name_idx' => + array( + 'type' => 'normal', + 'col' => 'code_name', + ), + 'application_idx' => + array( + 'type' => 'normal', + 'col' => 'application', + ), + ); + $hay = array(strtolower(Pluf::f('pluf_custom_group', 'Pluf_Group')), strtolower($this->_a['model'])); + sort($hay); + $t_asso = $this->_con->pfx.$hay[0].'_'.$hay[1].'_assoc'; + $t_perm = $this->_con->pfx.'permissions'; + $this->_a['views'] = array( + 'join_group' => + array( + 'join' => 'LEFT JOIN '.$t_asso + .' ON '.$t_perm.'.id=pluf_permission_id', + ), + ); + } + + function __toString() + { + return $this->name.' ('.$this->application.'.'.$this->code_name.')'; + } + + /** + * Get the matching permission object from the permission string. + * + * @param string Permission string, for example 'Pluf_User.create'. + * @return false|Pluf_Permission The matching permission or false. + */ + public static function getFromString($perm) + { + list($app, $code) = explode('.', trim($perm)); + $sql = new Pluf_SQL('code_name=%s AND application=%s', + array($code, $app)); + $perms = Pluf::factory('Pluf_Permission')->getList(array('filter'=>$sql->gen())); + if ($perms->count() != 1) { + return false; + } + return $perms[0]; + } +} + diff --git a/pluf/src/Pluf/Precondition.php b/pluf/src/Pluf/Precondition.php new file mode 100644 index 0000000..e004293 --- /dev/null +++ b/pluf/src/Pluf/Precondition.php @@ -0,0 +1,122 @@ +user) or $request->user->isAnonymous()) { + return new Pluf_HTTP_Response_RedirectToLogin($request); + } + if (!$request->user->active) { + return new Pluf_HTTP_Response_Forbidden($request); + } + return true; + } + + /** + * Check if the user is admin or staff. + * + * @param Pluf_HTTP_Request + * @return mixed + */ + static public function staffRequired($request) + { + $res = Pluf_Precondition::loginRequired($request); + if (true !== $res) { + return $res; + } + if ($request->user->administrator or $request->user->staff) { + return true; + } + return new Pluf_HTTP_Response_Forbidden($request); + } + + /** + * Check if the user is administrator.. + * + * @param Pluf_HTTP_Request + * @return mixed + */ + static public function adminRequired($request) + { + $res = Pluf_Precondition::loginRequired($request); + if (true !== $res) { + return $res; + } + if ($request->user->administrator) { + return true; + } + return new Pluf_HTTP_Response_Forbidden($request); + } + + /** + * Check if the user has a given permission.. + * + * @param Pluf_HTTP_Request + * @param string Permission + * @return mixed + */ + static public function hasPerm($request, $permission) + { + $res = Pluf_Precondition::loginRequired($request); + if (true !== $res) { + return $res; + } + if ($request->user->hasPerm($permission)) { + return true; + } + return new Pluf_HTTP_Response_Forbidden($request); + } + + /** + * Requires SSL to access the view. + * + * It will redirect the user to the same URL but over SSL if the + * user is not using SSL, if POST request, the data are lost, so + * handle it with care. + * + * @param Pluf_HTTP_Request + * @return mixed + */ + static public function sslRequired($request) + { + if (empty($_SERVER['HTTPS']) or $_SERVER['HTTPS'] == 'off') { + return new Pluf_HTTP_Response_Redirect('https://'.$request->http_host.$request->uri); + } + return true; + } + +} \ No newline at end of file diff --git a/pluf/src/Pluf/Queue.php b/pluf/src/Pluf/Queue.php new file mode 100644 index 0000000..d5eee91 --- /dev/null +++ b/pluf/src/Pluf/Queue.php @@ -0,0 +1,140 @@ +_a['verbose'] = __('message queue'); + $this->_a['table'] = 'pluf_queue'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + //It is automatically added. + 'blank' => true, + ), + 'model_class' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 150, + 'verbose' => __('model class'), + ), + 'model_id' => + array( + 'type' => 'Pluf_DB_Field_Integer', + 'blank' => false, + 'verbose' => __('model id'), + ), + 'action' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 150, + 'verbose' => __('action'), + ), + 'lock' => + array( + 'type' => 'Pluf_DB_Field_Integer', + 'blank' => false, + 'verbose' => __('lock status'), + 'default' => 0, + 'choices' => array( + __('Free') => 0, + __('In progress') => 1, + __('Completed') => 2, + ), + ), + 'creation_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('created at'), + ), + 'modif_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('modified at'), + ), + ); + $this->_a['idx'] = array( + 'lock_idx' => + array( + 'type' => 'normal', + 'col' => 'lock', + ), + ); + } + + function preSave($create=false) + { + if ($this->id == '') { + $this->creation_dtime = gmdate('Y-m-d H:i:s'); + } + $this->modif_dtime = gmdate('Y-m-d H:i:s'); + } + + /** + * Add an object to the queue. + * + * @param Pluf_Model Your model + * @param string Action for the object + */ + public static function addTo($object, $action='') + { + $q = new Pluf_Queue(); + $q->model_class = $object->_model; + $q->model_id = $object->id; + $q->lock = 0; + $q->action = $action; + $q->create(); + } +} + diff --git a/pluf/src/Pluf/Queue/Processor.php b/pluf/src/Pluf/Queue/Processor.php new file mode 100644 index 0000000..ac5e858 --- /dev/null +++ b/pluf/src/Pluf/Queue/Processor.php @@ -0,0 +1,93 @@ +begin(); + // In a transaction to not process the same item at + // the same time from to processes. + $gqueue = new Pluf_Queue(); + $items = $gqueue->getList(array('filter' => $db->qn('lock').'=0', + 'order' => 'creation_dtime ASC')); + if ($items->count() > 0) { + $item = $items[0]; + $item->lock = 1; + $item->update(); + } + $db->commit(); + if ($item === false) return false; + // try to get the corresponding object + $obj = Pluf::factory($item->model_class, $item->model_id); + if ($obj->id != $item->model_id) $obj = null; + return array('queue' => $item, 'item' => $obj); + } + + public static function process() + { + while (false !== ($q = self::getItem())) { + /** + * [signal] + * + * Pluf_Queue_Processor::process + * + * [sender] + * + * Pluf_Queue_Processor + * + * [description] + * + * This signal allows an application to perform an action on a + * queue item. The item is set to null if none existing. + * + * You must not modify the 'queue' object. + * + * [parameters] + * + * array('item' => $item, 'queue' => $queue); + * + * + */ + Pluf_Signal::send('Pluf_Queue_Processor::process', + 'Pluf_Queue_Process', $q); + $q['queue']->lock = 2; + $q['queue']->update(); + } + } +} diff --git a/pluf/src/Pluf/RowPermission.php b/pluf/src/Pluf/RowPermission.php new file mode 100644 index 0000000..c126b05 --- /dev/null +++ b/pluf/src/Pluf/RowPermission.php @@ -0,0 +1,145 @@ +_a['table'] = 'rowpermissions'; + $this->_a['model'] = 'Pluf_RowPermission'; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + //It is automatically added. + 'blank' => true, + ), + 'model_id' => + array( + 'type' => 'Pluf_DB_Field_Integer', + 'blank' => false, + 'verbose' => __('model ID'), + ), + 'model_class' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 50, + 'verbose' => __('model class'), + ), + 'owner_id' => + array( + 'type' => 'Pluf_DB_Field_Integer', + 'blank' => false, + 'verbose' => __('owner ID'), + ), + 'owner_class' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 50, + 'verbose' => __('owner class'), + 'help_text' => __('For example Pluf_User or Pluf_Group.'), + ), + 'negative' => + array( + 'type' => 'Pluf_DB_Field_Boolean', + 'blank' => false, + 'default' => false, + 'verbose' => __('do not have the permission'), + ), + 'permission' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'Pluf_Permission', + 'blank' => false, + 'verbose' => __('permission'), + ), + ); + $this->_a['idx'] = array( + 'permission_combo_idx' => + array( + 'type' => 'unique', + 'col' => 'model_id, model_class, owner_id, owner_class, permission', + ), + ); + $t_perm = $this->_con->pfx.'permissions'; + $this->_a['views'] = array( + 'join_permission' => + array( + 'select' => $this->getSelect().', ' + .$t_perm.'.code_name AS code_name, ' + .$t_perm.'.application AS application ', + 'join' => 'LEFT JOIN '.$t_perm + .' ON '.$t_perm.'.id=permission', + 'props' => array('code_name' => 'code_name', + 'application' => 'application'), + ), + ); + + } + + public static function add($owner, $object, $perm, $negative=false) + { + if (!is_object($perm)) { + // Find matching permission + $found = Pluf_Permission::getFromString($perm); + if (false === $found) { + throw new Exception(sprintf('The permission %s does not exist.', $perm)); + } + $perm = $found; + } + Pluf_RowPermission::remove($owner, $object, $perm); + $nperm = new Pluf_RowPermission(); + $nperm->owner_id = $owner->id; + $nperm->owner_class = $owner->_a['model']; + $nperm->model_id = $object->id; + $nperm->model_class = $object->_a['model']; + $nperm->permission = $perm; + $nperm->negative = $negative; + $nperm->create(); + return true; + } + + public static function remove($owner, $object, $perm) + { + if (!is_object($perm)) { + $found = Pluf_Permission::getFromString($perm); + if (false === $found) { + throw new Exception(sprintf('The permission %s does not exist.', $perm)); + } + $perm = $found; + } + $growp = new Pluf_RowPermission(); + $sql = new Pluf_SQL('owner_id=%s AND owner_class=%s AND model_id=%s AND model_class=%s AND permission=%s', + array($owner->id, $owner->_a['model'], $object->id, $object->_a['model'], $perm->id)); + $perms = $growp->getList(array('filter' => $sql->gen())); + foreach ($perms as $p) { + $p->delete(); + } + return true; + } +} diff --git a/pluf/src/Pluf/SQL.php b/pluf/src/Pluf/SQL.php new file mode 100644 index 0000000..733aaab --- /dev/null +++ b/pluf/src/Pluf/SQL.php @@ -0,0 +1,138 @@ +db = Pluf::db(); + if (strlen($base) > 0) { + $this->Q($base, $args); + } + } + + /** + * Returns the where clause. + * + * @return string Where clause without the WHERE + */ + function gen() + { + return implode(' AND ', $this->ands); + } + + /** + * Add a condition. + * + * @param string String to 'interpolate' + * @param mixed String or array of parameters (array()) + */ + function Q($base, $args=array()) + { + $escaped = array(); + if (!is_array($args)) { + $args = array($args); + } + foreach ($args as $arg) { + $escaped[] = $this->db->esc($arg); + } + $this->ands[] = vsprintf($base, $escaped); + return $this; + } + + /** + * Add another SQL as a AND. + * + * @param Pluf_SQL Other object to add to the current. + */ + function SAnd($sql) + { + return $this->SDef($sql); + } + + /** + * Add another SQL as a OR + * + * @param Pluf_SQL Other object to add to the current. + */ + function SOr($sql) + { + return $this->SDef($sql, 'OR'); + } + + /** + * Add another SQL to the current + * + * @param Pluf_SQL Other object to add to the current. + * @param string Type of addition + */ + function SDef($sql, $k='AND') + { + if (empty($this->ands)) { + $this->ands = $sql->ands; + } else { + $othersql = $sql->gen(); + $current = $this->gen(); + if (strlen($othersql)) { + $this->ands = array(); + $this->ands[] = '('.$current.') '.$k.' ('.$othersql.')'; + } + } + return $this; + } + + /** + * Get keywords. + * + * Considering a query string, explode the query string in + * keywords given a defined delimiter. + * + * @param string Query string + * @param string delimiter (' ') + * @return array Array of keywords + */ + function keywords($string, $del=' ') + { + $keys = array(); + $args = explode($del, $string); + foreach ($args as $arg) { + $arg = trim($arg); + if (strlen($arg) > 0) { + $keys[] = $arg; + } + } + return $keys; + } +} + diff --git a/pluf/src/Pluf/Search.php b/pluf/src/Pluf/Search.php new file mode 100644 index 0000000..183f05a --- /dev/null +++ b/pluf/src/Pluf/Search.php @@ -0,0 +1,221 @@ +$c) { + $words_flat[] = $word; + } + $word_ids = self::getWordIds($words_flat); + if (in_array(null, $word_ids)) { + return array(); + } + return self::searchDocuments($word_ids); + } + + /** + * Stem the words with the given stemmer. + */ + public static function stem($words, $stemmer) + { + $nwords = array(); + foreach ($words as $word => $occ) { + $word = call_user_func(array($stemmer, 'stem'), $word); + if (isset($nwords[$word])) { + $nwords[$word] += $occ; + } else { + $nwords[$word] = $occ; + } + } + return $nwords; + } + + /** + * Search documents. + * + * Only the total of the ponderated occurences is used to sort the + * results. + * + * @param array Ids. + * @return array Sorted by score, returns model_class, model_id and score. + */ + public static function searchDocuments($wids) + { + $db =& Pluf::db(); + $gocc = new Pluf_Search_Occ(); + $where = array(); + foreach ($wids as $id) { + $where[] = $db->qn('word').'='.(int)$id; + } + $select = 'SELECT model_class, model_id, SUM(pondocc) AS score FROM '.$gocc->getSqlTable().' WHERE '.implode(' OR ', $where).' GROUP BY model_class, model_id HAVING COUNT(*)='.count($wids).' ORDER BY score DESC'; + return $db->select($select); + } + + /** + * Get the id of each word. + * + * @param array Words + * @return array Ids, null if no matching word. + */ + public static function getWordIds($words) + { + $ids = array(); + $gword = new Pluf_Search_Word(); + foreach ($words as $word) { + $sql = new Pluf_SQL('word=%s', array($word)); + $l = $gword->getList(array('filter' => $sql->gen())); + if ($l->count() > 0) { + $ids[] = $l[0]->id; + } else { + $ids[] = null; + } + } + return $ids; + } + + /** + * Index a document. + * + * The document must provide a method _toIndex() returning the + * document as a string for indexation. The string must be clean + * and will simply be tokenized by Pluf_Text::tokenize(). + * + * So a recommended way to clean it at the end is to remove all + * the HTML tags and then run the following on it: + * + * return Pluf_Text::cleanString(html_entity_decode($string, + * ENT_QUOTES, 'UTF-8')); + * + * Indexing is resource intensive so it is recommanded to run the + * indexing in an asynchronous way. When you save a resource to be + * indexed, just write a log "need to index resource x" and then + * you can every few minutes index the resources. Nobody care if + * your index is not perfectly fresh, but your end users care if + * it takes 0.6s to get back the page instead of 0.1s. + * + * Take 500 average documents, index them while counting the total + * time it takes to index. Divide by 500 and if the result is more + * than 0.1s, use a log/queue. + * + * FIXME: Concurrency problem if you index at the same time the same doc. + * + * @param Pluf_Model Document to index. + * @param Stemmer used. ('Pluf_Text_Stemmer_Porter') + * @return array Statistics. + */ + public static function index($doc, $stemmer='Pluf_Text_Stemmer_Porter') + { + $words = Pluf_Text::tokenize($doc->_toIndex()); + if ($stemmer != null) { + $words = self::stem($words, $stemmer); + } + // Get the total number of words. + $total = 0.0; + $words_flat = array(); + foreach ($words as $word => $occ) { + $total += (float) $occ; + $words_flat[] = $word; + } + // Drop the last indexation. + $gocc = new Pluf_Search_Occ(); + $sql = new Pluf_SQL('DELETE FROM '.$gocc->getSqlTable().' WHERE model_class=%s AND model_id=%s', array($doc->_model, $doc->id)); + $db =& Pluf::db(); + $db->execute($sql->gen()); + // Get the ids for each word. + $ids = self::getWordIds($words_flat); + // Insert a new word for the missing words and add the occ. + $n = count($ids); + $new_words = 0; + $done = array(); + for ($i=0;$i<$n;$i++) { + if ($ids[$i] === null) { + $word = new Pluf_Search_Word(); + $word->word = $words_flat[$i]; + try { + $word->create(); + $ids[$i] = $word->id; + } catch (Exception $e) { + // most likely concurrent addition of a word, try + // to read it. + $_ids = self::getWordIds(array($words_flat[$i])); + if ($_ids[0] !== null) { + // if we miss it here, just forget about it + $ids[$i] = $_ids[0]; + } + } + $new_words++; + } + if (isset($done[$ids[$i]])) { + continue; + } + $done[$ids[$i]] = true; + $occ = new Pluf_Search_Occ(); + $occ->word = new Pluf_Search_Word($ids[$i]); + $occ->model_class = $doc->_model; + $occ->model_id = $doc->id; + $occ->occ = $words[$words_flat[$i]]; + $occ->pondocc = $words[$words_flat[$i]]/$total; + $occ->create(); + } + // update the stats + $sql = new Pluf_SQL('model_class=%s AND model_id=%s', + array($doc->_model, $doc->id)); + $last_index = Pluf::factory('Pluf_Search_Stats')->getList(array('filter' => $sql->gen())); + if ($last_index->count() == 0) { + $stats = new Pluf_Search_Stats(); + $stats->model_class = $doc->_model; + $stats->model_id = $doc->id; + $stats->indexations = 1; + $stats->create(); + } else { + $last_index[0]->indexations += 1; + $last_index[0]->update(); + } + return array('total' => $total, 'new' => $new_words, 'unique'=>$n); + } +} \ No newline at end of file diff --git a/pluf/src/Pluf/Search/Occ.php b/pluf/src/Pluf/Search/Occ.php new file mode 100644 index 0000000..cf25dd3 --- /dev/null +++ b/pluf/src/Pluf/Search/Occ.php @@ -0,0 +1,92 @@ +_a['verbose'] = __('occurence'); + $this->_a['table'] = 'pluf_search_occs'; + $this->_a['model'] = 'Pluf_Search_Occ'; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + //It is automatically added. + 'blank' => true, + ), + 'word' => + array( + 'type' => 'Pluf_DB_Field_Foreignkey', + 'model' => 'Pluf_Search_Word', + 'blank' => false, + 'verbose' => __('word'), + ), + 'model_class' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 150, + 'verbose' => __('model class'), + ), + 'model_id' => + array( + 'type' => 'Pluf_DB_Field_Integer', + 'blank' => false, + 'verbose' => __('model id'), + ), + 'occ' => + array( + 'type' => 'Pluf_DB_Field_Integer', + 'blank' => false, + 'verbose' => __('occurences'), + ), + 'pondocc' => + array( + 'type' => 'Pluf_DB_Field_Float', + 'blank' => false, + 'verbose' => __('weighted occurence'), + ), + ); + $this->_a['idx'] = array( + 'model_class_id_combo_word_idx' => + array( + 'type' => 'unique', + 'col' => 'model_class, model_id, word', + ), + ); + + } + + function __toString() + { + return $this->word; + } +} + diff --git a/pluf/src/Pluf/Search/ResultSet.php b/pluf/src/Pluf/Search/ResultSet.php new file mode 100644 index 0000000..54977ad --- /dev/null +++ b/pluf/src/Pluf/Search/ResultSet.php @@ -0,0 +1,76 @@ +results = $search_res; + reset($this->results); + } + + /** + * Get the current item. + */ + public function current() + { + $i = current($this->results); + $doc = Pluf::factory($i['model_class'], $i['model_id']); + $doc->_searchScore = $i['score']; + return $doc; + } + + public function key() + { + return key($this->results); + } + + public function next() + { + next($this->results); + } + + public function rewind() + { + reset($this->results); + } + + public function valid() + { + // We know that the boolean false will not be stored as a + // field, so we can test against false to check if valid or + // not. + return (false !== current($this->results)); + } + + public function count() + { + return count($this->results); + } +} \ No newline at end of file diff --git a/pluf/src/Pluf/Search/Stats.php b/pluf/src/Pluf/Search/Stats.php new file mode 100644 index 0000000..75f12ae --- /dev/null +++ b/pluf/src/Pluf/Search/Stats.php @@ -0,0 +1,97 @@ +_a['verbose'] = __('search stats'); + $this->_a['table'] = 'pluf_search_stats'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + //It is automatically added. + 'blank' => true, + ), + 'model_class' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 150, + 'verbose' => __('model class'), + ), + 'model_id' => + array( + 'type' => 'Pluf_DB_Field_Integer', + 'blank' => false, + 'verbose' => __('model id'), + ), + 'indexations' => + array( + 'type' => 'Pluf_DB_Field_Integer', + 'blank' => false, + 'verbose' => __('number of indexations'), + 'default' => 0, + ), + 'creation_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('created at'), + ), + 'modif_dtime' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('modified at'), + ), + ); + $this->_a['idx'] = array( + 'model_class_id_combo_idx' => + array( + 'type' => 'unique', + 'col' => 'model_class, model_id', + ), + ); + + } + + function preSave($create=false) + { + if ($this->id == '') { + $this->creation_dtime = gmdate('Y-m-d H:i:s'); + } + $this->modif_dtime = gmdate('Y-m-d H:i:s'); + } + +} + diff --git a/pluf/src/Pluf/Search/Word.php b/pluf/src/Pluf/Search/Word.php new file mode 100644 index 0000000..fd796a2 --- /dev/null +++ b/pluf/src/Pluf/Search/Word.php @@ -0,0 +1,61 @@ +_a['verbose'] = __('word'); + $this->_a['table'] = 'pluf_search_words'; + $this->_a['model'] = 'Pluf_Search_Word'; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + //It is automatically added. + 'blank' => true, + ), + 'word' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'unique' => true, + 'size' => 150, + 'verbose' => __('word'), + ), + ); + $this->_a['views'] = array(); + } + + function __toString() + { + return $this->word; + } +} + diff --git a/pluf/src/Pluf/Session.php b/pluf/src/Pluf/Session.php new file mode 100644 index 0000000..9179d07 --- /dev/null +++ b/pluf/src/Pluf/Session.php @@ -0,0 +1,171 @@ +cookie_name = Pluf::f('session_cookie_id', 'sessionid'); + parent::_init(); + } + + function init() + { + $this->_a['table'] = 'sessions'; + $this->_a['model'] = 'Pluf_Session'; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + //It is automatically added. + 'blank' => true, + ), + 'session_key' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 100, + ), + 'session_data' => + array( + 'type' => 'Pluf_DB_Field_Text', + 'blank' => false, + ), + 'expire' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => false, + ), + ); + $this->_a['idx'] = array( + 'session_key_idx' => + array( + 'type' => 'unique', + 'col' => 'session_key' + ), + ); + $this->_admin = array(); + $this->_a['views'] = array(); + } + + /** + * Set some data in the session object. + * + * @param string Key + * @param mixed Value (null), if null, it is removing the value + * from the session + */ + function setData($key, $value=null) + { + if (is_null($value)) { + unset($this->data[$key]); + } else { + $this->data[$key] = $value; + } + $this->touched = true; + } + + function getData($key=null, $default='') + { + if (is_null($key)) { + return parent::getData(); + } + if (isset($this->data[$key])) { + return $this->data[$key]; + } else { + return $default; + } + } + + function clear() + { + $this->data = array(); + $this->touched = true; + } + + + /** + * Generate a new session key. + */ + function getNewSessionKey() + { + while (1) { + $key = md5(microtime().rand(0, 123456789).rand(0, 123456789) + .Pluf::f('secret_key')); + $sess = $this->getList(array('filter' => 'session_key=\''.$key.'\'')); + if (count($sess) == 0) { + break; + } + } + return $key; + } + + /** + * Presave/create function to encode data into session_data. + */ + function preSave($create=false) + { + $this->session_data = serialize($this->data); + if ($this->session_key == '') { + $this->session_key = $this->getNewSessionKey(); + } + $this->expire = gmdate('Y-m-d H:i:s', time()+31536000); + } + + /** + * Restore function to decode the session_data into $this->data. + */ + function restore() + { + $this->data = unserialize($this->session_data); + } + + /** + * Create a test cookie. + */ + public function createTestCookie() + { + $this->set_test_cookie = true; + } + + public function getTestCookie() + { + return ($this->test_cookie == $this->test_cookie_value); + } + + public function deleteTestCookie() + { + $this->set_test_cookie = true; + $this->test_cookie_value = null; + } +} diff --git a/pluf/src/Pluf/Shortcuts.php b/pluf/src/Pluf/Shortcuts.php new file mode 100644 index 0000000..5f460f9 --- /dev/null +++ b/pluf/src/Pluf/Shortcuts.php @@ -0,0 +1,109 @@ + 0 && $item->id == $id) { + return $item; + } + throw new Pluf_HTTP_Error404(); +} + +/** + * Get an object by SQL or raise a 404 error. + * + * Usage: + *
+ * $obj = Pluf_Shortcuts_GetOneOr404('MyApp_Model',
+ *                                   'path=%s AND status=%s',
+ *                                    array('welcome', 1));
+ * 
+ * + * @param string Model + * @param string Base SQL request + * @param string Parameters for the base SQL + * @return Object The found object + */ +function Pluf_Shortcuts_GetOneOr404($object, $bsql, $psql) +{ + $sql = new Pluf_SQL($bsql, $psql); + $item = Pluf::factory($object)->getOne(array('filter' => $sql->gen())); + if ($item != null) { + return $item; + } + throw new Pluf_HTTP_Error404(); +} + +/** + * Render a template file and an array as a reponse. + * + * If a none null request object is given, the context used will + * automatically be a Pluf_Template_Context_Request context and thus + * the context will be populated using the + * 'template_context_processors' functions. + * + * @param string Template file name + * @param array Associative array for the context + * @param Pluf_HTTP_Request Request object (null) + * @return Pluf_HTTP_Response The response with the rendered template + */ +function Pluf_Shortcuts_RenderToResponse($tplfile, $params, $request=null) +{ + $tmpl = new Pluf_Template($tplfile); + if (is_null($request)) { + $context = new Pluf_Template_Context($params); + } else { + $context = new Pluf_Template_Context_Request($request, $params); + } + return new Pluf_HTTP_Response($tmpl->render($context)); +} + + +/** + * Get a given form from a model. + * + * @param Object The model. + * @param array Data to bound the form (null) + * @param array Extra parameters (array()) + * @param string Label suffix (null) + * @return Object Form for this model. + */ +function Pluf_Shortcuts_GetFormForModel($model, $data=null, $extra=array(), $label_suffix=null) +{ + $extra['model'] = $model; + return new Pluf_Form_Model($data, $extra, $label_suffix); +} diff --git a/pluf/src/Pluf/Sign.php b/pluf/src/Pluf/Sign.php new file mode 100644 index 0000000..ef2f212 --- /dev/null +++ b/pluf/src/Pluf/Sign.php @@ -0,0 +1,174 @@ + + * $signed = Pluf_Sign::sign($mystring); + * // send the string over the wire + * $mystring = Pluf_Sign::unsign($signed); + * + * + * Usage to pack and sign an object: + *
+ * $signed = Pluf_Sign::dumps($myobject);
+ * // send the string over the wire
+ * $myobject = Pluf_Sign::loads($signed);
+ * 
+ * + * Based on the work by Simon Willison: + * http://github.com/simonw/django-openid/blob/master/django_openid/signed.py + */ +class Pluf_Sign +{ + /** + * Dump and sign an object. + * + * If you want to sign a small string, use directly the + * sign/unsign function as compression will not help and you will + * save the overhead of the serialize call. + * + * @param mixed Object + * @param string Key (null) + * @param bool Compress with gzdeflate (false) + * @param string Extra key not to use only the secret_key ('') + * @return string Signed string + */ + public static function dumps($obj, $key=null, $compress=false, $extra_key='') + { + $serialized = serialize($obj); + $is_compressed = false; // Flag for if it's been compressed or not + if ($compress) { + $compressed = gzdeflate($serialized, 9); + if (strlen($compressed) < (strlen($serialized) - 1)) { + $serialized = $compressed; + $is_compressed = true; + } + } + $base64d = Pluf_Utils::urlsafe_b64encode($serialized); + if ($is_compressed) { + $base64d = '.'.$base64d; + } + if ($key === null) { + $key = Pluf::f('secret_key'); + } + return self::sign($base64d, $key.$extra_key); + } + + /** + * Reverse of dumps, throw an Exception in case of bad signature. + * + * @param string Signed key + * @param string Key (null) + * @param string Extra key ('') + * @return mixed The dumped signed object + */ + public static function loads($s, $key=null, $extra_key='') + { + if ($key === null) { + $key = Pluf::f('secret_key'); + } + $base64d = self::unsign($s, $key.$extra_key); + $decompress = false; + if ($base64d[0] == '.') { + // It's compressed; uncompress it first + $base64d = substr($base64d, 1); + $decompress = true; + } + $serialized = Pluf_Utils::urlsafe_b64decode($base64d); + if ($decompress) { + $serialized = gzinflate($serialized); + } + return unserialize($serialized); + } + + /** + * Sign a string. + * + * If the key is not provided, it will use the secret_key + * available in the configuration file. + * + * The signature string is safe to use in URLs. So if the string to + * sign is too, you can use the signed string in URLs. + * + * @param string The string to sign + * @param string Optional key (null) + * @return string Signed string + */ + public static function sign($value, $key=null) + { + if ($key === null) { + $key = Pluf::f('secret_key'); + } + return $value.'.'.self::base64_hmac($value, $key); + } + + + /** + * Unsign a value. + * + * It will throw an exception in case of error in the process. + * + * @return string Signed string + * @param string Optional key (null) + * @param string The string + */ + public static function unsign($signed_value, $key=null) + { + if ($key === null) { + $key = Pluf::f('secret_key'); + } + $compressed = ($signed_value[0] == '.') ? '.' : ''; + if ($compressed) { + $signed_value = substr($signed_value, 1); + } + if (false === strpos($signed_value, '.')) { + throw new Exception('Missing signature (no . found in value).'); + } + list($value, $sig) = explode('.', $signed_value, 2); + if (self::base64_hmac($compressed.$value, $key) == $sig) { + return $compressed.$value; + } else { + throw new Exception(sprintf('Signature failed: "%s".', $sig)); + } + } + + /** + * Calculate the URL safe base64 encoded SHA1 hmac of a string. + * + * @param string The string to sign + * @param string The key + * @return string The signature + */ + public static function base64_hmac($value, $key) + { + return Pluf_Utils::urlsafe_b64encode(hash_hmac('sha1', $value, $key, true)); + } +} \ No newline at end of file diff --git a/pluf/src/Pluf/Signal.php b/pluf/src/Pluf/Signal.php new file mode 100644 index 0000000..e6cc136 --- /dev/null +++ b/pluf/src/Pluf/Signal.php @@ -0,0 +1,66 @@ +$val) { + if ($val[2] === null or $sender == $val[2]) { + call_user_func_array(array($val[0], $val[1]), + array($signal, &$params)); + } + } + } + } + + + /** + * Connect to a signal. + * + * @param string Name of the signal. + * @param array array('class', 'method') handling the signal. + * @param string Optional sender filtering. + */ + public static function connect($signal, $who, $sender=null) + { + if (!isset($GLOBALS['_PX_signal'][$signal])) { + $GLOBALS['_PX_signal'][$signal] = array(); + } + $GLOBALS['_PX_signal'][$signal][] = array($who[0], $who[1], $sender); + } +} + diff --git a/pluf/src/Pluf/Template.php b/pluf/src/Pluf/Template.php new file mode 100644 index 0000000..25562e5 --- /dev/null +++ b/pluf/src/Pluf/Template.php @@ -0,0 +1,338 @@ +tpl = $template; + if (null == $folders) { + $this->folders = Pluf::f('template_folders'); + } else { + $this->folders = $folders; + } + if (null == $cache) { + $this->cache = Pluf::f('tmp_folder'); + } else { + $this->cache = $cache; + } + if (defined('IN_UNIT_TESTS')) { + if (!isset($GLOBALS['_PX_tests_templates'])) { + $GLOBALS['_PX_tests_templates'] = array(); + } + } + $this->compiled_template = $this->getCompiledTemplateName(); + $b = $this->compiled_template[1]; + $this->class = 'Pluf_Template_'.$b; + $this->compiled_template = $this->compiled_template[0]; + if (!class_exists($this->class, false)) { + if (!file_exists($this->compiled_template) or Pluf::f('debug')) { + $compiler = new Pluf_Template_Compiler($this->tpl, $this->folders); + $this->template_content = $compiler->getCompiledTemplate(); + $this->write($b); + } + include $this->compiled_template; + } + } + + /** + * Render the template with the given context and return the content. + * + * @param Object Context. + */ + function render($c=null) + { + if (defined('IN_UNIT_TESTS')) { + $GLOBALS['_PX_tests_templates'][] = $this; + } + if (null == $c) { + $c = new Pluf_Template_Context(); + } + $this->context = $c; + ob_start(); + $t = $c; + try { + call_user_func(array($this->class, 'render'), $t); + //include $this->compiled_template; + } catch (Exception $e) { + ob_clean(); + throw $e; + } + $a = ob_get_contents(); + ob_end_clean(); + return $a; + } + + /** + * Get the full name of the compiled template. + * + * Ends with .phps to prevent execution from outside if the cache folder + * is not secured but to still have the syntax higlightings by the tools + * for debugging. + * + * @return string Full path to the compiled template + */ + function getCompiledTemplateName() + { + // The compiled template not only depends on the file but also + // on the possible folders in which it can be found. + $_tmp = var_export($this->folders, true); + return array($this->cache.'/Pluf_Template-'.md5($_tmp.$this->tpl).'.phps', + md5($_tmp.$this->tpl)); + } + + /** + * Write the compiled template in the cache folder. + * Throw an exception if it cannot write it. + * + * @return bool Success in writing + */ + function write($name) + { + $this->template_content = ''.$this->template_content.'compiled_template, 'a'); + if ($fp !== false) { + // Exclusive lock on writing + flock($fp, LOCK_EX); + // We have the unique pointeur, we truncate + ftruncate($fp, 0); + // Go back to the start of the file like a +w + rewind($fp); + fwrite($fp, $this->template_content, strlen($this->template_content)); + // Lock released, read access is possible + flock($fp, LOCK_UN); + fclose($fp); + @chmod($this->compiled_template, 0777); + return true; + } else { + throw new Exception(sprintf(__('Cannot write the compiled template: %s'), $this->compiled_template)); + } + return false; + } + + public static function markSafe($string) + { + return new Pluf_Template_SafeString($string, true); + } +} + +/** + * Set a string to be safe for display. + * + * @param string String to be safe for display. + * @return string Pluf_Template_SafeString + */ +function Pluf_Template_unsafe($string) +{ + return new Pluf_Template_SafeString($string, true); +} + +/** + * Special htmlspecialchars that can handle the objects. + * + * @param string String proceeded by htmlspecialchars + * @return string String like if htmlspecialchars was not applied + */ +function Pluf_Template_htmlspecialchars($string) +{ + return htmlspecialchars((string)$string, ENT_COMPAT, 'UTF-8'); +} + +/** + * Modifier plugin: Convert the date from GMT to local and format it. + * + * This is used as all the datetime are stored in GMT in the database. + * + * @param string $date input date string considered GMT + * @param string $format strftime format for output ('%b %e, %Y') + * @return string date in localtime + */ +function Pluf_Template_dateFormat($date, $format='%b %e, %Y') +{ + if (substr(PHP_OS,0,3) == 'WIN') { + $_win_from = array ('%e', '%T', '%D'); + $_win_to = array ('%#d', '%H:%M:%S', '%m/%d/%y'); + $format = str_replace($_win_from, $_win_to, $format); + } + $date = date('Y-m-d H:i:s', strtotime($date.' GMT')); + return strftime($format, strtotime($date)); +} + +/** + * Modifier plugin: Format a unix time. + * + * Warning: date format is directly to be used, not consideration of + * GMT or local time. + * + * @param int $time input date string considered GMT + * @param string $format strftime format for output ('Y-m-d H:i:s') + * @return string formated time + */ +function Pluf_Template_timeFormat($time, $format='Y-m-d H:i:s') +{ + return date($format, $time); +} + + +/** + * Special echo function that checks if the string to output is safe + * or not, if not it is escaped. + * + * @param mixed Input + * @return string Safe to display in HTML. + */ +function Pluf_Template_safeEcho($mixed, $echo=true) +{ + if ($echo) { + echo (!is_object($mixed) or 'Pluf_Template_SafeString' != get_class($mixed)) ? + htmlspecialchars($mixed, ENT_COMPAT, 'UTF-8') : + $mixed->value; + } else { + return (!is_object($mixed) or 'Pluf_Template_SafeString' != get_class($mixed)) ? + htmlspecialchars($mixed, ENT_COMPAT, 'UTF-8') : + $mixed->value; + } +} + +/** + * New line to
returning a safe string. + * + * @param mixed Input + * @return string Safe to display in HTML. + */ +function Pluf_Template_nl2br($mixed) +{ + if (!is_object($mixed) or 'Pluf_Template_SafeString' !== get_class($mixed)) { + return Pluf_Template::markSafe(nl2br(htmlspecialchars((string) $mixed, ENT_COMPAT, 'UTF-8'))); + } else { + return Pluf_Template::markSafe(nl2br($mixed->value)); + } +} + +/** + * Var export returning a safe string. + * + * @param mixed Input + * @return string Safe to display in HTML. + */ +function Pluf_Template_varExport($mixed) +{ + return Pluf_Template_unsafe('
'.Pluf_esc(var_export($mixed, true)).'
'); +} + + +/** + * Display the date in a "6 days, 23 hours ago" style. + */ +function Pluf_Template_dateAgo($date, $f='withal') +{ + Pluf::loadFunction('Pluf_Date_Easy'); + $date = Pluf_Template_dateFormat($date, '%Y-%m-%d %H:%M:%S'); + if ($f == 'withal') { + return Pluf_Date_Easy($date, null, 2, __('now')); + } else { + return Pluf_Date_Easy($date, null, 2, __('now'), false); + } +} + +/** + * Display the time in a "6 days, 23 hours ago" style. + */ +function Pluf_Template_timeAgo($date, $f="withal") +{ + Pluf::loadFunction('Pluf_Date_Easy'); + $date = Pluf_Template_timeFormat($date); + if ($f == 'withal') { + return Pluf_Date_Easy($date, null, 2, __('now')); + } else { + return Pluf_Date_Easy($date, null, 2, __('now'), false); + } +} + +/** + * Hex encode an email excluding the "mailto:". + */ +function Pluf_Template_safeEmail($email) +{ + $email = chunk_split(bin2hex($email), 2, '%'); + $email = '%'.substr($email, 0, strlen($email) - 1); + return Pluf_Template::markSafe($email); +} + +/** + * Returns the first item in the given array. + * + * @param array $array + * @return mixed An empty string if $array is not an array. + */ +function Pluf_Template_first($array) +{ + $array = (array) $array; + $result = array_shift($array); + if (null === $result) { + return ''; + } + + return $result; +} + +/** + * Returns the last item in the given array. + * + * @param array $array + * @return mixed An empty string if $array is not an array. + */ +function Pluf_Template_last($array) +{ + $array = (array) $array; + $result = array_pop($array); + if (null === $result) { + return ''; + } + + return $result; +} diff --git a/pluf/src/Pluf/Template/Compiler.php b/pluf/src/Pluf/Template/Compiler.php new file mode 100644 index 0000000..14ecd31 --- /dev/null +++ b/pluf/src/Pluf/Template/Compiler.php @@ -0,0 +1,679 @@ + 'strtoupper', + 'lower' => 'strtolower', + 'count' => 'count', + 'md5' => 'md5', + 'sha1' => 'sha1', + 'escxml' => 'htmlspecialchars', + 'escape' => 'Pluf_Template_htmlspecialchars', + 'strip_tags' => 'strip_tags', + 'escurl' => 'rawurlencode', + 'capitalize' => 'ucwords', + // Not var_export because of recursive issues. + 'debug' => 'print_r', + 'dump' => 'Pluf_Template_varExport', + 'fulldebug' => 'var_export', + 'nl2br' => 'Pluf_Template_nl2br', + 'trim' => 'trim', + 'ltrim' => 'ltrim', + 'rtrim' => 'rtrim', + 'unsafe' => 'Pluf_Template_unsafe', + 'safe' => 'Pluf_Template_unsafe', + 'date' => 'Pluf_Template_dateFormat', + 'time' => 'Pluf_Template_timeFormat', + 'dateago' => 'Pluf_Template_dateAgo', + 'timeago' => 'Pluf_Template_timeAgo', + 'email' => 'Pluf_Template_safeEmail', + 'first' => 'Pluf_Template_first', + 'last' => 'Pluf_Template_last', + ); + + /** + * After the compilation is completed, this contains the list of + * modifiers used in the template. The GetCompiledTemplate method + * will add a series of Pluf::loadFunction at the top to preload + * these modifiers. + */ + public $_usedModifiers = array(); + + /** + * Default allowed extra tags/functions. + * + * These default tags are merged with the 'template_tags' defined + * in the configuration of the application. + */ + protected $_allowedTags = array( + 'url' => 'Pluf_Template_Tag_Url', + 'aurl' => 'Pluf_Template_Tag_Rurl', + 'media' => 'Pluf_Template_Tag_MediaUrl', + 'amedia' => 'Pluf_Template_Tag_RmediaUrl', + 'aperm' => 'Pluf_Template_Tag_APerm', + 'getmsgs' => 'Pluf_Template_Tag_Messages', + ); + /** + * During compilation, all the tags are created once so to query + * their interface easily. + */ + protected $_extraTags = array(); + + /** + * The block stack to see if the blocks are correctly closed. + */ + protected $_blockStack = array(); + + /** + * Special stack for the translation handling in blocktrans. + */ + protected $_transStack = array(); + protected $_transPlural = false; + + /** + * Current template source file. + */ + protected $_sourceFile; + + /** + * Current tag. + */ + protected $_currentTag; + + /** + * Template folders. + */ + public $templateFolders = array(); + + /** + * Template content. It can be set directly from a string. + */ + public $templateContent = ''; + + /** + * The extend blocks. + */ + public $_extendBlocks = array(); + + /** + * The extended template. + */ + public $_extendedTemplate = ''; + + /** + * Construct the compiler. + * + * @param string Basename of the template file. + * @param array Base folders in which the templates files + * should be found. (array()) + * @param bool Load directly the template content. (true) + */ + function __construct($template_file, $folders=array(), $load=true) + { + /** + * [signal] + * + * Pluf_Template_Compiler::construct_template_tags_modifiers + * + * [sender] + * + * Pluf_Template_Compiler + * + * [description] + * + * This signal allows an application to dynamically modify the + * allowed template tags. The order of the merge with the ones + * configured in the configuration files and the default one + * is: default -> signal -> configuration file. + * That is, the configuration file is the highest authority. + * + * [parameters] + * + * array('tags' => array(), + * 'modifiers' => array()); + * + */ + $params = array('tags' => array(), + 'modifiers' => array()); + Pluf_Signal::send('Pluf_Template_Compiler::construct_template_tags_modifiers', + 'Pluf_Template_Compiler', $params); + $this->_allowedTags = array_merge($this->_allowedTags, + $params['tags'], + Pluf::f('template_tags', array())); + $this->_modifier = array_merge($this->_modifier, + $params['modifiers'], + Pluf::f('template_modifiers', array())); + foreach ($this->_allowedTags as $name=>$model) { + $this->_extraTags[$name] = new $model(); + } + $this->_sourceFile = $template_file; + $this->_allowedInVar = array_merge($this->_vartype, $this->_op); + $this->_allowedInExpr = array_merge($this->_vartype, $this->_op); + $this->_allowedAssign = array_merge($this->_vartype, $this->_assignOp, + $this->_op); + $this->templateFolders = $folders; + if ($load) { + $this->loadTemplateFile($template_file); + } + } + + /** + * Compile the template into a PHP code. + * + * @return string PHP code of the compiled template. + */ + function compile() + { + $this->compileBlocks(); + $tplcontent = $this->templateContent; + // Remove the template comments + $tplcontent = preg_replace('!{\*(.*?)\*}!s', '', $tplcontent); + // Remove PHP code + $tplcontent = preg_replace('!<\?php(.*?)\?>!s', '', $tplcontent); + // Catch the litteral blocks and put them in the + // $this->_literals stack + preg_match_all('!{literal}(.*?){/literal}!s', $tplcontent, $_match); + $this->_literals = $_match[1]; + $tplcontent = preg_replace("!{literal}(.*?){/literal}!s", '{literal}', $tplcontent); + // Core regex to parse the template + $result = preg_replace_callback('/{((.).*?)}/s', + array($this, '_callback'), + $tplcontent); + if (count($this->_blockStack)) { + trigger_error(sprintf(__('End tag of a block missing: %s'), end($this->_blockStack)), E_USER_ERROR); + } + return $result; + } + + /** + * Get a cleaned compile template. + * + */ + function getCompiledTemplate() + { + $result = $this->compile(); + if (count($this->_usedModifiers)) { + $code = array(); + foreach ($this->_usedModifiers as $modifier) { + $code[] = 'Pluf::loadFunction(\''.$modifier.'\'); '; + } + $result = ''.$result; + } + // Clean the output + $result = str_replace(array('?>', ''), '', $result); + // To avoid the triming of the \n after a php closing tag. + $result = str_replace("?>\n", "?>\n\n", $result); + return $result; + } + + /** + * Parse the extend blocks. + * + * If the current template extends another, it finds the extended + * template and grabs the defined blocks and compile them. + */ + function compileBlocks() + { + $tplcontent = $this->templateContent; + $this->_extendedTemplate = ''; + // Match extends on the first line of the template + if (preg_match("!{extends\s['\"](.*?)['\"]}!", $tplcontent, $_match)) { + $this->_extendedTemplate = $_match[1]; + } + // Get the blocks in the current template + $cnt = preg_match_all("!{block\s(\S+?)}(.*?){/block}!s", $tplcontent, $_match); + // Compile the blocks + for ($i=0; $i<$cnt; $i++) { + if (!isset($this->_extendBlocks[$_match[1][$i]]) + or false !== strpos($this->_extendBlocks[$_match[1][$i]], '~~{~~superblock~~}~~')) { + $compiler = clone($this); + $compiler->templateContent = $_match[2][$i]; + $_tmp = $compiler->compile(); + $this->updateModifierStack($compiler); + if (!isset($this->_extendBlocks[$_match[1][$i]])) { + $this->_extendBlocks[$_match[1][$i]] = $_tmp; + } else { + $this->_extendBlocks[$_match[1][$i]] = str_replace('~~{~~superblock~~}~~', $_tmp, $this->_extendBlocks[$_match[1][$i]]); + } + } + } + if (strlen($this->_extendedTemplate) > 0) { + // The template of interest is now the extended template + // as we are not in a base template + $this->loadTemplateFile($this->_extendedTemplate); + $this->_sourceFile = $this->_extendedTemplate; + $this->compileBlocks(); //It will recurse to the base template. + } else { + // Replace the current blocks by a place holder + if ($cnt) { + $this->templateContent = preg_replace("!{block\s(\S+?)}(.*?){/block}!s", "{block $1}", $tplcontent, -1); + } + } + } + + /** + * Load a template file. + * + * The path to the file to load is relative and the file is found + * in one of the $templateFolders array of folders. + * + * @param string Relative path of the file to load. + */ + function loadTemplateFile($file) + { + // FIXME: Very small security check, could be better. + if (strpos($file, '..') !== false) { + throw new Exception(sprintf(__('Template file contains invalid characters: %s'), $file)); + } + foreach ($this->templateFolders as $folder) { + if (file_exists($folder.'/'.$file)) { + $this->templateContent = file_get_contents($folder.'/'.$file); + return; + } + } + // File not found in all the folders. + throw new Exception(sprintf(__('Template file not found: %s'), $file)); + } + + function _callback($matches) + { + list(,$tag, $firstcar) = $matches; + if (!preg_match('/^\$|[\'"]|[a-zA-Z\/]$/', $firstcar)) { + trigger_error(sprintf(__('Invalid tag syntax: %s'), $tag), E_USER_ERROR); + return ''; + } + $this->_currentTag = $tag; + if (in_array($firstcar, array('$', '\'', '"'))) { + if ('blocktrans' !== end($this->_blockStack)) { + return '_parseVariable($tag).'); ?>'; + } else { + $tok = explode('|', $tag); + $this->_transStack[substr($tok[0], 1)] = $this->_parseVariable($tag); + return '%%'.substr($tok[0], 1).'%%'; + } + } else { + if (!preg_match('/^(\/?[a-zA-Z0-9_]+)(?:(?:\s+(.*))|(?:\((.*)\)))?$/', $tag, $m)) { + trigger_error(sprintf(__('Invalid function syntax: %s'), $tag), E_USER_ERROR); + return ''; + } + if (count($m) == 4){ + $m[2] = $m[3]; + } + if (!isset($m[2])) $m[2] = ''; + if($m[1] == 'ldelim') return '{'; + if($m[1] == 'rdelim') return '}'; + if ($m[1] != 'include') { + return '_parseFunction($m[1], $m[2]).'?>'; + } else { + return $this->_parseFunction($m[1], $m[2]); + } + } + } + + function _parseVariable($expr) + { + $tok = explode('|', $expr); + $res = $this->_parseFinal(array_shift($tok), $this->_allowedInVar); + foreach ($tok as $modifier) { + if (!preg_match('/^(\w+)(?:\:(.*))?$/', $modifier, $m)) { + trigger_error(sprintf(__('Invalid modifier syntax: (%s) %s'), $this->_currentTag, $modifier), E_USER_ERROR); + return ''; + } + $targs = array($res); + if(isset($m[2])){ + $res = $this->_modifier[$m[1]].'('.$res.','.$m[2].')'; + } + else if (isset($this->_modifier[$m[1]])) { + $res = $this->_modifier[$m[1]].'('.$res.')'; + } else { + trigger_error(sprintf(__('Unknown modifier: (%s) %s'), $this->_currentTag, $m[1]), E_USER_ERROR); + return ''; + } + if (!in_array($this->_modifier[$m[1]], $this->_usedModifiers)) { + $this->_usedModifiers[] = $this->_modifier[$m[1]]; + } + } + return $res; + } + + function _parseFunction($name, $args) + { + switch ($name) { + case 'if': + $res = 'if ('.$this->_parseFinal($args, $this->_allowedInExpr).'): '; + array_push($this->_blockStack, 'if'); + break; + case 'else': + if (end($this->_blockStack) != 'if') { + trigger_error(sprintf(__('End tag of a block missing: %s'), end($this->_blockStack)), E_USER_ERROR); + } + $res = 'else: '; + break; + case 'elseif': + if (end($this->_blockStack) != 'if') { + trigger_error(sprintf(__('End tag of a block missing: %s'), end($this->_blockStack)), E_USER_ERROR); + } + $res = 'elseif('.$this->_parseFinal($args, $this->_allowedInExpr).'):'; + break; + case 'foreach': + $res = 'foreach ('.$this->_parseFinal($args, array_merge(array(T_AS, T_DOUBLE_ARROW, T_STRING, T_OBJECT_OPERATOR, T_LIST, $this->_allowedAssign, '[', ']')), array(';','!')).'): '; + array_push($this->_blockStack, 'foreach'); + break; + case 'while': + $res = 'while('.$this->_parseFinal($args,$this->_allowedInExpr).'):'; + array_push($this->_blockStack, 'while'); + break; + case '/foreach': + case '/if': + case '/while': + $short = substr($name,1); + if(end($this->_blockStack) != $short){ + trigger_error(sprintf(__('End tag of a block missing: %s'), end($this->_blockStack)), E_USER_ERROR); + } + array_pop($this->_blockStack); + $res = 'end'.$short.'; '; + break; + case 'assign': + $res = $this->_parseFinal($args, $this->_allowedAssign).'; '; + break; + case 'literal': + if(count($this->_literals)){ + $res = '?>'.array_shift($this->_literals).''.$this->_extendBlocks[$args].'~~{~~superblock~~}~~_parseFinal($args, $this->_allowedAssign); + $res = 'echo(__('.$argfct.'));'; + break; + case 'blocktrans': + array_push($this->_blockStack, 'blocktrans'); + $res = ''; + $this->_transStack = array(); + if ($args) { + $this->_transPlural = true; + $_args = $this->_parseFinal($args, $this->_allowedAssign, + array(';', '[', ']'), true); + $res .= '$_b_t_c='.trim(array_shift($_args)).'; '; + } + $res .= 'ob_start(); '; + break; + case '/blocktrans': + $short = substr($name,1); + if(end($this->_blockStack) != $short){ + trigger_error(sprintf(__('End tag of a block missing: %s'), end($this->_blockStack)), E_USER_ERROR); + } + $res = ''; + if ($this->_transPlural) { + $res .= '$_b_t_p=ob_get_contents(); ob_end_clean(); echo('; + $res .= 'Pluf_Translation::sprintf(_n($_b_t_s, $_b_t_p, $_b_t_c), array('; + $_tmp = array(); + foreach ($this->_transStack as $key=>$_trans) { + $_tmp[] = '\''.addslashes($key).'\' => Pluf_Template_safeEcho('.$_trans.', false)'; + } + $res .= implode(', ', $_tmp); + unset($_trans, $_tmp); + $res .= ')));'; + $this->_transStack = array(); + } else { + $res .= '$_b_t_s=ob_get_contents(); ob_end_clean(); '; + if (count($this->_transStack) == 0) { + $res .= 'echo(__($_b_t_s)); '; + } else { + $res .= 'echo(Pluf_Translation::sprintf(__($_b_t_s), array('; + $_tmp = array(); + foreach ($this->_transStack as $key=>$_trans) { + $_tmp[] = '\''.addslashes($key).'\' => Pluf_Template_safeEcho('.$_trans.', false)'; + } + $res .= implode(', ', $_tmp); + unset($_trans, $_tmp); + $res .= '))); '; + $this->_transStack = array(); + } + } + $this->_transPlural = false; + array_pop($this->_blockStack); + break; + case 'plural': + $res = '$_b_t_s=ob_get_contents(); ob_end_clean(); ob_start(); '; + break; + case 'include': + // XXX fixme: Will need some security check, when online editing. + $argfct = preg_replace('!^[\'"](.*)[\'"]$!', '$1', $args); + $_comp = new Pluf_Template_Compiler($argfct, $this->templateFolders); + $res = $_comp->compile(); + $this->updateModifierStack($_comp); + break; + default: + $_end = false; + $oname = $name; + if (substr($name, 0, 1) == '/') { + $_end = true; + $name = substr($name, 1); + } + // Here we should allow custom blocks. + + // Here we start the template tag calls at the template tag + // {tag ...} is not a block, so it must be a function. + if (!isset($this->_allowedTags[$name])) { + trigger_error(sprintf(__('The function tag "%s" is not allowed.'), $name), E_USER_ERROR); + } + $argfct = $this->_parseFinal($args, $this->_allowedAssign); + // $argfct is a string that can be copy/pasted in the PHP code + // but we need the array of args. + $res = ''; + if (isset($this->_extraTags[$name])) { + if (false == $_end) { + if (method_exists($this->_extraTags[$name], 'start')) { + $res .= '$_extra_tag = Pluf::factory(\''.$this->_allowedTags[$name].'\', $t); $_extra_tag->start('.$argfct.'); '; + } + if (method_exists($this->_extraTags[$name], 'genStart')) { + $res .= $this->_extraTags[$name]->genStart(); + } + } else { + if (method_exists($this->_extraTags[$name], 'end')) { + $res .= '$_extra_tag = Pluf::factory(\''.$this->_allowedTags[$name].'\', $t); $_extra_tag->end('.$argfct.'); '; + } + if (method_exists($this->_extraTags[$name], 'genEnd')) { + $res .= $this->_extraTags[$name]->genEnd(); + } + } + } + if ($res == '') { + trigger_error(sprintf(__('The function tag "{%s ...}" is not supported.'), $oname), E_USER_ERROR); + } + } + return $res; + } + + /* + + ------- + if: op, autre, var + foreach: T_AS, T_DOUBLE_ARROW, T_VARIABLE, @locale@ + for: autre, fin_instruction + while: op, autre, var + assign: T_VARIABLE puis assign puis autre, ponctuation, T_STRING + echo: T_VARIABLE/@locale@ puis autre + ponctuation + modificateur: serie de autre séparé par une virgule + + tous : T_VARIABLE, @locale@ + + */ + + function _parseFinal($string, $allowed=array(), + $exceptchar=array(';'), $getAsArray=false) + { + $tokens = token_get_all(''); + $result = ''; + $first = true; + $inDot = false; + $firstok = array_shift($tokens); + $afterAs = false; + $f_key = ''; + $f_val = ''; + $results = array(); + + // il y a un bug, parfois le premier token n'est pas T_OPEN_TAG... + if ($firstok == '<' && $tokens[0] == '?' && is_array($tokens[1]) + && $tokens[1][0] == T_STRING && $tokens[1][1] == 'php') { + array_shift($tokens); + array_shift($tokens); + } + foreach ($tokens as $tok) { + if (is_array($tok)) { + list($type, $str) = $tok; + $first = false; + if($type == T_CLOSE_TAG){ + continue; + } + if ($type == T_AS) { + $afterAs = true; + } + if ($type == T_STRING && $inDot) { + $result .= $str; + } elseif ($type == T_VARIABLE) { + //$result .= '$t->_vars[\''.substr($str, 1).'\']'; + $result .= '$t->_vars->'.substr($str, 1); + } elseif ($type == T_WHITESPACE || in_array($type, $allowed)) { + $result .= $str; + } else { + trigger_error(sprintf(__('Invalid syntax: (%s) %s.'), $this->_currentTag, $str.' tokens'.var_export($tokens, true)), E_USER_ERROR); + return ''; + } + } else { + if (in_array($tok, $exceptchar)) { + trigger_error(sprintf(__('Invalid character: (%s) %s.'), $this->_currentTag, $tok), E_USER_ERROR); + } elseif ($tok == '.') { + $inDot = true; + $result .= '->'; + } elseif ($tok == '~') { + $result .= '.'; + } elseif ($tok =='[') { + $result.=$tok; + } elseif ($tok ==']') { + $result.=$tok; + } elseif ($getAsArray && $tok == ',') { + $results[]=$result; + $result=''; + } else { + $result .= $tok; + } + $first = false; + } + } + if (!$getAsArray) { + return $result; + } else { + if ($result != '') { + $results[] = $result; + } + return $results; + } + } + + /** + * Update the current stack of modifiers from another compiler. + */ + protected function updateModifierStack($compiler) + { + foreach ($compiler->_usedModifiers as $_um) { + if (!in_array($_um, $this->_usedModifiers)) { + $this->_usedModifiers[] = $_um; + } + } + } +} diff --git a/pluf/src/Pluf/Template/Context.php b/pluf/src/Pluf/Template/Context.php new file mode 100644 index 0000000..a5371f4 --- /dev/null +++ b/pluf/src/Pluf/Template/Context.php @@ -0,0 +1,48 @@ +_vars = new Pluf_Template_ContextVars($vars); + } + + function get($var) + { + if (isset($this->_vars[$var])) { + return $this->_vars[$var]; + } + return ''; + } + + function set($var, $value) + { + $this->_vars[$var] = $value; + } +} diff --git a/pluf/src/Pluf/Template/Context/Request.php b/pluf/src/Pluf/Template/Context/Request.php new file mode 100644 index 0000000..4721ccc --- /dev/null +++ b/pluf/src/Pluf/Template/Context/Request.php @@ -0,0 +1,65 @@ + $request), $vars); + foreach (Pluf::f('template_context_processors', array()) as $proc) { + Pluf::loadFunction($proc); + $vars = array_merge($proc($request), $vars); + } + $params = array('request' => $request, + 'context' => $vars); + /** + * [signal] + * + * Pluf_Template_Context_Request::construct + * + * [sender] + * + * Pluf_Template_Context_Request + * + * [description] + * + * This signal allows an application to dynamically modify the + * context array. + * + * [parameters] + * + * array('request' => $request, + * 'context' => array()); + * + */ + Pluf_Signal::send('Pluf_Template_Context_Request::construct', + 'Pluf_Template_Context_Request', $params); + $this->_vars = new Pluf_Template_ContextVars($params['context']); + } +} diff --git a/pluf/src/Pluf/Template/ContextVars.php b/pluf/src/Pluf/Template/ContextVars.php new file mode 100644 index 0000000..a5b0f69 --- /dev/null +++ b/pluf/src/Pluf/Template/ContextVars.php @@ -0,0 +1,43 @@ +value = $mixed->value; + } else { + $this->value = ($safe) ? $mixed : htmlspecialchars($mixed, ENT_COMPAT, 'UTF-8'); + } + } + + function __toString() + { + return $this->value; + } + + public static function markSafe($string) + { + return new Pluf_Template_SafeString($string, true); + } +} \ No newline at end of file diff --git a/pluf/src/Pluf/Template/Tag.php b/pluf/src/Pluf/Template/Tag.php new file mode 100644 index 0000000..eb544b1 --- /dev/null +++ b/pluf/src/Pluf/Template/Tag.php @@ -0,0 +1,37 @@ +context = $context; + } +} diff --git a/pluf/src/Pluf/Template/Tag/APerm.php b/pluf/src/Pluf/Template/Tag/APerm.php new file mode 100644 index 0000000..aa42b09 --- /dev/null +++ b/pluf/src/Pluf/Template/Tag/APerm.php @@ -0,0 +1,49 @@ + + * {aperm 'can_drive', $user, 'MyApp.can_drive'} + * {aperm 'can_drive_big_car', $user, 'MyApp.can_drive', $bigcar} + * {if $can_drive}Can drive!{/if} + * + * + */ +class Pluf_Template_Tag_APerm extends Pluf_Template_Tag +{ + /** + * @param string Variable to get the permission + * @param Pluf_User + * @param string Permission string + * @param mixed Optional Pluf_Model if using row level permission (null) + */ + function start($var, $user, $perm, $object=null) + { + $this->context->set($var, $user->hasPerm($perm, $object)); + } +} diff --git a/pluf/src/Pluf/Template/Tag/Cfg.php b/pluf/src/Pluf/Template/Tag/Cfg.php new file mode 100644 index 0000000..63b7de8 --- /dev/null +++ b/pluf/src/Pluf/Template/Tag/Cfg.php @@ -0,0 +1,51 @@ +context->set($prefix.$cfg, Pluf::f($cfg, $default)); + } + } + } +} diff --git a/pluf/src/Pluf/Template/Tag/Cycle.php b/pluf/src/Pluf/Template/Tag/Cycle.php new file mode 100644 index 0000000..0643ec4 --- /dev/null +++ b/pluf/src/Pluf/Template/Tag/Cycle.php @@ -0,0 +1,153 @@ +cycle. + * + * Cycle among the given strings or variables each time this tag is + * encountered. + * + * Within a loop, cycles among the given strings each time through the loop: + * + * + * {foreach $some_list as $obj} + * + * ... + * + * {/foreach} + * + * + * You can use variables, too. For example, if you have two + * template variables, $rowvalue1 and $rowvalue2, you can + * cycle between their values like this: + * + * + * {foreach $some_list as $obj} + * + * ... + * + * {/foreach} + * + * + * You can mix variables and strings: + * + * + * {foreach $some_list as $obj} + * + * ... + * + * {/foreach} + * + * + * In some cases you might want to refer to the next value of a cycle + * from outside of a loop. To do this, just group the arguments into + * an array and give the {cycle} tag name last, like this: + * + * + * {cycle array('row1', 'row2'), 'rowcolors'} + * + * + * From then on, you can insert the current value of the cycle + * wherever you'd like in your template: + * + * + * ... + * ... + * + * Based on concepts from the Django cycle template tag. + */ +class Pluf_Template_Tag_Cycle extends Pluf_Template_Tag +{ + /** + * @see Pluf_Template_Tag::start() + * @throws InvalidArgumentException If no argument is provided. + */ + public function start() + { + $nargs = func_num_args(); + if (1 > $nargs) { + throw new InvalidArgumentException( + '`cycle` tag requires at least one argument' + ); + } + + $result = ''; + list($key, $index) = $this->_computeIndex(func_get_args()); + + switch ($nargs) { + # (array or mixed) argument + case 1: + $arg = func_get_arg(0); + if (is_array($arg)) { + $result = $arg[$index % count($arg)]; + } else { + $result = $arg; + } + break; + + # (array) arguments, (string) assign + case 2: + $args = func_get_args(); + if (is_array($args[0])) { + $last = array_pop($args); + if (is_string($last) && '' === $this->context->get($last)) { + $value = Pluf_Utils::flattenArray($args[0]); + $this->context->set($last, $value); + + list($assign_key, $assign_index) = $this->_computeIndex(array($value)); + $result = $value[0]; + } + break; + } + + # considers all the arguments as a value to use in the cycle + default: + $args = Pluf_Utils::flattenArray(func_get_args()); + $result = $args[$index % count($args)]; + break; + } + + echo Pluf_Template::markSafe((string) $result); + } + + /** + * Compute an index for the given array. + * + * @param array + * @return array A array of two elements: key and index. + */ + protected function _computeIndex($args) + { + if (!isset($this->context->__cycle_stack)) { + $this->context->__cycle_stack = array(); + } + + $key = serialize($args); + $this->context->__cycle_stack[$key] = (array_key_exists($key, $this->context->__cycle_stack)) ? + 1 + $this->context->__cycle_stack[$key] : + 0; + $index = $this->context->__cycle_stack[$key]; + + return array($key, $index); + } +} diff --git a/pluf/src/Pluf/Template/Tag/Firstof.php b/pluf/src/Pluf/Template/Tag/Firstof.php new file mode 100644 index 0000000..40af976 --- /dev/null +++ b/pluf/src/Pluf/Template/Tag/Firstof.php @@ -0,0 +1,79 @@ +firstof. + * + * Outputs the first variable passed that is not false, without escaping. + * Outputs nothing if all the passed variables are false. + * + * Sample usage: + * + * {firstof array($var1, $var2, $var3)} + * + * This is equivalent to: + * + * + * {if $var1} + * {$var1|safe} + * {elseif $var2} + * {$var2|safe} + * {elseif $var3} + * {$var3|safe} + * {/if} + * + * + * You can also use a literal string as a fallback value in case all + * passed variables are false: + * + * {firstof array($var1, $var2, $var3), "fallback value"} + * + * Based on concepts from the Django firstof template tag. + */ +class Pluf_Template_Tag_Firstof extends Pluf_Template_Tag +{ + /** + * @see Pluf_Template_Tag::start() + * @param string $token Variables to test. + * @param string $fallback Literal string to used when all passed variables are false. + * @throws InvalidArgumentException If no argument is provided. + */ + public function start($tokens = array(), $fallback = null) + { + if (!is_array($tokens) || 0 === count($tokens)) { + throw new InvalidArgumentException( + '`firstof` tag requires at least one array as argument' + ); + } + $result = (string) $fallback; + + foreach ($tokens as $var) { + if ($var) { + $result = Pluf_Template::markSafe((string) $var); + break; + } + } + + echo $result; + } +} diff --git a/pluf/src/Pluf/Template/Tag/MediaUrl.php b/pluf/src/Pluf/Template/Tag/MediaUrl.php new file mode 100644 index 0000000..41acaf1 --- /dev/null +++ b/pluf/src/Pluf/Template/Tag/MediaUrl.php @@ -0,0 +1,41 @@ +isAnonymous()) { + $messages = $user->getAndDeleteMessages(); + if (count($messages) > 0) { + echo '
'."\n".'
    '."\n"; + foreach ($messages as $m) { + echo '
  • '.$m.'
  • '; + } + echo '
'; + } + } + } +} diff --git a/pluf/src/Pluf/Template/Tag/Mytag.php b/pluf/src/Pluf/Template/Tag/Mytag.php new file mode 100644 index 0000000..98ffec9 --- /dev/null +++ b/pluf/src/Pluf/Template/Tag/Mytag.php @@ -0,0 +1,89 @@ +context + */ + function start($param1, $param2) + { + echo 'start of tag mytag:
'; + echo '$this->context[mytag]: ' + .$this->context->get('mytag').'
'; + } + + /** + * Generate some valid PHP code to be put in the template. + * + * The code generated by this function is included in the + * template just after the call to $this->start() if the start() + * method is implemented. + * + * You cannot access the template context but you can write + * code that is modifying it through $t + */ + function genStart() + { + return '$t->set(\'mytag\', \'hello world!\');'; + } + + /** + * Perform some operations at the closing of the + * tag {/mytag 'param1'}. + * + * You can access the template context through + * $this->context + */ + function end($param1) + { + echo 'end of tag mytag:
'; + echo '$this->context[mytag]: ' + .$this->context->get('mytag').'
'; + } + + /** + * Generate some valid PHP code to be put in the template. + * + * The code generated by this function is included in the + * template just after the call to $this->end() if the end() + * method is implemented. + * + * You cannot access the template context but you can write + * code that is modifying it through $t + */ + + function genEnd() + { + // Cleaning :) + return '$t->set(\'mytag\', \'\');'; + } + +} diff --git a/pluf/src/Pluf/Template/Tag/Now.php b/pluf/src/Pluf/Template/Tag/Now.php new file mode 100644 index 0000000..5126b32 --- /dev/null +++ b/pluf/src/Pluf/Template/Tag/Now.php @@ -0,0 +1,46 @@ +now. + * + * Displays the date, formatted according to the given string. + * + * Sample usage: + * It is {now "jS F Y H:i"} + * + * Based on concepts from the Django now template tag. + * + * @link http://php.net/date for all the possible values. + */ +class Pluf_Template_Tag_Now extends Pluf_Template_Tag +{ + /** + * @see Pluf_Template_Tag::start() + * @param string $token Format to be applied. + */ + public function start($token) + { + echo date($token); + } +} diff --git a/pluf/src/Pluf/Template/Tag/Regroup.php b/pluf/src/Pluf/Template/Tag/Regroup.php new file mode 100644 index 0000000..32cf857 --- /dev/null +++ b/pluf/src/Pluf/Template/Tag/Regroup.php @@ -0,0 +1,165 @@ +regroup. + * + * Regroup a list of alike objects by a common attribute. + * + * This complex tag is best illustrated by use of an example: + * say that people is a list of people represented by arrays with + * first_name, last_name, and gender keys: + * + * + * $people = array( + * array('first_name' => 'George', + * 'last_name' => 'Bush', + * 'gender' => 'Male'), + * array('first_name' => 'Bill', + * 'last_name' => 'Clinton', + * 'gender' => 'Male'), + * array('first_name' => 'Margaret', + * 'last_name' => 'Thatcher', + * 'gender' => 'Female'), + * array('first_name' => 'Condoleezza', + * 'last_name' => 'Rice', + * 'gender' => 'Female'), + * array('first_name' => 'Pat', + * 'last_name' => 'Smith', + * 'gender' => 'Unknow'), + * ); + * + * + * ...and you'd like to display a hierarchical list that is ordered by + * gender, like this: + * + *
    + *
  • Male: + *
      + *
    • George Bush
    • + *
    • Bill Clinton
    • + *
    + *
  • + *
  • Female: + *
      + *
    • Margaret Thatcher
    • + *
    • Condoleezza Rice
    • + *
    + *
  • + *
  • Unknown: + *
      + *
    • Pat Smith
    • + *
    + *
  • + *
+ * + * You can use the {regroup} tag to group the list of people by + * gender. The following snippet of template code would accomplish this: + * + * + * {regroup $people, 'gender', 'gender_list'} + *
    + * {foreach $gender_list as $gender} + *
  • {$gender.grouper}: + *
      + * {foreach $gender.list as $item} + *
    • {$item.first_name} {$item.last_name}
    • + * {/foreach} + *
    + *
  • + * {/foreach} + *
+ *
+ * + * Let's walk through this example. {regroup} takes three arguments: + * the object (array or instance of Pluf_Model or any object) + * you want to regroup, the attribute to group by,and the name of the + * resulting object. Here, we're regrouping the people list by the + * gender attribute and calling the result gender_list. The result is + * assigned in a context varible of the same name $gender_list. + * + * {regroup} produces a instance of ArrayObject (in this case, $gender_list) + * of group objects. Each group object has two attributes: + * + *
    + *
  • grouper -- the item that was grouped by + * (e.g., the string "Male" or "Female").
  • + *
  • list -- an ArrayObject of all items in this group + * (e.g., an ArrayObject of all people with gender='Male').
  • + *
+ * + * Note that {regroup} does not order its input! + * + * Based on concepts from the Django regroup template tag. + */ +class Pluf_Template_Tag_Regroup extends Pluf_Template_Tag +{ + /** + * @see Pluf_Template_Tag::start() + * @param mixed $data The object to group. + * @param string $by The attribute ti group by. + * @param string $assign The name of the resulting object. + * @throws InvalidArgumentException If no argument is provided. + */ + public function start($data, $by, $assign) + { + $grouped = array(); + $tmp = array(); + + foreach ($data as $group) { + if (is_object($group)) { + if (is_subclass_of($group, 'Pluf_Model')) { + $raw = $group->getData(); + if (!array_key_exists($by, $raw)) { + continue; + } + } else { + $ref = new ReflectionObject($group); + if (!$ref->hasProperty($by)) { + continue; + } + } + $key = $group->$by; + $list = $group; + } else { + if (!array_key_exists($by, $group)) { + continue; + } + $key = $group[$by]; + $list = new ArrayObject($group, ArrayObject::ARRAY_AS_PROPS); + } + + if (!array_key_exists($key, $tmp)) { + $tmp[$key] = array(); + } + $tmp[$key][] = $list; + } + + foreach ($tmp as $key => $list) { + $grouped[] = new ArrayObject(array('grouper' => $key, + 'list' => $list), + ArrayObject::ARRAY_AS_PROPS); + } + $this->context->set(trim($assign), $grouped); + } +} diff --git a/pluf/src/Pluf/Template/Tag/RmediaUrl.php b/pluf/src/Pluf/Template/Tag/RmediaUrl.php new file mode 100644 index 0000000..43d2dff --- /dev/null +++ b/pluf/src/Pluf/Template/Tag/RmediaUrl.php @@ -0,0 +1,18 @@ +context->set($var, + Pluf_Template_Tag_MediaUrl::url($file)); + } +} + diff --git a/pluf/src/Pluf/Template/Tag/Rurl.php b/pluf/src/Pluf/Template/Tag/Rurl.php new file mode 100644 index 0000000..e441c19 --- /dev/null +++ b/pluf/src/Pluf/Template/Tag/Rurl.php @@ -0,0 +1,36 @@ +context->set($var, + Pluf_HTTP_URL_urlForView($view, $params, $get_params)); + } +} diff --git a/pluf/src/Pluf/Template/Tag/Url.php b/pluf/src/Pluf/Template/Tag/Url.php new file mode 100644 index 0000000..46b9511 --- /dev/null +++ b/pluf/src/Pluf/Template/Tag/Url.php @@ -0,0 +1,32 @@ + + * $client = new Pluf_Test_Client('./path/to/app-views.php'); + * $response = $client->get('/the/page/', array('var'=>'toto')); + * $response is now the Pluf_HTTP_Response + * + * + */ +class Pluf_Test_Client +{ + public $views = ''; + public $dispatcher = ''; + public $cookies = array(); + + public function __construct($views) + { + $this->views = $views; + $this->dispatcher = new Pluf_Dispatcher(); + $this->dispatcher->loadControllers($this->views); + $this->clean(false); + } + + protected function clean($keepcookies=true) + { + $_REQUEST = array(); + if (!$keepcookies) { + $_COOKIE = array(); + $this->cookies = array(); + } + $_SERVER = array(); + $_GET = array(); + $_POST = array(); + $_FILES = array(); + $_SERVER['REQUEST_METHOD'] = ''; + $_SERVER['REQUEST_URI'] = ''; + $_SERVER['REMOTE_ADDR'] = '127.0.0.1'; + $_SERVER['HTTP_HOST'] = 'localhost'; + } + + protected function dispatch($page) + { + $GLOBALS['_PX_tests_templates'] = array(); + $_SERVER['REQUEST_URI'] = $page; + foreach ($this->cookies as $cookie => $data) { + $_COOKIE[$cookie] = $data; + } + ob_implicit_flush(False); + list($request, $response) = $this->dispatcher->dispatch($page); + ob_start(); + $response->render(); + $content = ob_get_contents(); + ob_end_clean(); + $response->content = $content; + $response->request = $request; + if (isset($GLOBALS['_PX_tests_templates'])) { + if (count($GLOBALS['_PX_tests_templates']) == 1) { + $response->template = $GLOBALS['_PX_tests_templates'][0]; + } else { + $response->template = $GLOBALS['_PX_tests_templates']; + } + } + foreach ($response->cookies as $cookie => $data) { + $_COOKIE[$cookie] = $data; + $this->cookies[$cookie] = $data; + } + return $response; + } + + public function get($page, $params=array()) + { + $this->clean(); + $_GET = $params; + $_REQUEST = $params; + $_SERVER['REQUEST_METHOD'] = 'GET'; + $response = $this->dispatch($page); + $code = $response->status_code; + if ($code == 302) { + list($page, $params) = $this->parseRedirect($response->headers['Location']); + $response = $this->get($page, $params); + } + return $response; + } + + + public function post($page, $params=array(), $files=array()) + { + $this->clean(); + $_POST = $params; + $_REQUEST = $params; + $_FILES = $files; //FIXME need to match the correct array structure + $_SERVER['REQUEST_METHOD'] = 'POST'; + $response = $this->dispatch($page); + if ($response->status_code == 302) { + list($page, $params) = $this->parseRedirect($response->headers['Location']); + return $this->get($page, $params); + } + return $response; + } + + public function parseRedirect($location) + { + $page = parse_url($location, PHP_URL_PATH); + $query = parse_url($location, PHP_URL_QUERY); + $params = array(); + if (strlen($query)) { + parse_str($query, $params); + } + return array($page, $params); + } +} + diff --git a/pluf/src/Pluf/Test/Fixture.php b/pluf/src/Pluf/Test/Fixture.php new file mode 100644 index 0000000..d53b72a --- /dev/null +++ b/pluf/src/Pluf/Test/Fixture.php @@ -0,0 +1,113 @@ + 0) { + $item = new $model['model']($model['pk']); + if ($item->id == $model['pk']) { + throw new Exception(sprintf(__('Cannot load existing model <%1$s(%2$s)>.'), $model['model'], $model['pk'])); + } + } + $m = new $model['model'](); + $m->setFromFormData($model['fields']); + $m->create(true); // we load in raw mode + $created[] = array($model['model'], $model['pk']); + } + return $created; + } + + /** + * Given a model or model name, dump the content. + * + * If the object is given, only this single object is dumped else + * the complete table. + * + * @param mixed Model object or model name + * @param bool Serialize as JSON (true) + * @return mixed Array or JSON string + */ + public static function dump($model, $serialize=true) + { + if (is_object($model)) { + return ($serialize) ? + json_encode(array(self::prepare($model))) : + array(self::prepare($model)); + } + $out = array(); + foreach (Pluf::factory($model)->getList(array('order' =>'id ASC')) as $item) { + $out[] = self::prepare($item); + } + return ($serialize) ? json_encode($out) : $out; + } + + /** + * Return an array, ready to be serialized as json. + */ + public static function prepare($model) + { + $out = array('model' => $model->_a['model'], + 'pk' => $model->id, + 'fields' => array()); + foreach ($model->_a['cols'] as $col=>$val) { + $field = new $val['type'](); + if ($field->type != 'manytomany') { + $out['fields'][$col] = $model->$col; + } else { + $func = 'get_'.$col.'_list'; + $out['fields'][$col] = array(); + foreach ($model->$func() as $item) { + $out['fields'][$col][] = $item->id; + } + } + } + return $out; + } +} \ No newline at end of file diff --git a/pluf/src/Pluf/Test/TemplatetagsUnitTestCase.php b/pluf/src/Pluf/Test/TemplatetagsUnitTestCase.php new file mode 100644 index 0000000..9030e15 --- /dev/null +++ b/pluf/src/Pluf/Test/TemplatetagsUnitTestCase.php @@ -0,0 +1,91 @@ +tag_name.'` template tag.'; + parent::__construct($label); + + if (null === $this->tag_name) { + throw new LogicException('You must initialize the `$tag_name` property.'); + } + if (null === $this->tag_class) { + throw new LogicException('You must initialize the `$tag_class` property.'); + } + + $folder = Pluf::f('tmp_folder').'/templatetags'; + if (!file_exists($folder)) { + mkdir($folder, 0777, true); + } + $this->tpl_folders = array($folder); + + Pluf_Signal::connect('Pluf_Template_Compiler::construct_template_tags_modifiers', + array($this, 'addTemplatetag')); + } + + public function addTemplatetag($signal, &$params) + { + $params['tags'] = array_merge($params['tags'], + array($this->tag_name => $this->tag_class)); + } + + protected function writeTemplateFile($tpl_name, $content) + { + $file = $this->tpl_folders[0].'/'.$tpl_name; + if (file_exists($file)) { + unlink($file); + } + file_put_contents($file, $content); + } + + protected function getNewTemplate($content = '') + { + $tpl_name = sprintf('%s-%s.html', + get_class($this), + md5($content.microtime(true))); + $this->writeTemplateFile($tpl_name, $content); + + return new Pluf_Template($tpl_name, $this->tpl_folders); + } +} diff --git a/pluf/src/Pluf/Tests/Cache/Apc.php b/pluf/src/Pluf/Tests/Cache/Apc.php new file mode 100644 index 0000000..1e5c51c --- /dev/null +++ b/pluf/src/Pluf/Tests/Cache/Apc.php @@ -0,0 +1,99 @@ + 'world', + 'foo' => false, + 0 => array('foo', 'bar') + ); + + public function __construct() + { + parent::__construct('Test the APC cache API.'); + } + + public function setUp() + { + $this->_config = $GLOBALS['_PX_config']; // backup + $GLOBALS['_PX_config']['cache_engine'] = 'Pluf_Cache_Apc'; + $GLOBALS['_PX_config']['cache_timeout'] = 5; + $GLOBALS['_PX_config']['cache_apc_keyprefix'] = 'pluf_unittest_'; + } + + public function tearDown() + { + $GLOBALS['_PX_config'] = $this->_config; + } + + public function testBasic() + { + $cache = Pluf_Cache::factory(); + $success = $cache->set('test1', 'foo1'); + $this->assertTrue($success); + $this->assertEqual('foo1', $cache->get('test1')); + } + + public function testGetUnknownKey() + { + $cache = Pluf_Cache::factory(); + $this->assertNull(null, $cache->get('unknown')); + } + + public function testGetDefault() + { + $cache = Pluf_Cache::factory(); + $this->assertEqual('default', $cache->get('unknown', 'default')); + } + + public function testSerialized() + { + $cache = Pluf_Cache::factory(); + $success = $cache->set('array', $this->_arrayData); + $this->assertTrue($success); + $this->assertCopy($this->_arrayData, $cache->get('array')); + + $obj = new stdClass(); + $obj->foo = 'bar'; + $obj->hello = 'world'; + $success = $cache->set('object', $obj); + $this->assertTrue($success); + $this->assertCopy($obj, $cache->get('object')); + + unset($obj); + $this->assertIsA($cache->get('object'), 'stdClass'); + $this->assertEqual('world', $cache->get('object')->hello); + } + + public function testCompress() + { + $GLOBALS['_PX_config']['cache_apc_compress'] = true; + $cache = Pluf_Cache::factory(); + $success = $cache->set('compressed', $this->_arrayData); + $this->assertTrue($success); + $this->assertCopy($this->_arrayData, $cache->get('compressed')); + } +} diff --git a/pluf/src/Pluf/Tests/Cache/File.php b/pluf/src/Pluf/Tests/Cache/File.php new file mode 100644 index 0000000..85a252b --- /dev/null +++ b/pluf/src/Pluf/Tests/Cache/File.php @@ -0,0 +1,102 @@ + 'world', + 'foo' => false, + 0 => array('foo', 'bar') + ); + + public function __construct() + { + parent::__construct('Test the File cache API.'); + } + + public function setUp() + { + $this->_config = $GLOBALS['_PX_config']; // backup + $GLOBALS['_PX_config']['cache_engine'] = 'Pluf_Cache_File'; + $GLOBALS['_PX_config']['cache_timeout'] = 5; + $GLOBALS['_PX_config']['cache_file_folder'] = '/tmp/pluf_unittest_cache'; + } + + public function tearDown() + { + $GLOBALS['_PX_config'] = $this->_config; + } + + public function testConstructor() + { + unset($GLOBALS['_PX_config']['cache_file_folder']); + try { + $cache = Pluf_Cache::factory(); + } catch (Pluf_Exception_SettingError $e) { + $this->pass(); + return; + } + $this->fail('An exception as not been raised, "cache_file_folder" setting not defined.'); + } + + public function testBasic() + { + $cache = Pluf_Cache::factory(); + $success = $cache->set('test1', 'foo1'); + $this->assertTrue($success); + $this->assertEqual('foo1', $cache->get('test1')); + } + + public function testGetUnknownKey() + { + $cache = Pluf_Cache::factory(); + $this->assertNull(null, $cache->get('unknown')); + } + + public function testGetDefault() + { + $cache = Pluf_Cache::factory(); + $this->assertEqual('default', $cache->get('unknown', 'default')); + } + + public function testSerialized() + { + $cache = Pluf_Cache::factory(); + $success = $cache->set('array', $this->_arrayData); + $this->assertTrue($success); + $this->assertCopy($this->_arrayData, $cache->get('array')); + + $obj = new stdClass(); + $obj->foo = 'bar'; + $obj->hello = 'world'; + $success = $cache->set('object', $obj); + $this->assertTrue($success); + $this->assertCopy($obj, $cache->get('object')); + + unset($obj); + $this->assertIsA($cache->get('object'), 'stdClass'); + $this->assertEqual('world', $cache->get('object')->hello); + } +} diff --git a/pluf/src/Pluf/Tests/Dispatch/Dispatcher.php b/pluf/src/Pluf/Tests/Dispatch/Dispatcher.php new file mode 100644 index 0000000..90f3e20 --- /dev/null +++ b/pluf/src/Pluf/Tests/Dispatch/Dispatcher.php @@ -0,0 +1,173 @@ +views = (isset($GLOBALS['_PX_views'])) ? $GLOBALS['_PX_views'] : array(); + } + + function tearDown() + { + $GLOBALS['_PX_views'] = $this->views; + } + + function hello() + { + return new Pluf_HTTP_Response('ok'); + } + + function hello1() + { + return 1; + } + + function hello2() + { + return 2; + } + + function hello3() + { + return 3; + } + + function hello4() + { + return 4; + } + + function testSimple() + { + $GLOBALS['_PX_views'] = array( + array( + 'regex' => '#^/hello/$#', + 'base' => '', + 'model' => 'Pluf_Tests_Dispatch_Dispatcher', + 'method' => 'hello' + ) + ); + $req1 = (object) array('query' => '/hello/'); // match + $req2 = (object) array('query' => '/hello'); // match second pass + $req3 = (object) array('query' => '/hello/you/'); // no match + $this->assertIdentical(200, Pluf_Dispatcher::match($req1)->status_code); + $this->assertEqual('ok', Pluf_Dispatcher::match($req1)->content); + $this->assertIsA(Pluf_Dispatcher::match($req2), + 'Pluf_HTTP_Response_Redirect'); + $this->assertIsA(Pluf_Dispatcher::match($req3), + 'Pluf_HTTP_Response_NotFound'); + } + + function testRecursif() + { + $GLOBALS['_PX_views'] = array( + array( + 'regex' => '#^/hello/$#', + 'base' => '', + 'model' => 'Pluf_Tests_Dispatch_Dispatcher', + 'method' => 'hello3' + ), + array( + 'regex' => '#^/hello/#', + 'base' => '', + 'sub' => array( + array( + 'regex' => '#^world/$#', + 'base' => '', + 'model' => 'Pluf_Tests_Dispatch_Dispatcher', + 'method' => 'hello' + ), + array( + 'regex' => '#^hello/$#', + 'base' => '', + 'model' => 'Pluf_Tests_Dispatch_Dispatcher', + 'method' => 'hello4' + ), + + ), + ), + array( + 'regex' => '#^/hello1/#', + 'base' => '', + 'sub' => array( + array( + 'regex' => '#^world/$#', + 'base' => '', + 'model' => 'Pluf_Tests_Dispatch_Dispatcher', + 'method' => 'hello1' + ) + ), + ), + array( + 'regex' => '#^/hello2/#', + 'base' => '', + 'sub' => array( + array( + 'regex' => '#^world/$#', + 'base' => '', + 'model' => 'Pluf_Tests_Dispatch_Dispatcher', + 'method' => 'hello2' + ) + ), + ), + ); + $req1 = (object) array('query' => '/hello/world/'); // match + $req2 = (object) array('query' => '/hello/world'); // match second pass + $req3 = (object) array('query' => '/hello/you/'); // no match + $h1 = (object) array('query' => '/hello1/world/'); // match + $h2 = (object) array('query' => '/hello2/world/'); // match + $h3 = (object) array('query' => '/hello/'); // match + $h4 = (object) array('query' => '/hello/hello/'); // match + $this->assertIdentical(200, Pluf_Dispatcher::match($req1)->status_code); + $this->assertEqual('ok', Pluf_Dispatcher::match($req1)->content); + $this->assertIdentical(1, Pluf_Dispatcher::match($h1)); + $this->assertIdentical(2, Pluf_Dispatcher::match($h2)); + $this->assertIdentical(3, Pluf_Dispatcher::match($h3)); + $this->assertIdentical(4, Pluf_Dispatcher::match($h4)); + $this->assertIsA(Pluf_Dispatcher::match($req2), + 'Pluf_HTTP_Response_Redirect'); + $this->assertIsA(Pluf_Dispatcher::match($req3), + 'Pluf_HTTP_Response_NotFound'); + Pluf::loadFunction('Pluf_HTTP_URL_reverse'); + $this->assertEqual('/hello/world/', + Pluf_HTTP_URL_reverse('Pluf_Tests_Dispatch_Dispatcher::hello')); + $this->assertEqual('/hello1/world/', + Pluf_HTTP_URL_reverse('Pluf_Tests_Dispatch_Dispatcher::hello1')); + $this->assertEqual('/hello2/world/', + Pluf_HTTP_URL_reverse('Pluf_Tests_Dispatch_Dispatcher::hello2')); + $this->assertEqual('/hello/', + Pluf_HTTP_URL_reverse('Pluf_Tests_Dispatch_Dispatcher::hello3')); + $this->assertEqual('/hello/hello/', + Pluf_HTTP_URL_reverse('Pluf_Tests_Dispatch_Dispatcher::hello4')); + } + + +} \ No newline at end of file diff --git a/pluf/src/Pluf/Tests/Fixture/LoadDump.php b/pluf/src/Pluf/Tests/Fixture/LoadDump.php new file mode 100644 index 0000000..b0cfe92 --- /dev/null +++ b/pluf/src/Pluf/Tests/Fixture/LoadDump.php @@ -0,0 +1,71 @@ +model = $m; + $schema->dropTables(); + $schema->createTables(); + } + + function tearDown() + { + $db = Pluf::db(); + $schema = Pluf::factory('Pluf_DB_Schema', $db); + $m = new Pluf_Permission(); + $schema->model = $m; + $schema->dropTables(); + } + + + function testDump() + { + $p = new Pluf_Permission(); + $p->name = 'test permission'; + $p->code_name = 'test'; + $p->description = 'Simple test permission.'; + $p->application = 'Pluf'; + $p->create(); + $json = Pluf_Test_Fixture::dump('Pluf_Permission'); + $this->assertEqual('[{"model":"Pluf_Permission","pk":1,"fields":{"id":1,"name":"test permission","code_name":"test","description":"Simple test permission.","application":"Pluf"}}]', + $json); + } + + function testLoad() + { + $created = Pluf_Test_Fixture::load('[{"model":"Pluf_Permission","pk":1,"fields":{"id":1,"name":"test permission","code_name":"test","description":"Simple test permission.","application":"Pluf"}}]'); + $this->assertEqual(array(array('Pluf_Permission', '1')), $created); + $p = new Pluf_Permission(1); + $this->assertEqual(1, $p->id); + } +} \ No newline at end of file diff --git a/pluf/src/Pluf/Tests/Log/TestLog.php b/pluf/src/Pluf/Tests/Log/TestLog.php new file mode 100644 index 0000000..7b31574 --- /dev/null +++ b/pluf/src/Pluf/Tests/Log/TestLog.php @@ -0,0 +1,92 @@ +logfile = Pluf::f('pluf_log_file', + Pluf::f('tmp_folder', '/tmp').'/pluf.log'); + @unlink($this->logfile); + } + + function tearDown() + { + @unlink($this->logfile); + } + + function testSimple() + { + $GLOBALS['_PX_config']['log_delayed'] = true; + Pluf_Log::log('hello'); + $this->assertEqual(count(Pluf_Log::$stack), 1); + $GLOBALS['_PX_config']['log_delayed'] = false; + Pluf_Log::log('hello'); + $this->assertEqual(count(Pluf_Log::$stack), 0); + $this->assertEqual(2, count(file($this->logfile))); + } + + function testAssertLog() + { + Pluf_Log::activeAssert(); + $GLOBALS['_PX_config']['log_delayed'] = true; + assert('Pluf_Log::alog("hello")'); + $this->assertEqual(count(Pluf_Log::$stack), 1); + $GLOBALS['_PX_config']['log_delayed'] = false; + assert('Pluf_Log::alog("hello")'); + $this->assertEqual(count(Pluf_Log::$stack), 0); + $this->assertEqual(2, count(file($this->logfile))); + + } + + /** + function testPerformance() + { + $start = microtime(true); + $GLOBALS['_PX_config']['log_delayed'] = false; + for ($i=0;$i<100;$i++) { + Pluf_Log::log('hello'.$i); + } + $end = microtime(true); + print "File: ".($end-$start)."s\n"; + $start = microtime(true); + $GLOBALS['_PX_config']['log_delayed'] = true; + for ($i=0;$i<100;$i++) { + Pluf_Log::log('hello'.$i); + } + Pluf_Log::flush(); + $end = microtime(true); + print "File delayed: ".($end-$start)."s\n"; + } + **/ +} \ No newline at end of file diff --git a/pluf/src/Pluf/Tests/Log/TestRemote.php b/pluf/src/Pluf/Tests/Log/TestRemote.php new file mode 100644 index 0000000..86794d1 --- /dev/null +++ b/pluf/src/Pluf/Tests/Log/TestRemote.php @@ -0,0 +1,92 @@ +assertEqual(count(Pluf_Log::$stack), 1); + $GLOBALS['_PX_config']['log_delayed'] = false; + Pluf_Log::log('hello'); + $this->assertEqual(count(Pluf_Log::$stack), 0); + } + + function testAssertLog() + { + if (Pluf::f('test_log_testremote', false) == false) { + return; + } + Pluf_Log::activeAssert(); + $GLOBALS['_PX_config']['log_delayed'] = true; + assert('Pluf_Log::alog("hello")'); + $this->assertEqual(count(Pluf_Log::$stack), 1); + $GLOBALS['_PX_config']['log_delayed'] = false; + assert('Pluf_Log::alog("hello")'); + $this->assertEqual(count(Pluf_Log::$stack), 0); + } + + /** + function testPerformance() + { + $start = microtime(true); + $GLOBALS['_PX_config']['log_delayed'] = false; + for ($i=0;$i<100;$i++) { + Pluf_Log::log('hello'.$i); + } + $end = microtime(true); + print "Remote: ".($end-$start)."s\n"; + $start = microtime(true); + $GLOBALS['_PX_config']['log_delayed'] = true; + for ($i=0;$i<100;$i++) { + Pluf_Log::log('hello'.$i); + } + Pluf_Log::flush(); + $end = microtime(true); + print "Remote delayed: ".($end-$start)."s\n"; + } + **/ +} \ No newline at end of file diff --git a/pluf/src/Pluf/Tests/Model/CompressedField.php b/pluf/src/Pluf/Tests/Model/CompressedField.php new file mode 100644 index 0000000..fd79abc --- /dev/null +++ b/pluf/src/Pluf/Tests/Model/CompressedField.php @@ -0,0 +1,71 @@ +_a['verbose'] = 'compressed'; + $this->_a['table'] = 'compressed'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + //It is automatically added. + 'blank' => true, + ), + 'compressed' => + array( + 'type' => 'Pluf_DB_Field_Compressed', + ), + ); + } +} + + +class Pluf_Tests_Model_CompressedField extends UnitTestCase { + + function __construct() + { + parent::__construct('Test the compressed field.'); + } + + function testCreate() + { + $db = Pluf::db(); + $schema = new Pluf_DB_Schema($db); + $m = new Pluf_Tests_Model_CompressedField_Model(); + $schema->model = $m; + $schema->createTables(); + $m->compressed = 'Youplaboum'; + $m->create(); + $this->assertEqual(1, $m->id); + $m = new Pluf_Tests_Model_CompressedField_Model(1); + $this->assertEqual('Youplaboum', $m->compressed); + $schema->dropTables(); + } +} \ No newline at end of file diff --git a/pluf/src/Pluf/Tests/Model/Schema.php b/pluf/src/Pluf/Tests/Model/Schema.php new file mode 100644 index 0000000..ee949bc --- /dev/null +++ b/pluf/src/Pluf/Tests/Model/Schema.php @@ -0,0 +1,97 @@ +_a['verbose'] = 'compressed'; + $this->_a['table'] = 'compressed'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + //It is automatically added. + 'blank' => true, + ), + 'column1' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + ), + 'column2' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + ), + 'column3' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + ), + ); + $this->_a['idx'] = array( + 'test_idx' => + array( + 'col' => 'column1, column2, column3', + 'type' => 'unique', + ), + ); + + } +} + + +class Pluf_Tests_Model_Schema extends UnitTestCase { + + function __construct() + { + parent::__construct('Test the compressed field.'); + } + + function testCreate() + { + $db = Pluf::db(); + $schema = new Pluf_DB_Schema($db); + $m = new Pluf_Tests_Model_Schema_Model(); + $schema->model = $m; + $schema->createTables(); + $m->column1 = 'Youplaboum'; + $m->column2 = 'Youplaboum'; + $m->column3 = 'Youplaboum'; + $m->create(); + $this->assertEqual(1, $m->id); + $m = new Pluf_Tests_Model_Schema_Model(); + $m->column1 = 'Youplaboum'; + $m->column2 = 'Youplaboum'; + $m->column3 = 'Youplaboum'; + try { + $m->create(); + $this->assertNotEqual(2, $m->id, 'Should not be able to create.'); + } catch (Exception $e) { + // do nothing + } + $schema->dropTables(); + } +} \ No newline at end of file diff --git a/pluf/src/Pluf/Tests/Model/SlugField.php b/pluf/src/Pluf/Tests/Model/SlugField.php new file mode 100644 index 0000000..1d93cdc --- /dev/null +++ b/pluf/src/Pluf/Tests/Model/SlugField.php @@ -0,0 +1,124 @@ +_a['verbose'] = 'slug'; + $this->_a['table'] = 'slug'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + 'id' => array( + 'type' => 'Pluf_DB_Field_Sequence', + 'blank' => true, + ), + 'slug_default_length' => array( + 'type' => 'Pluf_DB_Field_Slug', + ), + 'slug_custom_legnth' => array( + 'type' => 'Pluf_DB_Field_Slug', + 'widget_attrs' => array( + 'maxlength' => 5, + ), + ), + ); + } +} + +class Pluf_Tests_Model_SlugField extends UnitTestCase +{ + + function __construct() + { + parent::__construct('Test the slug field.'); + } + + function testSlugifyLowercase() + { + $slug = Pluf_DB_Field_Slug::slugify('Pluf'); + $this->assertEqual('pluf', $slug); + } + + function testSlugifyReplaceWhiteSpaces() + { + // replaces a white space by the separator + $slug = Pluf_DB_Field_Slug::slugify('ceondo pluf'); + $this->assertEqual('ceondo-pluf', $slug); + + // replaces several white spaces by a single the separator + $slug = Pluf_DB_Field_Slug::slugify('ceondo pluf'); + $this->assertEqual('ceondo-pluf', $slug); + + // removes separator at the bound of a string + $slug = Pluf_DB_Field_Slug::slugify(' ceondo pluf'); + $this->assertEqual('ceondo-pluf', $slug); + $slug = Pluf_DB_Field_Slug::slugify('ceondo pluf '); + $this->assertEqual('ceondo-pluf', $slug); + } + + function testSlugifyNonASCII() + { + // replaces non-ASCII characters by the separator + $slug = Pluf_DB_Field_Slug::slugify('ceondo,pluf'); + $this->assertEqual('ceondo-pluf', $slug); + $slug = Pluf_DB_Field_Slug::slugify('ceondo€pluf'); + $this->assertEqual('ceondo-pluf', $slug); + + // replaces accents by their equivalent non-accented + $slug = Pluf_DB_Field_Slug::slugify('éiùàñ'); + $this->assertEqual('eiuan', $slug); + } + + function testSlugifyWithCustomSeparator() + { + $backup = $GLOBALS['_PX_config']; + $GLOBALS['_PX_config']['slug-separator'] = '_'; + + $slug = Pluf_DB_Field_Slug::slugify('ceondo pluf'); + $this->assertEqual('ceondo_pluf', $slug); + $slug = Pluf_DB_Field_Slug::slugify('ceondo pluf'); + $this->assertEqual('ceondo_pluf', $slug); + + $GLOBALS['_PX_config'] = $backup; + } + + function testCreate() + { + $db = Pluf::db(); + $schema = new Pluf_DB_Schema($db); + $m = new Pluf_Tests_Model_SlugField_Model(); + $schema->model = $m; + $schema->createTables(); + + $m->slug_default_length = 'Pluf, supported by Céondo Ltd.'; + $m->create(); + $this->assertEqual(1, $m->id); + + $m = new Pluf_Tests_Model_SlugField_Model(1); + $this->assertEqual('pluf-supported-by-ceondo-ltd', $m->slug_default_length); + $schema->dropTables(); + } +} \ No newline at end of file diff --git a/pluf/src/Pluf/Tests/Sign/Sign.php b/pluf/src/Pluf/Tests/Sign/Sign.php new file mode 100644 index 0000000..7b7e285 --- /dev/null +++ b/pluf/src/Pluf/Tests/Sign/Sign.php @@ -0,0 +1,117 @@ +assertEqual(Pluf_Sign::sign($s), + $s.'.'.Pluf_Sign::base64_hmac($s, + Pluf::f('secret_key') + ) + ); + } + + function testSignIsReversible() + { + $examples = array( + 'q;wjmbk;wkmb', + '3098247529087', + '3098247:529:087:', + 'jkw osanteuh ,rcuh nthu aou oauh ,ud du', + ); + foreach ($examples as $example) { + $this->assertTrue($example != Pluf_Sign::sign($example)); + $this->assertEqual($example, Pluf_Sign::unsign(Pluf_Sign::sign($example))); + } + } + + function testUnsignDetectsTampering() + { + $value = 'Another string'; + $signed_value = Pluf_Sign::sign($value); + $transforms = array( + strtoupper($signed_value), + $signed_value.'a', + 'a'.substr($signed_value, 1), + str_replace('w', '', $signed_value), + ); + $this->assertEqual($value, Pluf_Sign::unsign($signed_value)); + foreach ($transforms as $t) { + try { + Pluf_Sign::unsign($t); + $this->fail(); + } catch (Exception $e) { + $this->pass(); + } + } + } + + function testEncodeDecode() + { + $objects = array( + array('an', 'array'), + 'a string', + (object) array('a' => 'property'), + ); + foreach ($objects as $o) { + $this->assertTrue($o != Pluf_Sign::dumps($o)); + $this->assertEqual($o, Pluf_Sign::loads(Pluf_Sign::dumps($o))); + } + } + + function testDecodeDetectsTampering() + { + $value = array('foo'=> 'bar', 'baz'=> 1); + $encoded = Pluf_Sign::dumps($value); + $transforms = array( + strtoupper($encoded), + $encoded.'a', + 'a'.substr($encoded, 1), + str_replace('M', '', $encoded), + ); + $this->assertEqual($value, Pluf_Sign::loads($encoded)); + foreach ($transforms as $t) { + try { + Pluf_Sign::loads($t); + $this->fail(); + } catch (Exception $e) { + $this->pass(); + } + } + } +} \ No newline at end of file diff --git a/pluf/src/Pluf/Tests/TemplateCompiler/BlockTrans.php b/pluf/src/Pluf/Tests/TemplateCompiler/BlockTrans.php new file mode 100644 index 0000000..f7e88d5 --- /dev/null +++ b/pluf/src/Pluf/Tests/TemplateCompiler/BlockTrans.php @@ -0,0 +1,39 @@ +{blocktrans}This email {$email} is already registered. If you forgot your password, you can recover it easily.{/blocktrans}'; + $compiler = new Pluf_Template_Compiler('dummy', array(), false); + $compiler->templateContent = $block; + $this->assertEqual('
  • This email %%email%% is already registered. If you forgot your password, you can recover it easily. Pluf_Template_safeEcho($t->_vars->email, false)))); ?>
  • ', + $compiler->getCompiledTemplate()); + } +} \ No newline at end of file diff --git a/pluf/src/Pluf/Tests/TemplateTags/Cycle.php b/pluf/src/Pluf/Tests/TemplateTags/Cycle.php new file mode 100644 index 0000000..f2540df --- /dev/null +++ b/pluf/src/Pluf/Tests/TemplateTags/Cycle.php @@ -0,0 +1,166 @@ +skipIf(1, "%s\n " . $message); + } + } + + public function testNoArguments() + { + $tpl = $this->getNewTemplate('{cycle}'); + try { + $tpl->render(); + $this->fail(); + } catch (InvalidArgumentException $e) { + $this->pass(); + } + } + + public function testSimpleCaseInLoop() + { + $context = new Pluf_Template_Context(array('test' => range(0, 4))); + $to_parse = '{foreach $test as $i}'. + '{cycle "a", "b"}{$i},'. + '{/foreach}'; + $expected = 'a0,b1,a2,b3,a4,'; + $tpl = $this->getNewTemplate($to_parse); + $this->assertEqual($expected, $tpl->render($context)); + } + + public function testSingleStringArgument() + { + $context = new Pluf_Template_Context(array('test' => range(0, 4))); + $to_parse = '{foreach $test as $i}'. + '{cycle "a"}{$i},'. + '{/foreach}'; + $expected = 'a0,a1,a2,a3,a4,'; + $tpl = $this->getNewTemplate($to_parse); + $this->assertEqual($expected, $tpl->render($context)); + } + + public function testSingleArrayArgument() + { + $context = new Pluf_Template_Context(array('test' => range(0, 4))); + $to_parse = '{foreach $test as $i}'. + '{cycle array("a", "b", "c")}{$i},'. + '{/foreach}'; + $expected = 'a0,b1,c2,a3,b4,'; + $tpl = $this->getNewTemplate($to_parse); + $this->assertEqual($expected, $tpl->render($context)); + } + + public function testSingleContextVariableArgument() + { + $context = new Pluf_Template_Context(array('one' => 1)); + $to_parse = '{cycle $one}{cycle $one}'; + $expected = '11'; + $tpl = $this->getNewTemplate($to_parse); + $this->assertEqual($expected, $tpl->render($context)); + } + + public function testMultipleCalls() + { + $to_parse = '{cycle "a", "b"}{cycle "a", "b"}'; + $expected = 'ab'; + $tpl = $this->getNewTemplate($to_parse); + $this->assertEqual($expected, $tpl->render()); + } + + public function testAssignContextVariable() + { + $to_parse = '{cycle array("a", "b", "c"), "abc"}'. + '{cycle $abc}'; + $expected = 'ab'; + $tpl = $this->getNewTemplate($to_parse); + $this->assertEqual($expected, $tpl->render()); + + $to_parse = '{cycle array("a", "b", "c"), "abc"}'. + '{cycle $abc}'. + '{cycle $abc}'; + $expected = 'abc'; + $tpl = $this->getNewTemplate($to_parse); + $this->assertEqual($expected, $tpl->render()); + + $to_parse = '{cycle array("a", "b", "c"), "abc"}'. + '{cycle $abc}'. + '{cycle $abc}'. + '{cycle $abc}'; + $expected = 'abca'; + $tpl = $this->getNewTemplate($to_parse); + $this->assertEqual($expected, $tpl->render()); + } + + public function testContextVariablesInArrayAsArgument() + { + $context = new Pluf_Template_Context(array('test' => range(0, 4), + 'one' => 1, + 'two' => 2)); + $to_parse = '{foreach $test as $i}'. + '{cycle array($one, $two)}'. + '{/foreach}'; + $expected = '12121'; + $tpl = $this->getNewTemplate($to_parse); + $this->assertEqual($expected, $tpl->render($context)); + + $context = new Pluf_Template_Context(array('one' => 1, + 'two' => 2)); + $to_parse = '{cycle array($one, $two), "counter"}{cycle $counter}'; + $expected = '12'; + $tpl = $this->getNewTemplate($to_parse); + $this->assertEqual($expected, $tpl->render($context)); + } + + public function testContextVariablesArgument() + { + $context = new Pluf_Template_Context(array('test' => range(0, 4), + 'first' => 'a', + 'second' => 'b')); + $to_parse = '{foreach $test as $i}'. + '{cycle $first, $second}{$i},'. + '{/foreach}'; + $expected = 'a0,b1,a2,b3,a4,'; + $tpl = $this->getNewTemplate($to_parse); + $this->assertEqual($expected, $tpl->render($context)); + } + + public function testFilterInCycle() + { + $this->skip('Pluf has no support for applying filters to a variable of array'); + return; + + $context = new Pluf_Template_Context(array('one' => 'A', + 'two' => '2')); + $to_parse = '{cycle array($one|lower, $two), "counter"}{cycle $counter}'; + $expected = 'a2'; + $tpl = $this->getNewTemplate($to_parse); + $this->assertEqual($expected, $tpl->render($context)); + } +} diff --git a/pluf/src/Pluf/Tests/TemplateTags/Firstof.php b/pluf/src/Pluf/Tests/TemplateTags/Firstof.php new file mode 100644 index 0000000..6201e17 --- /dev/null +++ b/pluf/src/Pluf/Tests/TemplateTags/Firstof.php @@ -0,0 +1,98 @@ +getNewTemplate('{firstof}'); + try { + $tpl->render(); + $this->fail(); + } catch (InvalidArgumentException $e) { + $this->pass(); + } + } + + public function testOutputsNothing() + { + $context = new Pluf_Template_Context(array('a' => 0, + 'b' => 0, + 'c' => 0)); + $to_parse = '{firstof array($a, $b, $c)}'; + $expected = ''; + $tpl = $this->getNewTemplate($to_parse); + $this->assertEqual($expected, $tpl->render($context)); + } + + public function testOutputsMatched() + { + $to_parse = '{firstof array($a, $b, $c)}'; + + $context = new Pluf_Template_Context(array('a' => 1, + 'b' => 0, + 'c' => 0)); + $expected = '1'; + $tpl = $this->getNewTemplate($to_parse); + $this->assertEqual($expected, $tpl->render($context)); + + $context = new Pluf_Template_Context(array('a' => 0, + 'b' => 2, + 'c' => 0)); + $expected = '2'; + $tpl = $this->getNewTemplate($to_parse); + $this->assertEqual($expected, $tpl->render($context)); + + $context = new Pluf_Template_Context(array('a' => 0, + 'b' => 0, + 'c' => 3)); + $expected = '3'; + $tpl = $this->getNewTemplate($to_parse); + $this->assertEqual($expected, $tpl->render($context)); + } + + public function testOutputsFirstMatch() + { + $context = new Pluf_Template_Context(array('a' => 1, + 'b' => 2, + 'c' => 3)); + $to_parse = '{firstof array($a, $b, $c)}'; + $expected = '1'; + $tpl = $this->getNewTemplate($to_parse); + $this->assertEqual($expected, $tpl->render($context)); + } + + public function testOutputsFallback() + { + $context = new Pluf_Template_Context(array('a' => 0, + 'b' => 0, + 'c' => 0)); + $to_parse = '{firstof array($a, $b, $c), "my fallback"}'; + $expected = 'my fallback'; + $tpl = $this->getNewTemplate($to_parse); + $this->assertEqual($expected, $tpl->render($context)); + } +} diff --git a/pluf/src/Pluf/Tests/TemplateTags/Now.php b/pluf/src/Pluf/Tests/TemplateTags/Now.php new file mode 100644 index 0000000..d990152 --- /dev/null +++ b/pluf/src/Pluf/Tests/TemplateTags/Now.php @@ -0,0 +1,49 @@ +getNewTemplate($to_parse); + $this->assertEqual($expected, $tpl->render()); + } + + public function testParsingEscapedCharaters() + { + $to_parse = '{now "j \"n\" Y"}'; + $expected = date("j \"n\" Y"); + $tpl = $this->getNewTemplate($to_parse); + $this->assertEqual($expected, $tpl->render()); + + $to_parse = '{now "j \nn\n Y"}'; + $tpl = $this->getNewTemplate($to_parse); + $expected = date("j \nn\n Y"); + $this->assertEqual($expected, $tpl->render()); + } +} diff --git a/pluf/src/Pluf/Tests/TemplateTags/Regroup.php b/pluf/src/Pluf/Tests/TemplateTags/Regroup.php new file mode 100644 index 0000000..78e9614 --- /dev/null +++ b/pluf/src/Pluf/Tests/TemplateTags/Regroup.php @@ -0,0 +1,208 @@ +_a['verbose'] = 'people'; + $this->_a['table'] = 'people'; + $this->_a['model'] = __CLASS__; + $this->_a['cols'] = array( + 'id' => array( + 'type' => 'Pluf_DB_Field_Sequence', + 'blank' => true, + ), + 'first_name' => array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => true, + 'size' => 50, + ), + 'last_name' => array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => true, + 'size' => 50, + ), + 'gender' => array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => true, + 'size' => 50, + 'default' => 'Unknown', + ), + ); + } +} + +class Pluf_Tests_Templatetags_Regroup extends Pluf_Test_TemplatetagsUnitTestCase +{ + protected $tag_class = 'Pluf_Template_Tag_Regroup'; + protected $tag_name = 'regroup'; + + public function testRegroupAnArray() + { + $context = new Pluf_Template_Context(array( + 'data' => array(array('foo' => 'c', 'bar' => 1), + array('foo' => 'd', 'bar' => 1), + array('foo' => 'a', 'bar' => 2), + array('foo' => 'b', 'bar' => 2), + array('foo' => 'x', 'bar' => 3)))); + $to_parse = '{regroup $data, "bar", "grouped"}'. + '{foreach $grouped as $group}'. + '{$group.grouper}:'. + '{foreach $group.list as $item}'. + '{$item.foo}'. + '{/foreach},'. + '{/foreach}'; + $expected = '1:cd,2:ab,3:x,'; + $tpl = $this->getNewTemplate($to_parse); + $this->assertEqual($expected, $tpl->render($context)); + } + + public function testRegroupAnObject() + { + $obj1 = new stdClass(); + $obj1->foo = 'c'; + $obj1->bar = 1; + $obj2 = new stdClass(); + $obj2->foo = 'd'; + $obj2->bar = 1; + + $obj3 = new stdClass(); + $obj3->foo = 'a'; + $obj3->bar = 2; + $obj4 = new stdClass(); + $obj4->foo = 'b'; + $obj4->bar = 2; + + $obj5 = new stdClass(); + $obj5->foo = 'x'; + $obj5->bar = 3; + + $context = new Pluf_Template_Context(array( + 'data' => array($obj1, $obj2, $obj3, $obj4, $obj5))); + $to_parse = '{regroup $data, "bar", "grouped"}'. + '{foreach $grouped as $group}'. + '{$group.grouper}:'. + '{foreach $group.list as $item}'. + '{$item.foo}'. + '{/foreach},'. + '{/foreach}'; + $expected = '1:cd,2:ab,3:x,'; + $tpl = $this->getNewTemplate($to_parse); + $this->assertEqual($expected, $tpl->render($context)); + } + + public function testRegroupPlufModelInstance() + { + $db = Pluf::db(); + $schema = new Pluf_DB_Schema($db); + $m = new Pluf_Tests_Model_People_Model(); + $schema->model = $m; + $schema->createTables(); + + $people = array( + array('first_name' => 'George', + 'last_name' => 'Bush', + 'gender' => 'Male'), + array('first_name' => 'Bill', + 'last_name' => 'Clinton', + 'gender' => 'Male'), + array('first_name' => 'Margaret', + 'last_name' => 'Thatcher', + 'gender' => 'Female'), + array('first_name' => 'Condoleezza', + 'last_name' => 'Rice', + 'gender' => 'Female'), + array('first_name' => 'Pat', + 'last_name' => 'Smith', + 'gender' => 'Unknow'), + ); + + foreach ($people as $person) { + $p = new Pluf_Tests_Model_People_Model(); + foreach ($person as $key => $value) { + $p->$key = $value; + } + $p->create(); + } + unset($p); + + $people_list = Pluf::factory('Pluf_Tests_Model_People_Model')->getList(); + $context = new Pluf_Template_Context(array( + 'people' => $people_list)); + $to_parse = << +{foreach \$gender_list as \$gender} +
  • {\$gender.grouper}: +
      + {foreach \$gender.list as \$item} +
    • {\$item.first_name} {\$item.last_name}
    • + {/foreach} +
    +
  • +{/foreach} + +TPL; + $expected = << + +
  • Male: +
      + +
    • George Bush
    • + +
    • Bill Clinton
    • + +
    +
  • + +
  • Female: +
      + +
    • Margaret Thatcher
    • + +
    • Condoleezza Rice
    • + +
    +
  • + +
  • Unknow: +
      + +
    • Pat Smith
    • + +
    +
  • + + +HTML; + $tpl = $this->getNewTemplate($to_parse); + $this->assertEqual($expected, $tpl->render($context)); + $schema->dropTables(); + } + +} diff --git a/pluf/src/Pluf/Tests/Text/Lang.php b/pluf/src/Pluf/Tests/Text/Lang.php new file mode 100644 index 0000000..4722cc8 --- /dev/null +++ b/pluf/src/Pluf/Tests/Text/Lang.php @@ -0,0 +1,46 @@ +assertEqual(count($n), 128); + } + + function testNGramsDist() + { + $n1 = Pluf_Text_Lang::docNgrams('test the language detection with a simple string this file is part of plume framework a simple php application framework'); + $n2 = Pluf_Text_Lang::docNgrams('teste la detection de la langue avec une simple chaine ce fichier fait partie de plume framework un framework simple de developpement d applications en php'); + $n3 = Pluf_Text_Lang::docNgrams('test the this file is part of plume framework a simple php application framework language detection with a simple string'); + $this->assertEqual(0, Pluf_Text_Lang::ngramDistance($n1, $n3)); + $this->assertEqual(Pluf_Text_Lang::ngramDistance($n1, $n2), + Pluf_Text_Lang::ngramDistance($n3, $n2)); + } +} \ No newline at end of file diff --git a/pluf/src/Pluf/Text.php b/pluf/src/Pluf/Text.php new file mode 100644 index 0000000..a16db0b --- /dev/null +++ b/pluf/src/Pluf/Text.php @@ -0,0 +1,306 @@ +') { + /** HTML ends */ + $html = false; + $wrapped .= $char; + continue; + } + if ($html) { + /** If this is inside HTML -> append to the wrapped string */ + $wrapped .= $char; + continue; + } + if ($char === $wrapString) { + /** Whitespace characted / new line */ + $wrapped .= $word.$char; + $word = ''; + $line_len = 0; + continue; + } + if (in_array($char, array(' ', "\t"))) { + // Word delimiter, check if split before it needed + $word .= $char; + if (mb_strlen($word) + $line_len <= $length) { + $line_len += mb_strlen($word); + $wrapped .= $word; + $word = ''; + } else { + // If we add the word, it will be above the limit + $line_len = mb_strlen($word); + $wrapped .= $wrapString.$word; + $word = ''; + } + continue; + } + /** Check chars */ + + $word .= $char; + if (mb_strlen($word) + $line_len > $length) { + $wrapped .= $wrapString; + $line_len = 0; + continue; + } + if (mb_strlen($word) >= $length) { + $wrapped .= $word.$wrapString; + $word = ''; + $line_len = 0; + continue; + } + } + if ($word !== '') { + $wrapped .= $word; + } + return $wrapped; + } + + /** + * Given a string, cleaned from the not interesting characters, + * returns an array with the words as index and the number of + * times it was in the text as the value. + * + * @credits Tokenizer of DokuWiki to handle Thai and CJK words. + * http://www.splitbrain.org/projects/dokuwiki + * + * @param string Cleaned, lowercased and utf-8 encoded string. + * @param bool Remove the accents (True) + * @return array Word and number of occurences. + */ + public static function tokenize($string, $remove_accents=True) + { + if ($remove_accents) { + $string = self::removeAccents($string); + } + $asian1 = '[\x{0E00}-\x{0E7F}]'; // Thai + $asian2 = '['. + '\x{2E80}-\x{3040}'. // CJK -> Hangul + '\x{309D}-\x{30A0}'. + '\x{30FD}-\x{31EF}\x{3200}-\x{D7AF}'. + '\x{F900}-\x{FAFF}'. // CJK Compatibility Ideographs + '\x{FE30}-\x{FE4F}'. // CJK Compatibility Forms + ']'; + $asian3 = '['. // Hiragana/Katakana (can be two characters) + '\x{3042}\x{3044}\x{3046}\x{3048}'. + '\x{304A}-\x{3062}\x{3064}-\x{3082}'. + '\x{3084}\x{3086}\x{3088}-\x{308D}'. + '\x{308F}-\x{3094}'. + '\x{30A2}\x{30A4}\x{30A6}\x{30A8}'. + '\x{30AA}-\x{30C2}\x{30C4}-\x{30E2}'. + '\x{30E4}\x{30E6}\x{30E8}-\x{30ED}'. + '\x{30EF}-\x{30F4}\x{30F7}-\x{30FA}'. + ']['. + '\x{3041}\x{3043}\x{3045}\x{3047}\x{3049}'. + '\x{3063}\x{3083}\x{3085}\x{3087}\x{308E}\x{3095}-\x{309C}'. + '\x{30A1}\x{30A3}\x{30A5}\x{30A7}\x{30A9}'. + '\x{30C3}\x{30E3}\x{30E5}\x{30E7}\x{30EE}\x{30F5}\x{30F6}\x{30FB}\x{30FC}'. + '\x{31F0}-\x{31FF}'. + ']?'; + $asian = '(?:'.$asian1.'|'.$asian2.'|'.$asian3.')'; + $words = array(); + // handle asian chars as single words. + $asia = @preg_replace('/('.$asian.')/u',' \1 ',$string); + if (!is_null($asia)) { + //will not be called if regexp failure + $string = $asia; + } + $arr = preg_split('/\s+/', $string, -1, PREG_SPLIT_NO_EMPTY); + foreach ($arr as $w) { + $w = trim($w); + if (isset($words[$w])) { + $words[$w]++; + } else { + $words[$w] = 1; + } + } + return $words; + } + + /** + * Clean a string from the HTML and the unnecessary + * punctuation. Convert the string to lowercase. + * + * @info Require mbstring extension. + * + * @param string String. + * @return string Cleaned lowercase string. + */ + public static function cleanString($string) + { + $string = html_entity_decode($string, ENT_QUOTES, 'utf-8'); + $string = str_replace(',;:(){}[]\\|*@!?^_=/\'~`%$#', + ' '); + return mb_strtolower($string, 'UTF-8'); + } + + /** + * Remove the accentuated characters. + * + * Requires a string in lowercase, the removal is not perfect but + * is better than nothing. + * + * @param string Lowercased string in utf-8. + * @return string String with some of the accents removed. + */ + public static function removeAccents($string) + { + $map = array( + 'à'=>'a', 'ô'=>'o', 'ď'=>'d', 'ḟ'=>'f', 'ë'=>'e', + 'š'=>'s', 'ơ'=>'o', 'ß'=>'ss', 'ă'=>'a', 'ř'=>'r', + 'ț'=>'t', 'ň'=>'n', 'ā'=>'a', 'ķ'=>'k', 'ŝ'=>'s', + 'ỳ'=>'y', 'ņ'=>'n', 'ĺ'=>'l', 'ħ'=>'h', 'ṗ'=>'p', + 'ó'=>'o', 'ú'=>'u', 'ě'=>'e', 'é'=>'e', 'ç'=>'c', + 'ẁ'=>'w', 'ċ'=>'c', 'õ'=>'o', 'ṡ'=>'s', 'ø'=>'o', + 'ģ'=>'g', 'ŧ'=>'t', 'ș'=>'s', 'ė'=>'e', 'ĉ'=>'c', + 'ś'=>'s', 'î'=>'i', 'ű'=>'u', 'ć'=>'c', 'ę'=>'e', + 'ŵ'=>'w', 'ṫ'=>'t', 'ū'=>'u', 'č'=>'c', 'ö'=>'oe', + 'è'=>'e', 'ŷ'=>'y', 'ą'=>'a', 'ł'=>'l', 'ų'=>'u', + 'ů'=>'u', 'ş'=>'s', 'ğ'=>'g', 'ļ'=>'l', 'ƒ'=>'f', + 'ž'=>'z', 'ẃ'=>'w', 'ḃ'=>'b', 'å'=>'a', 'ì'=>'i', + 'ï'=>'i', 'ḋ'=>'d', 'ť'=>'t', 'ŗ'=>'r', 'ä'=>'ae', + 'í'=>'i', 'ŕ'=>'r', 'ê'=>'e', 'ü'=>'ue', 'ò'=>'o', + 'ē'=>'e', 'ñ'=>'n', 'ń'=>'n', 'ĥ'=>'h', 'ĝ'=>'g', + 'đ'=>'d', 'ĵ'=>'j', 'ÿ'=>'y', 'ũ'=>'u', 'ŭ'=>'u', + 'ư'=>'u', 'ţ'=>'t', 'ý'=>'y', 'ő'=>'o', 'â'=>'a', + 'ľ'=>'l', 'ẅ'=>'w', 'ż'=>'z', 'ī'=>'i', 'ã'=>'a', + 'ġ'=>'g', 'ṁ'=>'m', 'ō'=>'o', 'ĩ'=>'i', 'ù'=>'u', + 'į'=>'i', 'ź'=>'z', 'á'=>'a', 'û'=>'u', 'þ'=>'th', + 'ð'=>'dh', 'æ'=>'ae', 'µ'=>'u', 'ĕ'=>'e', + ); + return strtr($string, $map); + } + + /** + * Convert a string to a list of characters. + * + * @param string utf-8 encoded string. + * @return array Characters. + */ + public static function stringToChars($string) + { + $chars = array(); + $strlen = mb_strlen($string, 'UTF-8'); + for ($i=0;$i<$strlen;$i++) { + $chars[] = mb_substr($string,$i, 1, 'UTF-8'); + } + return $chars; + } + + /** + * Prevent a string to be all uppercase. + * + * If more than 50% of the words in the string are uppercases and + * if the string contains more than one word, the string is + * converted using the mb_convert_case. + * + * @see http://www.php.net/mb_convert_case + * + * @param string String to test. + * @param int Mode to convert the string (MB_CASE_TITLE) + * @return string Cleaned string. + */ + public static function preventUpperCase($string, $mode=MB_CASE_TITLE) + { + $elts = mb_split(' ', $string); + $n_elts = count($elts); + if ($n_elts > 1) { + $tot = 0; + foreach ($elts as $elt) { + if ($elt == '') { + $n_elts--; + continue; + } + if ($elt == mb_strtoupper($elt, 'UTF-8')) { + $tot++; + } + } + if ( (float) $tot / (float) $n_elts >= 0.5) { + return mb_convert_case(mb_strtolower($string, 'UTF-8'), + $mode, 'UTF-8'); + } + } + return $string; + } + + /** + * Simple uppercase prevention. + * + * Contrary to self::preventUpperCase, this method will also + * prevent a single word to be uppercase. + * + * @param string String possibly in uppercase. + * @param int Mode to convert the string (MB_CASE_TITLE) + * @return string Mode cased if all uppercase in input. + */ + public static function simplePreventUpperCase($string, $mode=MB_CASE_TITLE) + { + if ($string == mb_strtoupper($string)) { + return mb_convert_case(mb_strtolower($string), $mode, 'UTF-8'); + } + return $string; + } +} diff --git a/pluf/src/Pluf/Text/HTML/Filter.php b/pluf/src/Pluf/Text/HTML/Filter.php new file mode 100644 index 0000000..c62c426 --- /dev/null +++ b/pluf/src/Pluf/Text/HTML/Filter.php @@ -0,0 +1,417 @@ + + * + * This code is licensed under a Creative Commons + * Attribution-ShareAlike 2.5 License + * http://creativecommons.org/licenses/by-sa/2.5/ + * + * Thanks to Jang Kim for adding support for single quoted attributes. + * + * TODO: Add HTML check from: + * http://simonwillison.net/2003/Feb/23/safeHtmlChecker/ + */ +class Pluf_Text_HTML_Filter +{ + public $tag_counts = array(); + + /** + * tags and attributes that are allowed + */ + public $allowed = array( + 'a' => array('href', 'target'), + 'b' => array(), + 'img' => array('src', 'width', 'height', 'alt'), + ); + + /** + * tags which should always be self-closing (e.g. "") + */ + public $no_close = array( + 'img', + ); + + /** + * tags which must always have seperate opening and closing tags + * (e.g. "") + */ + public $always_close = array( + 'a', + 'b', + ); + + /** + * attributes which should be checked for valid protocols + */ + public $protocol_attributes = array( + 'src', + 'href', + ); + + /** + * protocols which are allowed + */ + public $allowed_protocols = array( + 'http', + 'ftp', + 'mailto', + ); + + /** + * tags which should be removed if they contain no content + * (e.g. "" or "") + */ + public $remove_blanks = array( + 'a', + 'b', + ); + + /** + * should we remove comments? + */ + public $strip_comments = 1; + + /** + * should we try and make a b tag out of "b>" + */ + public $always_make_tags = 0; + + /** + * Allows decimal entities. + * + * An entity has to decimal format . + * For example, the entity @ is the @ character. + * + * @var int + */ + public $allow_numbered_entities = 1; + + /** + * Allows hexadecimal entities. + * + * An entity has to decimal format . + * For example, the entity @ is the @ character. + * + * @var int + */ + public $allow_hexadecimal_entities = 1; + + public $allowed_entities = array( + 'amp', + 'gt', + 'lt', + 'quot', + ); + + function go($data) + { + $this->tag_counts = array(); + $data = $this->escape_comments($data); + $data = $this->balance_html($data); + $data = $this->check_tags($data); + $data = $this->process_remove_blanks($data); + $data = $this->validate_entities($data); + return $data; + } + + function escape_comments($data) + { + $data = preg_replace("//se", "''", $data); + return $data; + } + + function balance_html($data) + { + if ($this->always_make_tags) { + // try and form html + $data = preg_replace("/>>+/", ">", $data); + $data = preg_replace("/<<+/", "<", $data); + $data = preg_replace("/^>/", "", $data); + $data = preg_replace("/<([^>]*?)(?=<|$)/", "<$1>", $data); + $data = preg_replace("/(^|>)([^<]*?)(?=>)/", "$1<$2", $data); + } else { + // escape stray brackets + $data = preg_replace("/<([^>]*?)(?=<|$)/", "<$1", $data); + $data = preg_replace("/(^|>)([^<]*?)(?=>)/", "$1$2><", $data); + // the last regexp causes '<>' entities to appear + // (we need to do a lookahead assertion so that the last bracket can + // be used in the next pass of the regexp) + $data = str_replace('<>', '', $data); + } + //echo "::".HtmlSpecialChars($data)."
    \n"; + return $data; + } + + function check_tags($data) + { + $data = preg_replace("/<(.*?)>/se", "\$this->process_tag(\$this->StripSingle('\\1'))", $data); + foreach (array_keys($this->tag_counts) as $tag) { + for ($i=0; $i<$this->tag_counts[$tag]; $i++) { + $data .= ""; + } + } + return $data; + } + + + + function process_tag($data) + { + // ending tags + if (preg_match("/^\/([a-z0-9]+)/si", $data, $matches)) { + $name = StrToLower($matches[1]); + if (in_array($name, array_keys($this->allowed))) { + if (!in_array($name, $this->no_close)) { + if (isset($this->tag_counts[$name]) and $this->tag_counts[$name]) { + $this->tag_counts[$name]--; + return ''; + } + } + } else { + return ''; + } + } + // starting tags + if (preg_match("/^([a-z0-9]+)(.*?)(\/?)$/si", $data, $matches)) { + $name = StrToLower($matches[1]); + $body = $matches[2]; + $ending = $matches[3]; + if (in_array($name, array_keys($this->allowed))) { + $params = ""; + preg_match_all("/([a-z0-9]+)=([\"'])(.*?)\\2/si", $body, $matches_2, PREG_SET_ORDER); // + preg_match_all("/([a-z0-9]+)(=)([^\"\s']+)/si", $body, $matches_1, PREG_SET_ORDER); // + preg_match_all("/([a-z0-9]+)=([\"'])([^\"']*?)\s*$/si", $body, $matches_3, PREG_SET_ORDER); // no_close)) { + $ending = ' /'; + } + if (in_array($name, $this->always_close)) { + $ending = ''; + } + if (!$ending) { + if (isset($this->tag_counts[$name])) { + $this->tag_counts[$name]++; + } else { + $this->tag_counts[$name] = 1; + } + } + if ($ending) { + $ending = ' /'; + } + return '<'.$name.$params.$ending.'>'; + } else { + return ''; + } + } + // comments + if (preg_match("/^!--(.*)--$/si", $data)) { + if ($this->strip_comments) { + return ''; + } else { + return '<'.$data.'>'; + } + } + // garbage, ignore it + return ''; + } + + function process_param_protocol($data) + { + $data = $this->decode_entities($data); + if (preg_match("/^([^:]+)\:/si", $data, $matches)) { + if (!in_array($matches[1], $this->allowed_protocols)) { + $data = '#'.substr($data, strlen($matches[1])+1); + } + } + return $data; + } + + function process_remove_blanks($data) + { + foreach($this->remove_blanks as $tag) { + $data = preg_replace("/<{$tag}(\s[^>]*)?><\\/{$tag}>/", '', $data); + $data = preg_replace("/<{$tag}(\s[^>]*)?\\/>/", '', $data); + } + return $data; + } + + function fix_case($data) + { + $data_notags = Strip_Tags($data); + $data_notags = preg_replace('/[^a-zA-Z]/', '', $data_notags); + if (strlen($data_notags)<5) { + return $data; + } + if (preg_match('/[a-z]/', $data_notags)) { + return $data; + } + return preg_replace( + "/(>|^)([^<]+?)(<|$)/se", + "\$this->StripSingle('\\1').". + "\$this->fix_case_inner(\$this->StripSingle('\\2')).". + "\$this->StripSingle('\\3')", + $data + ); + } + + function fix_case_inner($data) + { + $data = StrToLower($data); + $data = preg_replace( + '/(^|[^\w\s\';,\\-])(\s*)([a-z])/e', + "\$this->StripSingle('\\1\\2').StrToUpper(\$this->StripSingle('\\3'))", + $data + ); + return $data; + } + + function validate_entities($data) + { + // validate entities throughout the string + $data = preg_replace( + '!&([^&;]*)(?=(;|&|$))!e', + "\$this->check_entity(\$this->StripSingle('\\1'), \$this->StripSingle('\\2'))", + $data + ); + // validate quotes outside of tags + $data = preg_replace( + "/(>|^)([^<]+?)(<|$)/se", + "\$this->StripSingle('\\1').". + "str_replace('\"', '"', \$this->StripSingle('\\2')).". + "\$this->StripSingle('\\3')", + $data + ); + return $data; + } + + function check_entity($preamble, $term) + { + if (';' === $term) { + if ($this->is_valid_entity($preamble)) { + return '&'.$preamble; + } + } + return '&'.$preamble; + } + + /** + * Determines if the string provided is a valid entity. + * + * @param string $entity String to test against. + * @return boolean + */ + function is_valid_entity($entity) + { + if (preg_match('#^\#([0-9]{2,}|x[0-9a-f]{2,})$#i', $entity, $m)) { + if (0 === strpos($m[1], 'x')) { + // hexadecimal entity + if ($this->allow_hexadecimal_entities && $this->not_control_caracter($m[1])) { + return true; + } + return false; + } else { + // decimal entity + if ($this->allow_numbered_entities && $this->not_control_caracter($m[1])) { + return true; + } + return false; + } + } + // HTML 4.0 character entity + return in_array($entity, $this->allowed_entities); + } + + /** + * Determines if the data provided is not a control character. + * + * @param string|int $data Data to test against like "64" or "x40". + * @return boolean + */ + function not_control_caracter($data) + { + if (0 === strpos($data, 'x')) { + $data = substr($data, 1); + $data = hexdec($data); + } else { + $data = intval($data); + } + return (31 < $data && (127 > $data || 159 < $data)); + } + + // within attributes, we want to convert all hex/dec/url escape + // sequences into their raw characters so that we can check we + // don't get stray quotes/brackets inside strings + function decode_entities($data) + { + $data = preg_replace_callback('!(&)#(\d+);?!', array($this, 'decode_dec_entity'), $data); + $data = preg_replace_callback('!(&)#x([0-9a-f]+);?!i', array($this, 'decode_hex_entity'), $data); + $data = preg_replace_callback('!(%)([0-9a-f]{2});?!i', array($this, 'decode_hex_entity'), $data); + $data = $this->validate_entities($data); + return $data; + } + + function decode_hex_entity($m) + { + return $this->decode_num_entity($m[1], hexdec($m[2])); + } + + function decode_dec_entity($m) + { + return $this->decode_num_entity($m[1], intval($m[2])); + } + + function decode_num_entity($orig_type, $d) + { + if ($d < 0) { $d = 32; } // space + // don't mess with huigh chars + if ($this->not_control_caracter($d)) { + if ($orig_type == '%') { return '%'.dechex($d); } + if ($orig_type == '&') { return "&#$d;"; } + } + return HtmlSpecialChars(chr($d)); + } + + function StripSingle($data) + { + return str_replace(array('\\"', "\\0"), array('"', chr(0)), $data); + } +} diff --git a/pluf/src/Pluf/Text/LaTeX/Equation.php b/pluf/src/Pluf/Text/LaTeX/Equation.php new file mode 100644 index 0000000..db99b0d --- /dev/null +++ b/pluf/src/Pluf/Text/LaTeX/Equation.php @@ -0,0 +1,328 @@ + + * http://www.mayer.dial.pipex.com/tex.htm + * Kjell Magne Fauske + * http://www.fauskes.net/nb/htmleqII/ + * + * Example usage: + * + * $latex = new Pluf_Text_Latex_Equation(); + * if (true === $latex->render('e = mc^2')) { + * $png_file = $latex->output_file; + * $png_full_path = $latex->output_path; + * } else { + * $error = $latex->error_code; + * $msg = $latex->error_msg; + * } + * + * Note that the class is not using exception to return the errors, + * that way you can easily grab the error and depending on the error + * code/message generate a special .png file to display. + */ + +class Pluf_Text_Latex_Equation +{ + public $tmp_dir = '/tmp'; + public $output_dir = '/tmp'; + public $encoding = 'utf-8'; + public $fragment = ''; + public $latex_path = '/usr/bin/latex'; + public $dvipng_path = '/usr/bin/dvipng'; + public $resolution = '120'; + public $bg_color = 'ffffff'; + public $debug = false; + + /** + * Black listing of tags. + * + * this most certainly needs to be extended. in the long term it + * is planned to use a positive list for more security. this is + * hopefully enough for now. i'd be glad to receive more bad tags + * ! + */ + public $tags_blacklist = array( + 'include', 'def', 'command', 'loop', 'repeat', 'open', 'toks', 'output', + 'input', 'catcode', 'name', '^^', '\\every', '\\errhelp', + '\\errorstopmode', '\\scrollmode', '\\nonstopmode', '\\batchmode', + '\\read', '\\write', 'csname', '\\newhelp', '\\uppercase', '\\lowercase', + '\\relax', '\\aftergroup', '\\afterassignment', '\\expandafter', + '\\noexpand', '\\special'); + public $error_code = 0; + public $error_msg = ''; + + /* + var $_latex_path = "/usr/local/bin/latex"; + var $_dvips_path = "/usr/local/bin/dvips"; + var $_convert_path = "/usr/local/bin/convert"; + var $_identify_path="/usr/local/bin/identify"; + var $_formula_density = 100; // originally 110 + var $_xsize_limit = 700; + var $_ysize_limit = 1000; + var $_string_length_limit = 1000; + var $_font_size = 10; + var $_latexclass = "article"; //install extarticle class if you wish to have smaller font sizes + var $_tmp_filename; + var $_image_format = "png"; //change to png if you prefer + ); + var $_errorcode = 0; + var $_errorextra = ''; + */ + + + /** + * Initializes the class + * + * @param string Output directory (null) + * @param string Temp directory (null) + */ + public function __construct($output_dir=null, $tmp_dir=null) + { + if (!is_null($output_dir)) { + $this->output_dir = $output_dir; + } + if (!is_null($tmp_dir)) { + $this->tmp_dir = $tmp_dir; + } + } + + + /** + * Tries to match the LaTeX Formula given as argument against the + * formula cache. If the picture has not been rendered before, it'll + * try to render the formula and drop it in the picture cache directory. + * + * @param string formula in LaTeX format + * @returns the webserver based URL to a picture which contains the + * requested LaTeX formula. If anything fails, the resultvalue is false. + */ + function getFormulaURL($latex_formula) { + // circumvent certain security functions of web-software which + // is pretty pointless right here + $latex_formula = preg_replace("/>/i", ">", $latex_formula); + $latex_formula = preg_replace("/</i", "<", $latex_formula); + + $formula_hash = md5($latex_formula.$this->_font_size); + + $filename = $formula_hash.".".$this->_image_format; + $full_path_filename = $this->getPicturePath()."/".$filename; + + if (is_file($full_path_filename)) + { + return $this->getPicturePathHTTPD()."/".$filename; + } + else { + // security filter: reject too long formulas + if (strlen($latex_formula) > $this->_string_length_limit) { + $this->_errorcode = 1; + return false; + } + + // security filter: try to match against LaTeX-Tags Blacklist + for ($i=0;$i_latex_tags_blacklist);$i++) { + if (stristr($latex_formula,$this->_latex_tags_blacklist[$i])) { + $this->_errorcode = 2; + return false; + } + } + + // security checks assume correct formula, let's render it + if ($this->renderLatex($latex_formula)) { + return $this->getPicturePathHTTPD()."/".$filename; + } else { + // uncomment if required + //$this->_errorcode = 3; + return false; + } + } + } + + /** + * Get the Latex preamble. + * + * You can overwrite this function if you want. + * + * @return string Latex preamble. + */ + function getPreamble() + { + return '\documentclass{article}'."\n" + .'\usepackage{amsmath}'."\n" + .'\usepackage{amsthm}'."\n" + .'\usepackage{amssymb}'."\n" + .'\usepackage{bm}'."\n" + .'% \newcommand{\mx}[1]{\mathbf{\bm{#1}}} % Matrix command'."\n" + .'% \newcommand{\vc}[1]{\mathbf{\bm{#1}}} % Vector command'."\n" + .'% \newcommand{\T}{\text{T}} % Transpose'."\n" + .'\pagestyle{empty}'."\n" + .'\begin{document}'."\n"; + } + + /** + * Renders a LaTeX formula by the using the following method: + * - write the formula into a wrapped tex-file in a temporary directory + * and change to it + * - Create a DVI file using latex (tetex) + * - Convert DVI file to png or gif using dvipng + * - Save the resulting image to the picture cache directory using an + * md5 hash as filename. Already rendered formulas can be found directly + * this way. + * + * @param string LaTeX formula + * @param bool Render an inline formulat (false) + * @return true if the picture has been successfully saved to the picture + * cache directory + */ + function render($latex_formula, $inline=false) + { + $this->output_file = ''; + $this->output_path = ''; + $this->error_code = 0; + $this->error_msg = ''; + $output_file = $this->getOutputFile($latex_formula, $inline); + if (file_exists($this->output_dir.'/'.$output_file)) { + $this->output_file = $output_file; + $this->output_path = $this->output_dir.'/'.$output_file; + return true; + } + if (!$this->isCleanLatex($latex_formula)) { + // error code and message set by the method + return false; + } + if ($inline) { + $body = sprintf("$%s$ \n \\newpage \n", $latex_formula); + } else { + $body = sprintf("\\[\n%s \n\\] \n \\newpage \n", $latex_formula); + } + $latex_document = $this->getPreamble().$body; + $latex_document .= '\end{document}'; + + $current_dir = getcwd(); + chdir($this->tmp_dir); + + // create temporary latex file + $tmp_filename = md5($latex_formula.rand()); + $fp = fopen($this->tmp_dir.'/'.$tmp_filename.'.tex', 'a+'); + fputs($fp, $latex_document); + fclose($fp); + + // create temporary dvi file + $command = $this->latex_path.' --interaction=nonstopmode '.$tmp_filename.'.tex'; + exec($command); + if (!is_file($tmp_filename.'.dvi')) { + $this->clean($tmp_filename); + chdir($current_dir); + $this->error_code = 4; + $this->error_msg = __('Unable to generate the dvi file.'); + return false; + } + // convert dvi file to png using dvipng + $bg = 'rgb '; + $_r = sprintf('%01.2f', hexdec(substr($this->bg_color, 0, 2))/255); + $_g = sprintf('%01.2f', hexdec(substr($this->bg_color, 2, 2))/255); + $_b = sprintf('%01.2f', hexdec(substr($this->bg_color, 4, 2))/255); + + $command = $this->dvipng_path.' -q -T tight -D '.$this->resolution.' -z 9 -pp -1 -bg "rgb '.$_r.' '.$_g.' '.$_b.'" -bg transparent ' + .'-o %s.png %s.dvi'; + $command = sprintf($command, $tmp_filename, $tmp_filename); + exec($command); + if (!is_file($tmp_filename.'.png')) { + $this->clean($tmp_filename); + chdir($current_dir); + $this->error_code = 5; + $this->error_msg = __('Unable to generate the png file.'); + return false; + } + $output_file = $this->getOutputFile($latex_formula, $inline); + $output_path = $this->output_dir.'/'.$output_file; + if (false == rename($tmp_filename.'.png', $output_path) + or !is_file($output_path)) { + $this->clean($tmp_filename); + chdir($current_dir); + $this->error_code = 6; + $this->error_msg = __('Unable to move the png file.'); + return false; + } + $this->clean($tmp_filename); + $this->output_file = $output_file; + $this->output_path = $output_path; + chdir($current_dir); + return true; + } + + /** + * Cleans the temporary directory + */ + public function clean($tmp_filename) + { + if ($this->debug) return; + $current_dir = getcwd(); + chdir($this->tmp_dir); + $exts = array('tex', 'aux', 'log', 'dvi', 'png'); + foreach ($exts as $ext) { + if (file_exists($tmp_filename.'.'.$ext)) { + @unlink($tmp_filename.'.'.$ext); + } + } + chdir($current_dir); + } + + /** + * Check if the latex code is clean. + * + * @param string Latex code. + * @return bool Is Clean. + */ + public function isCleanLatex($latex) + { + foreach ($this->tags_blacklist as $tag) { + if (false !== stristr($latex, $tag)) { + $this->error_code = 2; + $this->error_msg = sprintf(__('The LaTeX tag "%s" is not acceptable.'), $tag); + return false; + } + } + return true; + } + + /** + * Get the output file based on the latex fragment. + * + * @param string Latex. + * @param bool Is the equation an inline equation (false). + * @param string Output file with extension without directory. + */ + public function getOutputFile($latex, $inline=false) + { + $inline = ($inline) ? 'inline' : 'normal'; + return md5($this->bg_color.'###'.$inline.'###'.$this->resolution.'###'.$latex).'.png'; + } + +} diff --git a/pluf/src/Pluf/Text/LaTeX/Texvc.php b/pluf/src/Pluf/Text/LaTeX/Texvc.php new file mode 100644 index 0000000..dd10e79 --- /dev/null +++ b/pluf/src/Pluf/Text/LaTeX/Texvc.php @@ -0,0 +1,90 @@ +$val) { + $this->$key = $val; + } + $this->fragment = $latex; + } + + /** + * @param string Return type 'md5', ('file') + * @return file Path to the generated png file. + */ + public function render($return='file') + { + $cmd = sprintf('%s %s %s %s %s', + $this->texvc_path, // texvc binary + escapeshellarg($this->tmp_dir), + escapeshellarg($this->output_dir), + escapeshellarg($this->fragment), + escapeshellarg($this->encoding)); + $out = exec($cmd); + if (strlen($out) == 0) { + throw new Exception('Unknown error in the LaTeX rendering.'); + } + $code = substr($out, 0, 1); + if (false !== strpos('SEF-', $code)) { + $error = ''; + switch ($code) { + case 'S': + $error = 'syntax error'; break; + case 'E': + $error = 'lexing error'; break; + case '-': + $error = 'other error'; break; + case 'F': + $error = 'unknown function: '.substr($out, 1); break; + } + throw new Exception('Error in the LaTeX rendering: '.$error); + } + $md5 = md5($this->fragment); + if (!file_exists($this->output_dir.'/'.$md5.'.png')) { + throw new Exception(sprintf('Error: Output file not written (%s).', $md5.'.png')); + } + if ($return == 'file') { + return $this->output_dir.'/'.$md5.'.png'; + } + return $md5; + } +} diff --git a/pluf/src/Pluf/Text/Lang.php b/pluf/src/Pluf/Text/Lang.php new file mode 100644 index 0000000..5d2ecd5 --- /dev/null +++ b/pluf/src/Pluf/Text/Lang.php @@ -0,0 +1,162 @@ + + * list($lang, $confid) = Pluf_Text_Lang::detect($string); + * + */ +class Pluf_Text_Lang +{ + /** + * Given a string, returns the language. + * + * Algorithm by Cavnar et al. 94. + * + * @param string + * @param bool Is the string clean (false) + * @return array Language, Confidence + */ + public static function detect($string, $is_clean=false) + { + if (!$is_clean) { + $string = Pluf_Text::cleanString($string); + } + + } + + /** + * Returns the sorted n-grams of a document. + * + * FIXME: We should detect the proportion of thai/chinese/japanese + * characters and switch to unigram instead of n-grams if the + * proportion is greater than 50%. + * + * @param string The clean document. + * @param int Maximum size of the n grams (3) + * @return array N-Grams + */ + public static function docNgrams($string, $n=3) + { + // do not remove the accents + $words = Pluf_Text::tokenize($string, false); + $ngrams = array(); + for ($i=2;$i<=$n;$i++) { + foreach ($words as $word=>$occ) { + foreach (self::makeNgrams($word, $i) as $ngram) { + $ngrams[] = array($ngram, $occ); + } + } + } + $out = array(); + foreach ($ngrams as $ngram) { + if (!isset($out[$ngram[0]])) { + $out[$ngram[0]] = $ngram[1]; + } else { + $out[$ngram[0]] += $ngram[1]; + } + } + // split the ngrams by occurence. + $ngrams = array(); + foreach ($out as $ngram=>$occ) { + if (isset($ngrams[$occ])) { + $ngrams[$occ][] = $ngram; + } else { + $ngrams[$occ] = array($ngram); + } + } + krsort($ngrams); + $res = array(); + foreach ($ngrams as $occ=>$list) { + sort($list); + foreach ($list as $ngram) { + $res[] = $ngram; + } + } + return $res; + } + + /** + * Returns the n-grams of rank n of the word. + * + * @param string Word. + * @return array N-grams + */ + public static function makeNgrams($word, $n=3) + { + $chars = array('_'); + $chars = $chars + Pluf_Text::stringToChars($word); + $chars[] = '_'; + $l = count($chars); + $ngrams = array(); + for ($i=0;$i<$l+1-$n;$i++) { + $ngrams[$i] = array(); + } + $n_ngrams = $l+1-$n; + for ($i=0;$i<$l;$i++) { + for ($j=0;$j<$n;$j++) { + if (isset($ngrams[$i-$j])) { + $ngrams[$i-$j][] = $chars[$i]; + } + } + } + $out = array(); + foreach ($ngrams as $ngram) { + $t = implode('', $ngram); + if ($t != '__') { + $out[] = $t; + } + } + return $out; + } + + /** + * Return the distance between two document ngrams. + * + * @param array n-gram + * @param array n-gram + * @return integer distance + */ + public static function ngramDistance($n1, $n2) + { + $res = 0; + $n_n1 = count($n1); + $n_n2 = count($n2); + if ($n_n1 > $n_n2) { + list($n_n1, $n_n2) = array($n_n2, $n_n1); + list($n1, $n2) = array($n2, $n1); + } + for ($i=0;$i<$n_n1;$i++) { + if (false !== ($index = array_search($n1[$i], $n2))) { + $offset = abs($index - $i); + $res += ($offset > 3) ? 3 : $offset; + } else { + $res += 3; + } + } + $res += ($n_n2 - $n_n1) * 3; + return $res; + } +} \ No newline at end of file diff --git a/pluf/src/Pluf/Text/MarkDown.License.txt b/pluf/src/Pluf/Text/MarkDown.License.txt new file mode 100644 index 0000000..3f0c1b1 --- /dev/null +++ b/pluf/src/Pluf/Text/MarkDown.License.txt @@ -0,0 +1,36 @@ +PHP Markdown & Extra +Copyright (c) 2004-2007 Michel Fortin + +All rights reserved. + +Based on Markdown +Copyright (c) 2003-2006 John Gruber + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +* Neither the name "Markdown" nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +This software is provided by the copyright holders and contributors "as +is" and any express or implied warranties, including, but not limited +to, the implied warranties of merchantability and fitness for a +particular purpose are disclaimed. In no event shall the copyright owner +or contributors be liable for any direct, indirect, incidental, special, +exemplary, or consequential damages (including, but not limited to, +procurement of substitute goods or services; loss of use, data, or +profits; or business interruption) however caused and on any theory of +liability, whether in contract, strict liability, or tort (including +negligence or otherwise) arising in any way out of the use of this +software, even if advised of the possibility of such damage. diff --git a/pluf/src/Pluf/Text/MarkDown.php b/pluf/src/Pluf/Text/MarkDown.php new file mode 100644 index 0000000..93724dd --- /dev/null +++ b/pluf/src/Pluf/Text/MarkDown.php @@ -0,0 +1,3338 @@ + +# +# Original Markdown +# Copyright (c) 2004-2006 John Gruber +# +# + + +define( 'MARKDOWN_VERSION', "1.0.1q" ); # 11 Apr 2013 +define( 'MARKDOWNEXTRA_VERSION', "1.2.7" ); # 11 Apr 2013 + + +# +# Global default settings: +# + +# Change to ">" for HTML output +@define( 'MARKDOWN_EMPTY_ELEMENT_SUFFIX', " />"); + +# Define the width of a tab for code blocks. +@define( 'MARKDOWN_TAB_WIDTH', 4 ); + +# Optional title attribute for footnote links and backlinks. +@define( 'MARKDOWN_FN_LINK_TITLE', "" ); +@define( 'MARKDOWN_FN_BACKLINK_TITLE', "" ); + +# Optional class attribute for footnote links and backlinks. +@define( 'MARKDOWN_FN_LINK_CLASS', "" ); +@define( 'MARKDOWN_FN_BACKLINK_CLASS', "" ); + +# Optional class prefix for fenced code block. +@define( 'MARKDOWN_CODE_CLASS_PREFIX', "" ); + +# Class attribute for code blocks goes on the `code` tag; +# setting this to true will put attributes on the `pre` tag instead. +@define( 'MARKDOWN_CODE_ATTR_ON_PRE', false ); + + +# +# WordPress settings: +# + +# Change to false to remove Markdown from posts and/or comments. +@define( 'MARKDOWN_WP_POSTS', true ); +@define( 'MARKDOWN_WP_COMMENTS', true ); + + + +### Standard Function Interface ### + +@define( 'MARKDOWN_PARSER_CLASS', 'MarkdownExtra_Parser' ); + +function Markdown($text) { +# +# Initialize the parser and return the result of its transform method. +# + # Setup static parser variable. + static $parser; + if (!isset($parser)) { + $parser_class = MARKDOWN_PARSER_CLASS; + $parser = new $parser_class; + } + + # Transform text using parser. + return $parser->transform($text); +} + +function Pluf_Text_MarkDown_parse($text) { + return Markdown($text); +} + + +### WordPress Plugin Interface ### + +/* +Plugin Name: Markdown Extra +Plugin Name: Markdown +Plugin URI: http://michelf.ca/projects/php-markdown/ +Description: Markdown syntax allows you to write using an easy-to-read, easy-to-write plain text format. Based on the original Perl version by John Gruber. More... +Version: 1.2.7 +Author: Michel Fortin +Author URI: http://michelf.ca/ +*/ + +if (isset($wp_version)) { + # More details about how it works here: + # + + # Post content and excerpts + # - Remove WordPress paragraph generator. + # - Run Markdown on excerpt, then remove all tags. + # - Add paragraph tag around the excerpt, but remove it for the excerpt rss. + if (MARKDOWN_WP_POSTS) { + remove_filter('the_content', 'wpautop'); + remove_filter('the_content_rss', 'wpautop'); + remove_filter('the_excerpt', 'wpautop'); + add_filter('the_content', 'mdwp_MarkdownPost', 6); + add_filter('the_content_rss', 'mdwp_MarkdownPost', 6); + add_filter('get_the_excerpt', 'mdwp_MarkdownPost', 6); + add_filter('get_the_excerpt', 'trim', 7); + add_filter('the_excerpt', 'mdwp_add_p'); + add_filter('the_excerpt_rss', 'mdwp_strip_p'); + + remove_filter('content_save_pre', 'balanceTags', 50); + remove_filter('excerpt_save_pre', 'balanceTags', 50); + add_filter('the_content', 'balanceTags', 50); + add_filter('get_the_excerpt', 'balanceTags', 9); + } + + # Add a footnote id prefix to posts when inside a loop. + function mdwp_MarkdownPost($text) { + static $parser; + if (!$parser) { + $parser_class = MARKDOWN_PARSER_CLASS; + $parser = new $parser_class; + } + if (is_single() || is_page() || is_feed()) { + $parser->fn_id_prefix = ""; + } else { + $parser->fn_id_prefix = get_the_ID() . "."; + } + return $parser->transform($text); + } + + # Comments + # - Remove WordPress paragraph generator. + # - Remove WordPress auto-link generator. + # - Scramble important tags before passing them to the kses filter. + # - Run Markdown on excerpt then remove paragraph tags. + if (MARKDOWN_WP_COMMENTS) { + remove_filter('comment_text', 'wpautop', 30); + remove_filter('comment_text', 'make_clickable'); + add_filter('pre_comment_content', 'Markdown', 6); + add_filter('pre_comment_content', 'mdwp_hide_tags', 8); + add_filter('pre_comment_content', 'mdwp_show_tags', 12); + add_filter('get_comment_text', 'Markdown', 6); + add_filter('get_comment_excerpt', 'Markdown', 6); + add_filter('get_comment_excerpt', 'mdwp_strip_p', 7); + + global $mdwp_hidden_tags, $mdwp_placeholders; + $mdwp_hidden_tags = explode(' ', + '

     
  • '); + $mdwp_placeholders = explode(' ', str_rot13( + 'pEj07ZbbBZ U1kqgh4w4p pre2zmeN6K QTi31t9pre ol0MP1jzJR '. + 'ML5IjmbRol ulANi1NsGY J7zRLJqPul liA8ctl16T K9nhooUHli')); + } + + function mdwp_add_p($text) { + if (!preg_match('{^$|^<(p|ul|ol|dl|pre|blockquote)>}i', $text)) { + $text = '

    '.$text.'

    '; + $text = preg_replace('{\n{2,}}', "

    \n\n

    ", $text); + } + return $text; + } + + function mdwp_strip_p($t) { return preg_replace('{}i', '', $t); } + + function mdwp_hide_tags($text) { + global $mdwp_hidden_tags, $mdwp_placeholders; + return str_replace($mdwp_hidden_tags, $mdwp_placeholders, $text); + } + function mdwp_show_tags($text) { + global $mdwp_hidden_tags, $mdwp_placeholders; + return str_replace($mdwp_placeholders, $mdwp_hidden_tags, $text); + } +} + + +### bBlog Plugin Info ### + +function identify_modifier_markdown() { + return array( + 'name' => 'markdown', + 'type' => 'modifier', + 'nicename' => 'PHP Markdown Extra', + 'description' => 'A text-to-HTML conversion tool for web writers', + 'authors' => 'Michel Fortin and John Gruber', + 'licence' => 'GPL', + 'version' => MARKDOWNEXTRA_VERSION, + 'help' => 'Markdown syntax allows you to write using an easy-to-read, easy-to-write plain text format. Based on the original Perl version by John Gruber. More...', + ); +} + + +### Smarty Modifier Interface ### + +function smarty_modifier_markdown($text) { + return Markdown($text); +} + + +### Textile Compatibility Mode ### + +# Rename this file to "classTextile.php" and it can replace Textile everywhere. + +if (strcasecmp(substr(__FILE__, -16), "classTextile.php") == 0) { + # Try to include PHP SmartyPants. Should be in the same directory. + @include_once 'smartypants.php'; + # Fake Textile class. It calls Markdown instead. + class Textile { + function TextileThis($text, $lite='', $encode='') { + if ($lite == '' && $encode == '') $text = Markdown($text); + if (function_exists('SmartyPants')) $text = SmartyPants($text); + return $text; + } + # Fake restricted version: restrictions are not supported for now. + function TextileRestricted($text, $lite='', $noimage='') { + return $this->TextileThis($text, $lite); + } + # Workaround to ensure compatibility with TextPattern 4.0.3. + function blockLite($text) { return $text; } + } +} + + + +# +# Markdown Parser Class +# + +class Markdown_Parser { + + ### Configuration Variables ### + + # Change to ">" for HTML output. + var $empty_element_suffix = MARKDOWN_EMPTY_ELEMENT_SUFFIX; + var $tab_width = MARKDOWN_TAB_WIDTH; + + # Change to `true` to disallow markup or entities. + var $no_markup = false; + var $no_entities = false; + + # Predefined urls and titles for reference links and images. + var $predef_urls = array(); + var $predef_titles = array(); + + + ### Parser Implementation ### + + # Regex to match balanced [brackets]. + # Needed to insert a maximum bracked depth while converting to PHP. + var $nested_brackets_depth = 6; + var $nested_brackets_re; + + var $nested_url_parenthesis_depth = 4; + var $nested_url_parenthesis_re; + + # Table of hash values for escaped characters: + var $escape_chars = '\`*_{}[]()>#+-.!'; + var $escape_chars_re; + + + function Markdown_Parser() { + # + # Constructor function. Initialize appropriate member variables. + # + $this->_initDetab(); + $this->prepareItalicsAndBold(); + + $this->nested_brackets_re = + str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth). + str_repeat('\])*', $this->nested_brackets_depth); + + $this->nested_url_parenthesis_re = + str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth). + str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth); + + $this->escape_chars_re = '['.preg_quote($this->escape_chars).']'; + + # Sort document, block, and span gamut in ascendent priority order. + asort($this->document_gamut); + asort($this->block_gamut); + asort($this->span_gamut); + } + + + # Internal hashes used during transformation. + var $urls = array(); + var $titles = array(); + var $html_hashes = array(); + + # Status flag to avoid invalid nesting. + var $in_anchor = false; + + + function setup() { + # + # Called before the transformation process starts to setup parser + # states. + # + # Clear global hashes. + $this->urls = $this->predef_urls; + $this->titles = $this->predef_titles; + $this->html_hashes = array(); + + $this->in_anchor = false; + } + + function teardown() { + # + # Called after the transformation process to clear any variable + # which may be taking up memory unnecessarly. + # + $this->urls = array(); + $this->titles = array(); + $this->html_hashes = array(); + } + + + function transform($text) { + # + # Main function. Performs some preprocessing on the input text + # and pass it through the document gamut. + # + $this->setup(); + + # Remove UTF-8 BOM and marker character in input, if present. + $text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text); + + # Standardize line endings: + # DOS to Unix and Mac to Unix + $text = preg_replace('{\r\n?}', "\n", $text); + + # Make sure $text ends with a couple of newlines: + $text .= "\n\n"; + + # Convert all tabs to spaces. + $text = $this->detab($text); + + # Turn block-level HTML blocks into hash entries + $text = $this->hashHTMLBlocks($text); + + # Strip any lines consisting only of spaces and tabs. + # This makes subsequent regexen easier to write, because we can + # match consecutive blank lines with /\n+/ instead of something + # contorted like /[ ]*\n+/ . + $text = preg_replace('/^[ ]+$/m', '', $text); + + # Run document gamut methods. + foreach ($this->document_gamut as $method => $priority) { + $text = $this->$method($text); + } + + $this->teardown(); + + return $text . "\n"; + } + + var $document_gamut = array( + # Strip link definitions, store in hashes. + "stripLinkDefinitions" => 20, + + "runBasicBlockGamut" => 30, + ); + + + function stripLinkDefinitions($text) { + # + # Strips link definitions from text, stores the URLs and titles in + # hash references. + # + $less_than_tab = $this->tab_width - 1; + + # Link defs are in the form: ^[id]: url "optional title" + $text = preg_replace_callback('{ + ^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?: # id = $1 + [ ]* + \n? # maybe *one* newline + [ ]* + (?: + <(.+?)> # url = $2 + | + (\S+?) # url = $3 + ) + [ ]* + \n? # maybe one newline + [ ]* + (?: + (?<=\s) # lookbehind for whitespace + ["(] + (.*?) # title = $4 + [")] + [ ]* + )? # title is optional + (?:\n+|\Z) + }xm', + array(&$this, '_stripLinkDefinitions_callback'), + $text); + return $text; + } + function _stripLinkDefinitions_callback($matches) { + $link_id = strtolower($matches[1]); + $url = $matches[2] == '' ? $matches[3] : $matches[2]; + $this->urls[$link_id] = $url; + $this->titles[$link_id] =& $matches[4]; + return ''; # String that will replace the block + } + + + function hashHTMLBlocks($text) { + if ($this->no_markup) return $text; + + $less_than_tab = $this->tab_width - 1; + + # Hashify HTML blocks: + # We only want to do this for block-level HTML tags, such as headers, + # lists, and tables. That's because we still want to wrap

    s around + # "paragraphs" that are wrapped in non-block-level tags, such as anchors, + # phrase emphasis, and spans. The list of tags we're looking for is + # hard-coded: + # + # * List "a" is made of tags which can be both inline or block-level. + # These will be treated block-level when the start tag is alone on + # its line, otherwise they're not matched here and will be taken as + # inline later. + # * List "b" is made of tags which are always block-level; + # + $block_tags_a_re = 'ins|del'; + $block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'. + 'script|noscript|form|fieldset|iframe|math|svg|'. + 'article|section|nav|aside|hgroup|header|footer|'. + 'figure'; + + # Regular expression for the content of a block tag. + $nested_tags_level = 4; + $attr = ' + (?> # optional tag attributes + \s # starts with whitespace + (?> + [^>"/]+ # text outside quotes + | + /+(?!>) # slash not followed by ">" + | + "[^"]*" # text inside double quotes (tolerate ">") + | + \'[^\']*\' # text inside single quotes (tolerate ">") + )* + )? + '; + $content = + str_repeat(' + (?> + [^<]+ # content without tag + | + <\2 # nested opening tag + '.$attr.' # attributes + (?> + /> + | + >', $nested_tags_level). # end of opening tag + '.*?'. # last level nested tag content + str_repeat(' + # closing nested tag + ) + | + <(?!/\2\s*> # other tags with a different name + ) + )*', + $nested_tags_level); + $content2 = str_replace('\2', '\3', $content); + + # First, look for nested blocks, e.g.: + #

    + #
    + # tags for inner block must be indented. + #
    + #
    + # + # The outermost tags must start at the left margin for this to match, and + # the inner nested divs must be indented. + # We need to do this before the next, more liberal match, because the next + # match will start at the first `
    ` and stop at the first `
    `. + $text = preg_replace_callback('{(?> + (?> + (?<=\n\n) # Starting after a blank line + | # or + \A\n? # the beginning of the doc + ) + ( # save in $1 + + # Match from `\n` to `\n`, handling nested tags + # in between. + + [ ]{0,'.$less_than_tab.'} + <('.$block_tags_b_re.')# start tag = $2 + '.$attr.'> # attributes followed by > and \n + '.$content.' # content, support nesting + # the matching end tag + [ ]* # trailing spaces/tabs + (?=\n+|\Z) # followed by a newline or end of document + + | # Special version for tags of group a. + + [ ]{0,'.$less_than_tab.'} + <('.$block_tags_a_re.')# start tag = $3 + '.$attr.'>[ ]*\n # attributes followed by > + '.$content2.' # content, support nesting + # the matching end tag + [ ]* # trailing spaces/tabs + (?=\n+|\Z) # followed by a newline or end of document + + | # Special case just for
    . It was easier to make a special + # case than to make the other regex more complicated. + + [ ]{0,'.$less_than_tab.'} + <(hr) # start tag = $2 + '.$attr.' # attributes + /?> # the matching end tag + [ ]* + (?=\n{2,}|\Z) # followed by a blank line or end of document + + | # Special case for standalone HTML comments: + + [ ]{0,'.$less_than_tab.'} + (?s: + + ) + [ ]* + (?=\n{2,}|\Z) # followed by a blank line or end of document + + | # PHP and ASP-style processor instructions ( + ) + [ ]* + (?=\n{2,}|\Z) # followed by a blank line or end of document + + ) + )}Sxmi', + array(&$this, '_hashHTMLBlocks_callback'), + $text); + + return $text; + } + function _hashHTMLBlocks_callback($matches) { + $text = $matches[1]; + $key = $this->hashBlock($text); + return "\n\n$key\n\n"; + } + + + function hashPart($text, $boundary = 'X') { + # + # Called whenever a tag must be hashed when a function insert an atomic + # element in the text stream. Passing $text to through this function gives + # a unique text-token which will be reverted back when calling unhash. + # + # The $boundary argument specify what character should be used to surround + # the token. By convension, "B" is used for block elements that needs not + # to be wrapped into paragraph tags at the end, ":" is used for elements + # that are word separators and "X" is used in the general case. + # + # Swap back any tag hash found in $text so we do not have to `unhash` + # multiple times at the end. + $text = $this->unhash($text); + + # Then hash the block. + static $i = 0; + $key = "$boundary\x1A" . ++$i . $boundary; + $this->html_hashes[$key] = $text; + return $key; # String that will replace the tag. + } + + + function hashBlock($text) { + # + # Shortcut function for hashPart with block-level boundaries. + # + return $this->hashPart($text, 'B'); + } + + + var $block_gamut = array( + # + # These are all the transformations that form block-level + # tags like paragraphs, headers, and list items. + # + "doHeaders" => 10, + "doHorizontalRules" => 20, + + "doLists" => 40, + "doCodeBlocks" => 50, + "doBlockQuotes" => 60, + ); + + function runBlockGamut($text) { + # + # Run block gamut tranformations. + # + # We need to escape raw HTML in Markdown source before doing anything + # else. This need to be done for each block, and not only at the + # begining in the Markdown function since hashed blocks can be part of + # list items and could have been indented. Indented blocks would have + # been seen as a code block in a previous pass of hashHTMLBlocks. + $text = $this->hashHTMLBlocks($text); + + return $this->runBasicBlockGamut($text); + } + + function runBasicBlockGamut($text) { + # + # Run block gamut tranformations, without hashing HTML blocks. This is + # useful when HTML blocks are known to be already hashed, like in the first + # whole-document pass. + # + foreach ($this->block_gamut as $method => $priority) { + $text = $this->$method($text); + } + + # Finally form paragraph and restore hashed blocks. + $text = $this->formParagraphs($text); + + return $text; + } + + + function doHorizontalRules($text) { + # Do Horizontal Rules: + return preg_replace( + '{ + ^[ ]{0,3} # Leading space + ([-*_]) # $1: First marker + (?> # Repeated marker group + [ ]{0,2} # Zero, one, or two spaces. + \1 # Marker character + ){2,} # Group repeated at least twice + [ ]* # Tailing spaces + $ # End of line. + }mx', + "\n".$this->hashBlock("empty_element_suffix")."\n", + $text); + } + + + var $span_gamut = array( + # + # These are all the transformations that occur *within* block-level + # tags like paragraphs, headers, and list items. + # + # Process character escapes, code spans, and inline HTML + # in one shot. + "parseSpan" => -30, + + # Process anchor and image tags. Images must come first, + # because ![foo][f] looks like an anchor. + "doImages" => 10, + "doAnchors" => 20, + + # Make links out of things like `` + # Must come after doAnchors, because you can use < and > + # delimiters in inline links like [this](). + "doAutoLinks" => 30, + "encodeAmpsAndAngles" => 40, + + "doItalicsAndBold" => 50, + "doHardBreaks" => 60, + ); + + function runSpanGamut($text) { + # + # Run span gamut tranformations. + # + foreach ($this->span_gamut as $method => $priority) { + $text = $this->$method($text); + } + + return $text; + } + + + function doHardBreaks($text) { + # Do hard breaks: + return preg_replace_callback('/ {2,}\n/', + array(&$this, '_doHardBreaks_callback'), $text); + } + function _doHardBreaks_callback($matches) { + return $this->hashPart("empty_element_suffix\n"); + } + + + function doAnchors($text) { + # + # Turn Markdown link shortcuts into XHTML tags. + # + if ($this->in_anchor) return $text; + $this->in_anchor = true; + + # + # First, handle reference-style links: [link text] [id] + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + \[ + ('.$this->nested_brackets_re.') # link text = $2 + \] + + [ ]? # one optional space + (?:\n[ ]*)? # one optional newline followed by spaces + + \[ + (.*?) # id = $3 + \] + ) + }xs', + array(&$this, '_doAnchors_reference_callback'), $text); + + # + # Next, inline-style links: [link text](url "optional title") + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + \[ + ('.$this->nested_brackets_re.') # link text = $2 + \] + \( # literal paren + [ \n]* + (?: + <(.+?)> # href = $3 + | + ('.$this->nested_url_parenthesis_re.') # href = $4 + ) + [ \n]* + ( # $5 + ([\'"]) # quote char = $6 + (.*?) # Title = $7 + \6 # matching quote + [ \n]* # ignore any spaces/tabs between closing quote and ) + )? # title is optional + \) + ) + }xs', + array(&$this, '_doAnchors_inline_callback'), $text); + + # + # Last, handle reference-style shortcuts: [link text] + # These must come last in case you've also got [link text][1] + # or [link text](/foo) + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + \[ + ([^\[\]]+) # link text = $2; can\'t contain [ or ] + \] + ) + }xs', + array(&$this, '_doAnchors_reference_callback'), $text); + + $this->in_anchor = false; + return $text; + } + function _doAnchors_reference_callback($matches) { + $whole_match = $matches[1]; + $link_text = $matches[2]; + $link_id =& $matches[3]; + + if ($link_id == "") { + # for shortcut links like [this][] or [this]. + $link_id = $link_text; + } + + # lower-case and turn embedded newlines into spaces + $link_id = strtolower($link_id); + $link_id = preg_replace('{[ ]?\n}', ' ', $link_id); + + if (isset($this->urls[$link_id])) { + $url = $this->urls[$link_id]; + $url = $this->encodeAttribute($url); + + $result = "titles[$link_id] ) ) { + $title = $this->titles[$link_id]; + $title = $this->encodeAttribute($title); + $result .= " title=\"$title\""; + } + + $link_text = $this->runSpanGamut($link_text); + $result .= ">$link_text"; + $result = $this->hashPart($result); + } + else { + $result = $whole_match; + } + return $result; + } + function _doAnchors_inline_callback($matches) { + $whole_match = $matches[1]; + $link_text = $this->runSpanGamut($matches[2]); + $url = $matches[3] == '' ? $matches[4] : $matches[3]; + $title =& $matches[7]; + + $url = $this->encodeAttribute($url); + + $result = "encodeAttribute($title); + $result .= " title=\"$title\""; + } + + $link_text = $this->runSpanGamut($link_text); + $result .= ">$link_text"; + + return $this->hashPart($result); + } + + + function doImages($text) { + # + # Turn Markdown image shortcuts into tags. + # + # + # First, handle reference-style labeled images: ![alt text][id] + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + !\[ + ('.$this->nested_brackets_re.') # alt text = $2 + \] + + [ ]? # one optional space + (?:\n[ ]*)? # one optional newline followed by spaces + + \[ + (.*?) # id = $3 + \] + + ) + }xs', + array(&$this, '_doImages_reference_callback'), $text); + + # + # Next, handle inline images: ![alt text](url "optional title") + # Don't forget: encode * and _ + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + !\[ + ('.$this->nested_brackets_re.') # alt text = $2 + \] + \s? # One optional whitespace character + \( # literal paren + [ \n]* + (?: + <(\S*)> # src url = $3 + | + ('.$this->nested_url_parenthesis_re.') # src url = $4 + ) + [ \n]* + ( # $5 + ([\'"]) # quote char = $6 + (.*?) # title = $7 + \6 # matching quote + [ \n]* + )? # title is optional + \) + ) + }xs', + array(&$this, '_doImages_inline_callback'), $text); + + return $text; + } + function _doImages_reference_callback($matches) { + $whole_match = $matches[1]; + $alt_text = $matches[2]; + $link_id = strtolower($matches[3]); + + if ($link_id == "") { + $link_id = strtolower($alt_text); # for shortcut links like ![this][]. + } + + $alt_text = $this->encodeAttribute($alt_text); + if (isset($this->urls[$link_id])) { + $url = $this->encodeAttribute($this->urls[$link_id]); + $result = "\"$alt_text\"";titles[$link_id])) { + $title = $this->titles[$link_id]; + $title = $this->encodeAttribute($title); + $result .= " title=\"$title\""; + } + $result .= $this->empty_element_suffix; + $result = $this->hashPart($result); + } + else { + # If there's no such link ID, leave intact: + $result = $whole_match; + } + + return $result; + } + function _doImages_inline_callback($matches) { + $whole_match = $matches[1]; + $alt_text = $matches[2]; + $url = $matches[3] == '' ? $matches[4] : $matches[3]; + $title =& $matches[7]; + + $alt_text = $this->encodeAttribute($alt_text); + $url = $this->encodeAttribute($url); + $result = "\"$alt_text\"";encodeAttribute($title); + $result .= " title=\"$title\""; # $title already quoted + } + $result .= $this->empty_element_suffix; + + return $this->hashPart($result); + } + + + function doHeaders($text) { + # Setext-style headers: + # Header 1 + # ======== + # + # Header 2 + # -------- + # + $text = preg_replace_callback('{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx', + array(&$this, '_doHeaders_callback_setext'), $text); + + # atx-style headers: + # # Header 1 + # ## Header 2 + # ## Header 2 with closing hashes ## + # ... + # ###### Header 6 + # + $text = preg_replace_callback('{ + ^(\#{1,6}) # $1 = string of #\'s + [ ]* + (.+?) # $2 = Header text + [ ]* + \#* # optional closing #\'s (not counted) + \n+ + }xm', + array(&$this, '_doHeaders_callback_atx'), $text); + + return $text; + } + function _doHeaders_callback_setext($matches) { + # Terrible hack to check we haven't found an empty list item. + if ($matches[2] == '-' && preg_match('{^-(?: |$)}', $matches[1])) + return $matches[0]; + + $level = $matches[2]{0} == '=' ? 1 : 2; + $block = "".$this->runSpanGamut($matches[1]).""; + return "\n" . $this->hashBlock($block) . "\n\n"; + } + function _doHeaders_callback_atx($matches) { + $level = strlen($matches[1]); + $block = "".$this->runSpanGamut($matches[2]).""; + return "\n" . $this->hashBlock($block) . "\n\n"; + } + + + function doLists($text) { + # + # Form HTML ordered (numbered) and unordered (bulleted) lists. + # + $less_than_tab = $this->tab_width - 1; + + # Re-usable patterns to match list item bullets and number markers: + $marker_ul_re = '[*+-]'; + $marker_ol_re = '\d+[\.]'; + $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)"; + + $markers_relist = array( + $marker_ul_re => $marker_ol_re, + $marker_ol_re => $marker_ul_re, + ); + + foreach ($markers_relist as $marker_re => $other_marker_re) { + # Re-usable pattern to match any entirel ul or ol list: + $whole_list_re = ' + ( # $1 = whole list + ( # $2 + ([ ]{0,'.$less_than_tab.'}) # $3 = number of spaces + ('.$marker_re.') # $4 = first list item marker + [ ]+ + ) + (?s:.+?) + ( # $5 + \z + | + \n{2,} + (?=\S) + (?! # Negative lookahead for another list item marker + [ ]* + '.$marker_re.'[ ]+ + ) + | + (?= # Lookahead for another kind of list + \n + \3 # Must have the same indentation + '.$other_marker_re.'[ ]+ + ) + ) + ) + '; // mx + + # We use a different prefix before nested lists than top-level lists. + # See extended comment in _ProcessListItems(). + + if ($this->list_level) { + $text = preg_replace_callback('{ + ^ + '.$whole_list_re.' + }mx', + array(&$this, '_doLists_callback'), $text); + } + else { + $text = preg_replace_callback('{ + (?:(?<=\n)\n|\A\n?) # Must eat the newline + '.$whole_list_re.' + }mx', + array(&$this, '_doLists_callback'), $text); + } + } + + return $text; + } + function _doLists_callback($matches) { + # Re-usable patterns to match list item bullets and number markers: + $marker_ul_re = '[*+-]'; + $marker_ol_re = '\d+[\.]'; + $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)"; + + $list = $matches[1]; + $list_type = preg_match("/$marker_ul_re/", $matches[4]) ? "ul" : "ol"; + + $marker_any_re = ( $list_type == "ul" ? $marker_ul_re : $marker_ol_re ); + + $list .= "\n"; + $result = $this->processListItems($list, $marker_any_re); + + $result = $this->hashBlock("<$list_type>\n" . $result . ""); + return "\n". $result ."\n\n"; + } + + var $list_level = 0; + + function processListItems($list_str, $marker_any_re) { + # + # Process the contents of a single ordered or unordered list, splitting it + # into individual list items. + # + # The $this->list_level global keeps track of when we're inside a list. + # Each time we enter a list, we increment it; when we leave a list, + # we decrement. If it's zero, we're not in a list anymore. + # + # We do this because when we're not inside a list, we want to treat + # something like this: + # + # I recommend upgrading to version + # 8. Oops, now this line is treated + # as a sub-list. + # + # As a single paragraph, despite the fact that the second line starts + # with a digit-period-space sequence. + # + # Whereas when we're inside a list (or sub-list), that line will be + # treated as the start of a sub-list. What a kludge, huh? This is + # an aspect of Markdown's syntax that's hard to parse perfectly + # without resorting to mind-reading. Perhaps the solution is to + # change the syntax rules such that sub-lists must start with a + # starting cardinal number; e.g. "1." or "a.". + + $this->list_level++; + + # trim trailing blank lines: + $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str); + + $list_str = preg_replace_callback('{ + (\n)? # leading line = $1 + (^[ ]*) # leading whitespace = $2 + ('.$marker_any_re.' # list marker and space = $3 + (?:[ ]+|(?=\n)) # space only required if item is not empty + ) + ((?s:.*?)) # list item text = $4 + (?:(\n+(?=\n))|\n) # tailing blank line = $5 + (?= \n* (\z | \2 ('.$marker_any_re.') (?:[ ]+|(?=\n)))) + }xm', + array(&$this, '_processListItems_callback'), $list_str); + + $this->list_level--; + return $list_str; + } + function _processListItems_callback($matches) { + $item = $matches[4]; + $leading_line =& $matches[1]; + $leading_space =& $matches[2]; + $marker_space = $matches[3]; + $tailing_blank_line =& $matches[5]; + + if ($leading_line || $tailing_blank_line || + preg_match('/\n{2,}/', $item)) + { + # Replace marker with the appropriate whitespace indentation + $item = $leading_space . str_repeat(' ', strlen($marker_space)) . $item; + $item = $this->runBlockGamut($this->outdent($item)."\n"); + } + else { + # Recursion for sub-lists: + $item = $this->doLists($this->outdent($item)); + $item = preg_replace('/\n+$/', '', $item); + $item = $this->runSpanGamut($item); + } + + return "
  • " . $item . "
  • \n"; + } + + + function doCodeBlocks($text) { + # + # Process Markdown `
    ` blocks.
    +	#
    +		$text = preg_replace_callback('{
    +				(?:\n\n|\A\n?)
    +				(	            # $1 = the code block -- one or more lines, starting with a space/tab
    +				  (?>
    +					[ ]{'.$this->tab_width.'}  # Lines must start with a tab or a tab-width of spaces
    +					.*\n+
    +				  )+
    +				)
    +				((?=^[ ]{0,'.$this->tab_width.'}\S)|\Z)	# Lookahead for non-space at line-start, or end of doc
    +			}xm',
    +			array(&$this, '_doCodeBlocks_callback'), $text);
    +
    +		return $text;
    +	}
    +	function _doCodeBlocks_callback($matches) {
    +		$codeblock = $matches[1];
    +
    +		$codeblock = $this->outdent($codeblock);
    +		$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
    +
    +		# trim leading newlines and trailing newlines
    +		$codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock);
    +
    +		$codeblock = "
    $codeblock\n
    "; + return "\n\n".$this->hashBlock($codeblock)."\n\n"; + } + + + function makeCodeSpan($code) { + # + # Create a code span markup for $code. Called from handleSpanToken. + # + $code = htmlspecialchars(trim($code), ENT_NOQUOTES); + return $this->hashPart("$code"); + } + + + var $em_relist = array( + '' => '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(?em_relist as $em => $em_re) { + foreach ($this->strong_relist as $strong => $strong_re) { + # Construct list of allowed token expressions. + $token_relist = array(); + if (isset($this->em_strong_relist["$em$strong"])) { + $token_relist[] = $this->em_strong_relist["$em$strong"]; + } + $token_relist[] = $em_re; + $token_relist[] = $strong_re; + + # Construct master expression from list. + $token_re = '{('. implode('|', $token_relist) .')}'; + $this->em_strong_prepared_relist["$em$strong"] = $token_re; + } + } + } + + function doItalicsAndBold($text) { + $token_stack = array(''); + $text_stack = array(''); + $em = ''; + $strong = ''; + $tree_char_em = false; + + while (1) { + # + # Get prepared regular expression for seraching emphasis tokens + # in current context. + # + $token_re = $this->em_strong_prepared_relist["$em$strong"]; + + # + # Each loop iteration search for the next emphasis token. + # Each token is then passed to handleSpanToken. + # + $parts = preg_split($token_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE); + $text_stack[0] .= $parts[0]; + $token =& $parts[1]; + $text =& $parts[2]; + + if (empty($token)) { + # Reached end of text span: empty stack without emitting. + # any more emphasis. + while ($token_stack[0]) { + $text_stack[1] .= array_shift($token_stack); + $text_stack[0] .= array_shift($text_stack); + } + break; + } + + $token_len = strlen($token); + if ($tree_char_em) { + # Reached closing marker while inside a three-char emphasis. + if ($token_len == 3) { + # Three-char closing marker, close em and strong. + array_shift($token_stack); + $span = array_shift($text_stack); + $span = $this->runSpanGamut($span); + $span = "$span"; + $text_stack[0] .= $this->hashPart($span); + $em = ''; + $strong = ''; + } else { + # Other closing marker: close one em or strong and + # change current token state to match the other + $token_stack[0] = str_repeat($token{0}, 3-$token_len); + $tag = $token_len == 2 ? "strong" : "em"; + $span = $text_stack[0]; + $span = $this->runSpanGamut($span); + $span = "<$tag>$span"; + $text_stack[0] = $this->hashPart($span); + $$tag = ''; # $$tag stands for $em or $strong + } + $tree_char_em = false; + } else if ($token_len == 3) { + if ($em) { + # Reached closing marker for both em and strong. + # Closing strong marker: + for ($i = 0; $i < 2; ++$i) { + $shifted_token = array_shift($token_stack); + $tag = strlen($shifted_token) == 2 ? "strong" : "em"; + $span = array_shift($text_stack); + $span = $this->runSpanGamut($span); + $span = "<$tag>$span"; + $text_stack[0] .= $this->hashPart($span); + $$tag = ''; # $$tag stands for $em or $strong + } + } else { + # Reached opening three-char emphasis marker. Push on token + # stack; will be handled by the special condition above. + $em = $token{0}; + $strong = "$em$em"; + array_unshift($token_stack, $token); + array_unshift($text_stack, ''); + $tree_char_em = true; + } + } else if ($token_len == 2) { + if ($strong) { + # Unwind any dangling emphasis marker: + if (strlen($token_stack[0]) == 1) { + $text_stack[1] .= array_shift($token_stack); + $text_stack[0] .= array_shift($text_stack); + } + # Closing strong marker: + array_shift($token_stack); + $span = array_shift($text_stack); + $span = $this->runSpanGamut($span); + $span = "$span"; + $text_stack[0] .= $this->hashPart($span); + $strong = ''; + } else { + array_unshift($token_stack, $token); + array_unshift($text_stack, ''); + $strong = $token; + } + } else { + # Here $token_len == 1 + if ($em) { + if (strlen($token_stack[0]) == 1) { + # Closing emphasis marker: + array_shift($token_stack); + $span = array_shift($text_stack); + $span = $this->runSpanGamut($span); + $span = "$span"; + $text_stack[0] .= $this->hashPart($span); + $em = ''; + } else { + $text_stack[0] .= $token; + } + } else { + array_unshift($token_stack, $token); + array_unshift($text_stack, ''); + $em = $token; + } + } + } + return $text_stack[0]; + } + + + function doBlockQuotes($text) { + $text = preg_replace_callback('/ + ( # Wrap whole match in $1 + (?> + ^[ ]*>[ ]? # ">" at the start of a line + .+\n # rest of the first line + (.+\n)* # subsequent consecutive lines + \n* # blanks + )+ + ) + /xm', + array(&$this, '_doBlockQuotes_callback'), $text); + + return $text; + } + function _doBlockQuotes_callback($matches) { + $bq = $matches[1]; + # trim one level of quoting - trim whitespace-only lines + $bq = preg_replace('/^[ ]*>[ ]?|^[ ]+$/m', '', $bq); + $bq = $this->runBlockGamut($bq); # recurse + + $bq = preg_replace('/^/m', " ", $bq); + # These leading spaces cause problem with
     content, 
    +		# so we need to fix that:
    +		$bq = preg_replace_callback('{(\s*
    .+?
    )}sx', + array(&$this, '_doBlockQuotes_callback2'), $bq); + + return "\n". $this->hashBlock("
    \n$bq\n
    ")."\n\n"; + } + function _doBlockQuotes_callback2($matches) { + $pre = $matches[1]; + $pre = preg_replace('/^ /m', '', $pre); + return $pre; + } + + + function formParagraphs($text) { + # + # Params: + # $text - string to process with html

    tags + # + # Strip leading and trailing lines: + $text = preg_replace('/\A\n+|\n+\z/', '', $text); + + $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY); + + # + # Wrap

    tags and unhashify HTML blocks + # + foreach ($grafs as $key => $value) { + if (!preg_match('/^B\x1A[0-9]+B$/', $value)) { + # Is a paragraph. + $value = $this->runSpanGamut($value); + $value = preg_replace('/^([ ]*)/', "

    ", $value); + $value .= "

    "; + $grafs[$key] = $this->unhash($value); + } + else { + # Is a block. + # Modify elements of @grafs in-place... + $graf = $value; + $block = $this->html_hashes[$graf]; + $graf = $block; +// if (preg_match('{ +// \A +// ( # $1 =
    tag +//
    ]* +// \b +// markdown\s*=\s* ([\'"]) # $2 = attr quote char +// 1 +// \2 +// [^>]* +// > +// ) +// ( # $3 = contents +// .* +// ) +// (
    ) # $4 = closing tag +// \z +// }xs', $block, $matches)) +// { +// list(, $div_open, , $div_content, $div_close) = $matches; +// +// # We can't call Markdown(), because that resets the hash; +// # that initialization code should be pulled into its own sub, though. +// $div_content = $this->hashHTMLBlocks($div_content); +// +// # Run document gamut methods on the content. +// foreach ($this->document_gamut as $method => $priority) { +// $div_content = $this->$method($div_content); +// } +// +// $div_open = preg_replace( +// '{\smarkdown\s*=\s*([\'"]).+?\1}', '', $div_open); +// +// $graf = $div_open . "\n" . $div_content . "\n" . $div_close; +// } + $grafs[$key] = $graf; + } + } + + return implode("\n\n", $grafs); + } + + + function encodeAttribute($text) { + # + # Encode text for a double-quoted HTML attribute. This function + # is *not* suitable for attributes enclosed in single quotes. + # + $text = $this->encodeAmpsAndAngles($text); + $text = str_replace('"', '"', $text); + return $text; + } + + + function encodeAmpsAndAngles($text) { + # + # Smart processing for ampersands and angle brackets that need to + # be encoded. Valid character entities are left alone unless the + # no-entities mode is set. + # + if ($this->no_entities) { + $text = str_replace('&', '&', $text); + } else { + # Ampersand-encoding based entirely on Nat Irons's Amputator + # MT plugin: + $text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/', + '&', $text);; + } + # Encode remaining <'s + $text = str_replace('<', '<', $text); + + return $text; + } + + + function doAutoLinks($text) { + $text = preg_replace_callback('{<((https?|ftp|dict):[^\'">\s]+)>}i', + array(&$this, '_doAutoLinks_url_callback'), $text); + + # Email addresses: + $text = preg_replace_callback('{ + < + (?:mailto:)? + ( + (?: + [-!#$%&\'*+/=?^_`.{|}~\w\x80-\xFF]+ + | + ".*?" + ) + \@ + (?: + [-a-z0-9\x80-\xFF]+(\.[-a-z0-9\x80-\xFF]+)*\.[a-z]+ + | + \[[\d.a-fA-F:]+\] # IPv4 & IPv6 + ) + ) + > + }xi', + array(&$this, '_doAutoLinks_email_callback'), $text); + + return $text; + } + function _doAutoLinks_url_callback($matches) { + $url = $this->encodeAttribute($matches[1]); + $link = "$url"; + return $this->hashPart($link); + } + function _doAutoLinks_email_callback($matches) { + $address = $matches[1]; + $link = $this->encodeEmailAddress($address); + return $this->hashPart($link); + } + + + function encodeEmailAddress($addr) { + # + # Input: an email address, e.g. "foo@example.com" + # + # Output: the email address as a mailto link, with each character + # of the address encoded as either a decimal or hex entity, in + # the hopes of foiling most address harvesting spam bots. E.g.: + # + #

    foo@exampl + # e.com

    + # + # Based by a filter by Matthew Wickline, posted to BBEdit-Talk. + # With some optimizations by Milian Wolff. + # + $addr = "mailto:" . $addr; + $chars = preg_split('/(? $char) { + $ord = ord($char); + # Ignore non-ascii chars. + if ($ord < 128) { + $r = ($seed * (1 + $key)) % 100; # Pseudo-random function. + # roughly 10% raw, 45% hex, 45% dec + # '@' *must* be encoded. I insist. + if ($r > 90 && $char != '@') /* do nothing */; + else if ($r < 45) $chars[$key] = '&#x'.dechex($ord).';'; + else $chars[$key] = '&#'.$ord.';'; + } + } + + $addr = implode('', $chars); + $text = implode('', array_slice($chars, 7)); # text without `mailto:` + $addr = "$text"; + + return $addr; + } + + + function parseSpan($str) { + # + # Take the string $str and parse it into tokens, hashing embeded HTML, + # escaped characters and handling code spans. + # + $output = ''; + + $span_re = '{ + ( + \\\\'.$this->escape_chars_re.' + | + (?no_markup ? '' : ' + | + # comment + | + <\?.*?\?> | <%.*?%> # processing instruction + | + <[!$]?[-a-zA-Z0-9:_]+ # regular tags + (?> + \s + (?>[^"\'>]+|"[^"]*"|\'[^\']*\')* + )? + > + | + <[-a-zA-Z0-9:_]+\s*/> # xml-style empty tag + | + # closing tag + ').' + ) + }xs'; + + while (1) { + # + # Each loop iteration seach for either the next tag, the next + # openning code span marker, or the next escaped character. + # Each token is then passed to handleSpanToken. + # + $parts = preg_split($span_re, $str, 2, PREG_SPLIT_DELIM_CAPTURE); + + # Create token from text preceding tag. + if ($parts[0] != "") { + $output .= $parts[0]; + } + + # Check if we reach the end. + if (isset($parts[1])) { + $output .= $this->handleSpanToken($parts[1], $parts[2]); + $str = $parts[2]; + } + else { + break; + } + } + + return $output; + } + + + function handleSpanToken($token, &$str) { + # + # Handle $token provided by parseSpan by determining its nature and + # returning the corresponding value that should replace it. + # + switch ($token{0}) { + case "\\": + return $this->hashPart("&#". ord($token{1}). ";"); + case "`": + # Search for end marker in remaining text. + if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm', + $str, $matches)) + { + $str = $matches[2]; + $codespan = $this->makeCodeSpan($matches[1]); + return $this->hashPart($codespan); + } + return $token; // return as text since no ending marker found. + default: + return $this->hashPart($token); + } + } + + + function outdent($text) { + # + # Remove one level of line-leading tabs or spaces + # + return preg_replace('/^(\t|[ ]{1,'.$this->tab_width.'})/m', '', $text); + } + + + # String length function for detab. `_initDetab` will create a function to + # hanlde UTF-8 if the default function does not exist. + var $utf8_strlen = 'mb_strlen'; + + function detab($text) { + # + # Replace tabs with the appropriate amount of space. + # + # For each line we separate the line in blocks delemited by + # tab characters. Then we reconstruct every line by adding the + # appropriate number of space between each blocks. + + $text = preg_replace_callback('/^.*\t.*$/m', + array(&$this, '_detab_callback'), $text); + + return $text; + } + function _detab_callback($matches) { + $line = $matches[0]; + $strlen = $this->utf8_strlen; # strlen function for UTF-8. + + # Split in blocks. + $blocks = explode("\t", $line); + # Add each blocks to the line. + $line = $blocks[0]; + unset($blocks[0]); # Do not add first block twice. + foreach ($blocks as $block) { + # Calculate amount of space, insert spaces, insert block. + $amount = $this->tab_width - + $strlen($line, 'UTF-8') % $this->tab_width; + $line .= str_repeat(" ", $amount) . $block; + } + return $line; + } + function _initDetab() { + # + # Check for the availability of the function in the `utf8_strlen` property + # (initially `mb_strlen`). If the function is not available, create a + # function that will loosely count the number of UTF-8 characters with a + # regular expression. + # + if (function_exists($this->utf8_strlen)) return; + $this->utf8_strlen = create_function('$text', 'return preg_match_all( + "/[\\\\x00-\\\\xBF]|[\\\\xC0-\\\\xFF][\\\\x80-\\\\xBF]*/", + $text, $m);'); + } + + + function unhash($text) { + # + # Swap back in all the tags hashed by _HashHTMLBlocks. + # + return preg_replace_callback('/(.)\x1A[0-9]+\1/', + array(&$this, '_unhash_callback'), $text); + } + function _unhash_callback($matches) { + return $this->html_hashes[$matches[0]]; + } + +} + + +# +# Markdown Extra Parser Class +# + +class MarkdownExtra_Parser extends Markdown_Parser { + + ### Configuration Variables ### + + # Prefix for footnote ids. + var $fn_id_prefix = ""; + + # Optional title attribute for footnote links and backlinks. + var $fn_link_title = MARKDOWN_FN_LINK_TITLE; + var $fn_backlink_title = MARKDOWN_FN_BACKLINK_TITLE; + + # Optional class attribute for footnote links and backlinks. + var $fn_link_class = MARKDOWN_FN_LINK_CLASS; + var $fn_backlink_class = MARKDOWN_FN_BACKLINK_CLASS; + + # Optional class prefix for fenced code block. + var $code_class_prefix = MARKDOWN_CODE_CLASS_PREFIX; + # Class attribute for code blocks goes on the `code` tag; + # setting this to true will put attributes on the `pre` tag instead. + var $code_attr_on_pre = MARKDOWN_CODE_ATTR_ON_PRE; + + # Predefined abbreviations. + var $predef_abbr = array(); + + + ### Parser Implementation ### + + function MarkdownExtra_Parser() { + # + # Constructor function. Initialize the parser object. + # + # Add extra escapable characters before parent constructor + # initialize the table. + $this->escape_chars .= ':|'; + + # Insert extra document, block, and span transformations. + # Parent constructor will do the sorting. + $this->document_gamut += array( + "doFencedCodeBlocks" => 5, + "stripFootnotes" => 15, + "stripAbbreviations" => 25, + "appendFootnotes" => 50, + ); + $this->block_gamut += array( + "doFencedCodeBlocks" => 5, + "doTables" => 15, + "doDefLists" => 45, + ); + $this->span_gamut += array( + "doFootnotes" => 5, + "doAbbreviations" => 70, + ); + + parent::Markdown_Parser(); + } + + + # Extra variables used during extra transformations. + var $footnotes = array(); + var $footnotes_ordered = array(); + var $footnotes_ref_count = array(); + var $footnotes_numbers = array(); + var $abbr_desciptions = array(); + var $abbr_word_re = ''; + + # Give the current footnote number. + var $footnote_counter = 1; + + + function setup() { + # + # Setting up Extra-specific variables. + # + parent::setup(); + + $this->footnotes = array(); + $this->footnotes_ordered = array(); + $this->footnotes_ref_count = array(); + $this->footnotes_numbers = array(); + $this->abbr_desciptions = array(); + $this->abbr_word_re = ''; + $this->footnote_counter = 1; + + foreach ($this->predef_abbr as $abbr_word => $abbr_desc) { + if ($this->abbr_word_re) + $this->abbr_word_re .= '|'; + $this->abbr_word_re .= preg_quote($abbr_word); + $this->abbr_desciptions[$abbr_word] = trim($abbr_desc); + } + } + + function teardown() { + # + # Clearing Extra-specific variables. + # + $this->footnotes = array(); + $this->footnotes_ordered = array(); + $this->footnotes_ref_count = array(); + $this->footnotes_numbers = array(); + $this->abbr_desciptions = array(); + $this->abbr_word_re = ''; + + parent::teardown(); + } + + + ### Extra Attribute Parser ### + + # Expression to use to catch attributes (includes the braces) + var $id_class_attr_catch_re = '\{((?:[ ]*[#.][-_:a-zA-Z0-9]+){1,})[ ]*\}'; + # Expression to use when parsing in a context when no capture is desired + var $id_class_attr_nocatch_re = '\{(?:[ ]*[#.][-_:a-zA-Z0-9]+){1,}[ ]*\}'; + + function doExtraAttributes($tag_name, $attr) { + # + # Parse attributes caught by the $this->id_class_attr_catch_re expression + # and return the HTML-formatted list of attributes. + # + # Currently supported attributes are .class and #id. + # + if (empty($attr)) return ""; + + # Split on components + preg_match_all('/[#.][-_:a-zA-Z0-9]+/', $attr, $matches); + $elements = $matches[0]; + + # handle classes and ids (only first id taken into account) + $classes = array(); + $id = false; + foreach ($elements as $element) { + if ($element{0} == '.') { + $classes[] = substr($element, 1); + } else if ($element{0} == '#') { + if ($id === false) $id = substr($element, 1); + } + } + + # compose attributes as string + $attr_str = ""; + if (!empty($id)) { + $attr_str .= ' id="'.$id.'"'; + } + if (!empty($classes)) { + $attr_str .= ' class="'.implode(" ", $classes).'"'; + } + return $attr_str; + } + + + function stripLinkDefinitions($text) { + # + # Strips link definitions from text, stores the URLs and titles in + # hash references. + # + $less_than_tab = $this->tab_width - 1; + + # Link defs are in the form: ^[id]: url "optional title" + $text = preg_replace_callback('{ + ^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?: # id = $1 + [ ]* + \n? # maybe *one* newline + [ ]* + (?: + <(.+?)> # url = $2 + | + (\S+?) # url = $3 + ) + [ ]* + \n? # maybe one newline + [ ]* + (?: + (?<=\s) # lookbehind for whitespace + ["(] + (.*?) # title = $4 + [")] + [ ]* + )? # title is optional + (?:[ ]* '.$this->id_class_attr_catch_re.' )? # $5 = extra id & class attr + (?:\n+|\Z) + }xm', + array(&$this, '_stripLinkDefinitions_callback'), + $text); + return $text; + } + function _stripLinkDefinitions_callback($matches) { + $link_id = strtolower($matches[1]); + $url = $matches[2] == '' ? $matches[3] : $matches[2]; + $this->urls[$link_id] = $url; + $this->titles[$link_id] =& $matches[4]; + $this->ref_attr[$link_id] = $this->doExtraAttributes("", $dummy =& $matches[5]); + return ''; # String that will replace the block + } + + + ### HTML Block Parser ### + + # Tags that are always treated as block tags: + var $block_tags_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|form|fieldset|iframe|hr|legend|article|section|nav|aside|hgroup|header|footer|figcaption'; + + # Tags treated as block tags only if the opening tag is alone on its line: + var $context_block_tags_re = 'script|noscript|ins|del|iframe|object|source|track|param|math|svg|canvas|audio|video'; + + # Tags where markdown="1" default to span mode: + var $contain_span_tags_re = 'p|h[1-6]|li|dd|dt|td|th|legend|address'; + + # Tags which must not have their contents modified, no matter where + # they appear: + var $clean_tags_re = 'script|math|svg'; + + # Tags that do not need to be closed. + var $auto_close_tags_re = 'hr|img|param|source|track'; + + + function hashHTMLBlocks($text) { + # + # Hashify HTML Blocks and "clean tags". + # + # We only want to do this for block-level HTML tags, such as headers, + # lists, and tables. That's because we still want to wrap

    s around + # "paragraphs" that are wrapped in non-block-level tags, such as anchors, + # phrase emphasis, and spans. The list of tags we're looking for is + # hard-coded. + # + # This works by calling _HashHTMLBlocks_InMarkdown, which then calls + # _HashHTMLBlocks_InHTML when it encounter block tags. When the markdown="1" + # attribute is found within a tag, _HashHTMLBlocks_InHTML calls back + # _HashHTMLBlocks_InMarkdown to handle the Markdown syntax within the tag. + # These two functions are calling each other. It's recursive! + # + if ($this->no_markup) return $text; + + # + # Call the HTML-in-Markdown hasher. + # + list($text, ) = $this->_hashHTMLBlocks_inMarkdown($text); + + return $text; + } + function _hashHTMLBlocks_inMarkdown($text, $indent = 0, + $enclosing_tag_re = '', $span = false) + { + # + # Parse markdown text, calling _HashHTMLBlocks_InHTML for block tags. + # + # * $indent is the number of space to be ignored when checking for code + # blocks. This is important because if we don't take the indent into + # account, something like this (which looks right) won't work as expected: + # + #

    + #
    + # Hello World. <-- Is this a Markdown code block or text? + #
    <-- Is this a Markdown code block or a real tag? + #
    + # + # If you don't like this, just don't indent the tag on which + # you apply the markdown="1" attribute. + # + # * If $enclosing_tag_re is not empty, stops at the first unmatched closing + # tag with that name. Nested tags supported. + # + # * If $span is true, text inside must treated as span. So any double + # newline will be replaced by a single newline so that it does not create + # paragraphs. + # + # Returns an array of that form: ( processed text , remaining text ) + # + if ($text === '') return array('', ''); + + # Regex to check for the presense of newlines around a block tag. + $newline_before_re = '/(?:^\n?|\n\n)*$/'; + $newline_after_re = + '{ + ^ # Start of text following the tag. + (?>[ ]*)? # Optional comment. + [ ]*\n # Must be followed by newline. + }xs'; + + # Regex to match any tag. + $block_tag_re = + '{ + ( # $2: Capture whole tag. + # Tag name. + '.$this->block_tags_re.' | + '.$this->context_block_tags_re.' | + '.$this->clean_tags_re.' | + (?!\s)'.$enclosing_tag_re.' + ) + (?: + (?=[\s"\'/a-zA-Z0-9]) # Allowed characters after tag name. + (?> + ".*?" | # Double quotes (can contain `>`) + \'.*?\' | # Single quotes (can contain `>`) + .+? # Anything but quotes and `>`. + )*? + )? + > # End of tag. + | + # HTML Comment + | + <\?.*?\?> | <%.*?%> # Processing instruction + | + # CData Block + | + # Code span marker + `+ + '. ( !$span ? ' # If not in span. + | + # Indented code block + (?: ^[ ]*\n | ^ | \n[ ]*\n ) + [ ]{'.($indent+4).'}[^\n]* \n + (?> + (?: [ ]{'.($indent+4).'}[^\n]* | [ ]* ) \n + )* + | + # Fenced code block marker + (?<= ^ | \n ) + [ ]{0,'.($indent+3).'}~{3,} + [ ]* + (?: + \.?[-_:a-zA-Z0-9]+ # standalone class name + | + '.$this->id_class_attr_nocatch_re.' # extra attributes + )? + [ ]* + \n + ' : '' ). ' # End (if not is span). + ) + }xs'; + + + $depth = 0; # Current depth inside the tag tree. + $parsed = ""; # Parsed text that will be returned. + + # + # Loop through every tag until we find the closing tag of the parent + # or loop until reaching the end of text if no parent tag specified. + # + do { + # + # Split the text using the first $tag_match pattern found. + # Text before pattern will be first in the array, text after + # pattern will be at the end, and between will be any catches made + # by the pattern. + # + $parts = preg_split($block_tag_re, $text, 2, + PREG_SPLIT_DELIM_CAPTURE); + + # If in Markdown span mode, add a empty-string span-level hash + # after each newline to prevent triggering any block element. + if ($span) { + $void = $this->hashPart("", ':'); + $newline = "$void\n"; + $parts[0] = $void . str_replace("\n", $newline, $parts[0]) . $void; + } + + $parsed .= $parts[0]; # Text before current tag. + + # If end of $text has been reached. Stop loop. + if (count($parts) < 3) { + $text = ""; + break; + } + + $tag = $parts[1]; # Tag to handle. + $text = $parts[2]; # Remaining text after current tag. + $tag_re = preg_quote($tag); # For use in a regular expression. + + # + # Check for: Code span marker + # + if ($tag{0} == "`") { + # Find corresponding end marker. + $tag_re = preg_quote($tag); + if (preg_match('{^(?>.+?|\n(?!\n))*?(?.*\n)*?[ ]{'.($fence_indent).'}'.$fence_re.'[ ]*(?:\n|$)}', $text, + $matches)) + { + # End marker found: pass text unchanged until marker. + $parsed .= $tag . $matches[0]; + $text = substr($text, strlen($matches[0])); + } + else { + # No end marker: just skip it. + $parsed .= $tag; + } + } + # + # Check for: Indented code block. + # + else if ($tag{0} == "\n" || $tag{0} == " ") { + # Indented code block: pass it unchanged, will be handled + # later. + $parsed .= $tag; + } + # + # Check for: Opening Block level tag or + # Opening Context Block tag (like ins and del) + # used as a block tag (tag is alone on it's line). + # + else if (preg_match('{^<(?:'.$this->block_tags_re.')\b}', $tag) || + ( preg_match('{^<(?:'.$this->context_block_tags_re.')\b}', $tag) && + preg_match($newline_before_re, $parsed) && + preg_match($newline_after_re, $text) ) + ) + { + # Need to parse tag and following text using the HTML parser. + list($block_text, $text) = + $this->_hashHTMLBlocks_inHTML($tag . $text, "hashBlock", true); + + # Make sure it stays outside of any paragraph by adding newlines. + $parsed .= "\n\n$block_text\n\n"; + } + # + # Check for: Clean tag (like script, math) + # HTML Comments, processing instructions. + # + else if (preg_match('{^<(?:'.$this->clean_tags_re.')\b}', $tag) || + $tag{1} == '!' || $tag{1} == '?') + { + # Need to parse tag and following text using the HTML parser. + # (don't check for markdown attribute) + list($block_text, $text) = + $this->_hashHTMLBlocks_inHTML($tag . $text, "hashClean", false); + + $parsed .= $block_text; + } + # + # Check for: Tag with same name as enclosing tag. + # + else if ($enclosing_tag_re !== '' && + # Same name as enclosing tag. + preg_match('{^= 0); + + return array($parsed, $text); + } + function _hashHTMLBlocks_inHTML($text, $hash_method, $md_attr) { + # + # Parse HTML, calling _HashHTMLBlocks_InMarkdown for block tags. + # + # * Calls $hash_method to convert any blocks. + # * Stops when the first opening tag closes. + # * $md_attr indicate if the use of the `markdown="1"` attribute is allowed. + # (it is not inside clean tags) + # + # Returns an array of that form: ( processed text , remaining text ) + # + if ($text === '') return array('', ''); + + # Regex to match `markdown` attribute inside of a tag. + $markdown_attr_re = ' + { + \s* # Eat whitespace before the `markdown` attribute + markdown + \s*=\s* + (?> + (["\']) # $1: quote delimiter + (.*?) # $2: attribute value + \1 # matching delimiter + | + ([^\s>]*) # $3: unquoted attribute value + ) + () # $4: make $3 always defined (avoid warnings) + }xs'; + + # Regex to match any tag. + $tag_re = '{ + ( # $2: Capture whole tag. + + ".*?" | # Double quotes (can contain `>`) + \'.*?\' | # Single quotes (can contain `>`) + .+? # Anything but quotes and `>`. + )*? + )? + > # End of tag. + | + # HTML Comment + | + <\?.*?\?> | <%.*?%> # Processing instruction + | + # CData Block + ) + }xs'; + + $original_text = $text; # Save original text in case of faliure. + + $depth = 0; # Current depth inside the tag tree. + $block_text = ""; # Temporary text holder for current text. + $parsed = ""; # Parsed text that will be returned. + + # + # Get the name of the starting tag. + # (This pattern makes $base_tag_name_re safe without quoting.) + # + if (preg_match('/^<([\w:$]*)\b/', $text, $matches)) + $base_tag_name_re = $matches[1]; + + # + # Loop through every tag until we find the corresponding closing tag. + # + do { + # + # Split the text using the first $tag_match pattern found. + # Text before pattern will be first in the array, text after + # pattern will be at the end, and between will be any catches made + # by the pattern. + # + $parts = preg_split($tag_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE); + + if (count($parts) < 3) { + # + # End of $text reached with unbalenced tag(s). + # In that case, we return original text unchanged and pass the + # first character as filtered to prevent an infinite loop in the + # parent function. + # + return array($original_text{0}, substr($original_text, 1)); + } + + $block_text .= $parts[0]; # Text before current tag. + $tag = $parts[1]; # Tag to handle. + $text = $parts[2]; # Remaining text after current tag. + + # + # Check for: Auto-close tag (like
    ) + # Comments and Processing Instructions. + # + if (preg_match('{^auto_close_tags_re.')\b}', $tag) || + $tag{1} == '!' || $tag{1} == '?') + { + # Just add the tag to the block as if it was text. + $block_text .= $tag; + } + else { + # + # Increase/decrease nested tag count. Only do so if + # the tag's name match base tag's. + # + if (preg_match('{^mode = $attr_m[2] . $attr_m[3]; + $span_mode = $this->mode == 'span' || $this->mode != 'block' && + preg_match('{^<(?:'.$this->contain_span_tags_re.')\b}', $tag); + + # Calculate indent before tag. + if (preg_match('/(?:^|\n)( *?)(?! ).*?$/', $block_text, $matches)) { + $strlen = $this->utf8_strlen; + $indent = $strlen($matches[1], 'UTF-8'); + } else { + $indent = 0; + } + + # End preceding block with this tag. + $block_text .= $tag; + $parsed .= $this->$hash_method($block_text); + + # Get enclosing tag name for the ParseMarkdown function. + # (This pattern makes $tag_name_re safe without quoting.) + preg_match('/^<([\w:$]*)\b/', $tag, $matches); + $tag_name_re = $matches[1]; + + # Parse the content using the HTML-in-Markdown parser. + list ($block_text, $text) + = $this->_hashHTMLBlocks_inMarkdown($text, $indent, + $tag_name_re, $span_mode); + + # Outdent markdown text. + if ($indent > 0) { + $block_text = preg_replace("/^[ ]{1,$indent}/m", "", + $block_text); + } + + # Append tag content to parsed text. + if (!$span_mode) $parsed .= "\n\n$block_text\n\n"; + else $parsed .= "$block_text"; + + # Start over with a new block. + $block_text = ""; + } + else $block_text .= $tag; + } + + } while ($depth > 0); + + # + # Hash last block text that wasn't processed inside the loop. + # + $parsed .= $this->$hash_method($block_text); + + return array($parsed, $text); + } + + + function hashClean($text) { + # + # Called whenever a tag must be hashed when a function inserts a "clean" tag + # in $text, it passes through this function and is automaticaly escaped, + # blocking invalid nested overlap. + # + return $this->hashPart($text, 'C'); + } + + + function doAnchors($text) { + # + # Turn Markdown link shortcuts into XHTML tags. + # + if ($this->in_anchor) return $text; + $this->in_anchor = true; + + # + # First, handle reference-style links: [link text] [id] + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + \[ + ('.$this->nested_brackets_re.') # link text = $2 + \] + + [ ]? # one optional space + (?:\n[ ]*)? # one optional newline followed by spaces + + \[ + (.*?) # id = $3 + \] + ) + }xs', + array(&$this, '_doAnchors_reference_callback'), $text); + + # + # Next, inline-style links: [link text](url "optional title") + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + \[ + ('.$this->nested_brackets_re.') # link text = $2 + \] + \( # literal paren + [ \n]* + (?: + <(.+?)> # href = $3 + | + ('.$this->nested_url_parenthesis_re.') # href = $4 + ) + [ \n]* + ( # $5 + ([\'"]) # quote char = $6 + (.*?) # Title = $7 + \6 # matching quote + [ \n]* # ignore any spaces/tabs between closing quote and ) + )? # title is optional + \) + (?:[ ]? '.$this->id_class_attr_catch_re.' )? # $8 = id/class attributes + ) + }xs', + array(&$this, '_doAnchors_inline_callback'), $text); + + # + # Last, handle reference-style shortcuts: [link text] + # These must come last in case you've also got [link text][1] + # or [link text](/foo) + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + \[ + ([^\[\]]+) # link text = $2; can\'t contain [ or ] + \] + ) + }xs', + array(&$this, '_doAnchors_reference_callback'), $text); + + $this->in_anchor = false; + return $text; + } + function _doAnchors_reference_callback($matches) { + $whole_match = $matches[1]; + $link_text = $matches[2]; + $link_id =& $matches[3]; + + if ($link_id == "") { + # for shortcut links like [this][] or [this]. + $link_id = $link_text; + } + + # lower-case and turn embedded newlines into spaces + $link_id = strtolower($link_id); + $link_id = preg_replace('{[ ]?\n}', ' ', $link_id); + + if (isset($this->urls[$link_id])) { + $url = $this->urls[$link_id]; + $url = $this->encodeAttribute($url); + + $result = "titles[$link_id] ) ) { + $title = $this->titles[$link_id]; + $title = $this->encodeAttribute($title); + $result .= " title=\"$title\""; + } + if (isset($this->ref_attr[$link_id])) + $result .= $this->ref_attr[$link_id]; + + $link_text = $this->runSpanGamut($link_text); + $result .= ">$link_text"; + $result = $this->hashPart($result); + } + else { + $result = $whole_match; + } + return $result; + } + function _doAnchors_inline_callback($matches) { + $whole_match = $matches[1]; + $link_text = $this->runSpanGamut($matches[2]); + $url = $matches[3] == '' ? $matches[4] : $matches[3]; + $title =& $matches[7]; + $attr = $this->doExtraAttributes("a", $dummy =& $matches[8]); + + + $url = $this->encodeAttribute($url); + + $result = "encodeAttribute($title); + $result .= " title=\"$title\""; + } + $result .= $attr; + + $link_text = $this->runSpanGamut($link_text); + $result .= ">$link_text"; + + return $this->hashPart($result); + } + + + function doImages($text) { + # + # Turn Markdown image shortcuts into tags. + # + # + # First, handle reference-style labeled images: ![alt text][id] + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + !\[ + ('.$this->nested_brackets_re.') # alt text = $2 + \] + + [ ]? # one optional space + (?:\n[ ]*)? # one optional newline followed by spaces + + \[ + (.*?) # id = $3 + \] + + ) + }xs', + array(&$this, '_doImages_reference_callback'), $text); + + # + # Next, handle inline images: ![alt text](url "optional title") + # Don't forget: encode * and _ + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + !\[ + ('.$this->nested_brackets_re.') # alt text = $2 + \] + \s? # One optional whitespace character + \( # literal paren + [ \n]* + (?: + <(\S*)> # src url = $3 + | + ('.$this->nested_url_parenthesis_re.') # src url = $4 + ) + [ \n]* + ( # $5 + ([\'"]) # quote char = $6 + (.*?) # title = $7 + \6 # matching quote + [ \n]* + )? # title is optional + \) + (?:[ ]? '.$this->id_class_attr_catch_re.' )? # $8 = id/class attributes + ) + }xs', + array(&$this, '_doImages_inline_callback'), $text); + + return $text; + } + function _doImages_reference_callback($matches) { + $whole_match = $matches[1]; + $alt_text = $matches[2]; + $link_id = strtolower($matches[3]); + + if ($link_id == "") { + $link_id = strtolower($alt_text); # for shortcut links like ![this][]. + } + + $alt_text = $this->encodeAttribute($alt_text); + if (isset($this->urls[$link_id])) { + $url = $this->encodeAttribute($this->urls[$link_id]); + $result = "\"$alt_text\"";titles[$link_id])) { + $title = $this->titles[$link_id]; + $title = $this->encodeAttribute($title); + $result .= " title=\"$title\""; + } + if (isset($this->ref_attr[$link_id])) + $result .= $this->ref_attr[$link_id]; + $result .= $this->empty_element_suffix; + $result = $this->hashPart($result); + } + else { + # If there's no such link ID, leave intact: + $result = $whole_match; + } + + return $result; + } + function _doImages_inline_callback($matches) { + $whole_match = $matches[1]; + $alt_text = $matches[2]; + $url = $matches[3] == '' ? $matches[4] : $matches[3]; + $title =& $matches[7]; + $attr = $this->doExtraAttributes("img", $dummy =& $matches[8]); + + $alt_text = $this->encodeAttribute($alt_text); + $url = $this->encodeAttribute($url); + $result = "\"$alt_text\"";encodeAttribute($title); + $result .= " title=\"$title\""; # $title already quoted + } + $result .= $attr; + $result .= $this->empty_element_suffix; + + return $this->hashPart($result); + } + + + function doHeaders($text) { + # + # Redefined to add id and class attribute support. + # + # Setext-style headers: + # Header 1 {#header1} + # ======== + # + # Header 2 {#header2 .class1 .class2} + # -------- + # + $text = preg_replace_callback( + '{ + (^.+?) # $1: Header text + (?:[ ]+ '.$this->id_class_attr_catch_re.' )? # $3 = id/class attributes + [ ]*\n(=+|-+)[ ]*\n+ # $3: Header footer + }mx', + array(&$this, '_doHeaders_callback_setext'), $text); + + # atx-style headers: + # # Header 1 {#header1} + # ## Header 2 {#header2} + # ## Header 2 with closing hashes ## {#header3.class1.class2} + # ... + # ###### Header 6 {.class2} + # + $text = preg_replace_callback('{ + ^(\#{1,6}) # $1 = string of #\'s + [ ]* + (.+?) # $2 = Header text + [ ]* + \#* # optional closing #\'s (not counted) + (?:[ ]+ '.$this->id_class_attr_catch_re.' )? # $3 = id/class attributes + [ ]* + \n+ + }xm', + array(&$this, '_doHeaders_callback_atx'), $text); + + return $text; + } + function _doHeaders_callback_setext($matches) { + if ($matches[3] == '-' && preg_match('{^- }', $matches[1])) + return $matches[0]; + $level = $matches[3]{0} == '=' ? 1 : 2; + $attr = $this->doExtraAttributes("h$level", $dummy =& $matches[2]); + $block = "".$this->runSpanGamut($matches[1]).""; + return "\n" . $this->hashBlock($block) . "\n\n"; + } + function _doHeaders_callback_atx($matches) { + $level = strlen($matches[1]); + $attr = $this->doExtraAttributes("h$level", $dummy =& $matches[3]); + $block = "".$this->runSpanGamut($matches[2]).""; + return "\n" . $this->hashBlock($block) . "\n\n"; + } + + + function doTables($text) { + # + # Form HTML tables. + # + $less_than_tab = $this->tab_width - 1; + # + # Find tables with leading pipe. + # + # | Header 1 | Header 2 + # | -------- | -------- + # | Cell 1 | Cell 2 + # | Cell 3 | Cell 4 + # + $text = preg_replace_callback(' + { + ^ # Start of a line + [ ]{0,'.$less_than_tab.'} # Allowed whitespace. + [|] # Optional leading pipe (present) + (.+) \n # $1: Header row (at least one pipe) + + [ ]{0,'.$less_than_tab.'} # Allowed whitespace. + [|] ([ ]*[-:]+[-| :]*) \n # $2: Header underline + + ( # $3: Cells + (?> + [ ]* # Allowed whitespace. + [|] .* \n # Row content. + )* + ) + (?=\n|\Z) # Stop at final double newline. + }xm', + array(&$this, '_doTable_leadingPipe_callback'), $text); + + # + # Find tables without leading pipe. + # + # Header 1 | Header 2 + # -------- | -------- + # Cell 1 | Cell 2 + # Cell 3 | Cell 4 + # + $text = preg_replace_callback(' + { + ^ # Start of a line + [ ]{0,'.$less_than_tab.'} # Allowed whitespace. + (\S.*[|].*) \n # $1: Header row (at least one pipe) + + [ ]{0,'.$less_than_tab.'} # Allowed whitespace. + ([-:]+[ ]*[|][-| :]*) \n # $2: Header underline + + ( # $3: Cells + (?> + .* [|] .* \n # Row content + )* + ) + (?=\n|\Z) # Stop at final double newline. + }xm', + array(&$this, '_DoTable_callback'), $text); + + return $text; + } + function _doTable_leadingPipe_callback($matches) { + $head = $matches[1]; + $underline = $matches[2]; + $content = $matches[3]; + + # Remove leading pipe for each row. + $content = preg_replace('/^ *[|]/m', '', $content); + + return $this->_doTable_callback(array($matches[0], $head, $underline, $content)); + } + function _doTable_callback($matches) { + $head = $matches[1]; + $underline = $matches[2]; + $content = $matches[3]; + + # Remove any tailing pipes for each line. + $head = preg_replace('/[|] *$/m', '', $head); + $underline = preg_replace('/[|] *$/m', '', $underline); + $content = preg_replace('/[|] *$/m', '', $content); + + # Reading alignement from header underline. + $separators = preg_split('/ *[|] */', $underline); + foreach ($separators as $n => $s) { + if (preg_match('/^ *-+: *$/', $s)) $attr[$n] = ' align="right"'; + else if (preg_match('/^ *:-+: *$/', $s))$attr[$n] = ' align="center"'; + else if (preg_match('/^ *:-+ *$/', $s)) $attr[$n] = ' align="left"'; + else $attr[$n] = ''; + } + + # Parsing span elements, including code spans, character escapes, + # and inline HTML tags, so that pipes inside those gets ignored. + $head = $this->parseSpan($head); + $headers = preg_split('/ *[|] */', $head); + $col_count = count($headers); + $attr = array_pad($attr, $col_count, ''); + + # Write column headers. + $text = "\n"; + $text .= "\n"; + $text .= "\n"; + foreach ($headers as $n => $header) + $text .= " ".$this->runSpanGamut(trim($header))."\n"; + $text .= "\n"; + $text .= "\n"; + + # Split content by row. + $rows = explode("\n", trim($content, "\n")); + + $text .= "\n"; + foreach ($rows as $row) { + # Parsing span elements, including code spans, character escapes, + # and inline HTML tags, so that pipes inside those gets ignored. + $row = $this->parseSpan($row); + + # Split row by cell. + $row_cells = preg_split('/ *[|] */', $row, $col_count); + $row_cells = array_pad($row_cells, $col_count, ''); + + $text .= "\n"; + foreach ($row_cells as $n => $cell) + $text .= " ".$this->runSpanGamut(trim($cell))."\n"; + $text .= "\n"; + } + $text .= "\n"; + $text .= "
    "; + + return $this->hashBlock($text) . "\n"; + } + + + function doDefLists($text) { + # + # Form HTML definition lists. + # + $less_than_tab = $this->tab_width - 1; + + # Re-usable pattern to match any entire dl list: + $whole_list_re = '(?> + ( # $1 = whole list + ( # $2 + [ ]{0,'.$less_than_tab.'} + ((?>.*\S.*\n)+) # $3 = defined term + \n? + [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition + ) + (?s:.+?) + ( # $4 + \z + | + \n{2,} + (?=\S) + (?! # Negative lookahead for another term + [ ]{0,'.$less_than_tab.'} + (?: \S.*\n )+? # defined term + \n? + [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition + ) + (?! # Negative lookahead for another definition + [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition + ) + ) + ) + )'; // mx + + $text = preg_replace_callback('{ + (?>\A\n?|(?<=\n\n)) + '.$whole_list_re.' + }mx', + array(&$this, '_doDefLists_callback'), $text); + + return $text; + } + function _doDefLists_callback($matches) { + # Re-usable patterns to match list item bullets and number markers: + $list = $matches[1]; + + # Turn double returns into triple returns, so that we can make a + # paragraph for the last item in a list, if necessary: + $result = trim($this->processDefListItems($list)); + $result = "
    \n" . $result . "\n
    "; + return $this->hashBlock($result) . "\n\n"; + } + + + function processDefListItems($list_str) { + # + # Process the contents of a single definition list, splitting it + # into individual term and definition list items. + # + $less_than_tab = $this->tab_width - 1; + + # trim trailing blank lines: + $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str); + + # Process definition terms. + $list_str = preg_replace_callback('{ + (?>\A\n?|\n\n+) # leading line + ( # definition terms = $1 + [ ]{0,'.$less_than_tab.'} # leading whitespace + (?!\:[ ]|[ ]) # negative lookahead for a definition + # mark (colon) or more whitespace. + (?> \S.* \n)+? # actual term (not whitespace). + ) + (?=\n?[ ]{0,3}:[ ]) # lookahead for following line feed + # with a definition mark. + }xm', + array(&$this, '_processDefListItems_callback_dt'), $list_str); + + # Process actual definitions. + $list_str = preg_replace_callback('{ + \n(\n+)? # leading line = $1 + ( # marker space = $2 + [ ]{0,'.$less_than_tab.'} # whitespace before colon + \:[ ]+ # definition mark (colon) + ) + ((?s:.+?)) # definition text = $3 + (?= \n+ # stop at next definition mark, + (?: # next term or end of text + [ ]{0,'.$less_than_tab.'} \:[ ] | +
    | \z + ) + ) + }xm', + array(&$this, '_processDefListItems_callback_dd'), $list_str); + + return $list_str; + } + function _processDefListItems_callback_dt($matches) { + $terms = explode("\n", trim($matches[1])); + $text = ''; + foreach ($terms as $term) { + $term = $this->runSpanGamut(trim($term)); + $text .= "\n
    " . $term . "
    "; + } + return $text . "\n"; + } + function _processDefListItems_callback_dd($matches) { + $leading_line = $matches[1]; + $marker_space = $matches[2]; + $def = $matches[3]; + + if ($leading_line || preg_match('/\n{2,}/', $def)) { + # Replace marker with the appropriate whitespace indentation + $def = str_repeat(' ', strlen($marker_space)) . $def; + $def = $this->runBlockGamut($this->outdent($def . "\n\n")); + $def = "\n". $def ."\n"; + } + else { + $def = rtrim($def); + $def = $this->runSpanGamut($this->outdent($def)); + } + + return "\n
    " . $def . "
    \n"; + } + + + function doFencedCodeBlocks($text) { + # + # Adding the fenced code block syntax to regular Markdown: + # + # ~~~ + # Code block + # ~~~ + # + $less_than_tab = $this->tab_width; + + $text = preg_replace_callback('{ + (?:\n|\A) + # 1: Opening marker + ( + ~{3,} # Marker: three tilde or more. + ) + [ ]* + (?: + \.?([-_:a-zA-Z0-9]+) # 2: standalone class name + | + '.$this->id_class_attr_catch_re.' # 3: Extra attributes + )? + [ ]* \n # Whitespace and newline following marker. + + # 4: Content + ( + (?> + (?!\1 [ ]* \n) # Not a closing marker. + .*\n+ + )+ + ) + + # Closing marker. + \1 [ ]* \n + }xm', + array(&$this, '_doFencedCodeBlocks_callback'), $text); + + return $text; + } + function _doFencedCodeBlocks_callback($matches) { + $classname =& $matches[2]; + $attrs =& $matches[3]; + $codeblock = $matches[4]; + $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES); + $codeblock = preg_replace_callback('/^\n+/', + array(&$this, '_doFencedCodeBlocks_newlines'), $codeblock); + + if ($classname != "") { + if ($classname{0} == '.') + $classname = substr($classname, 1); + $attr_str = ' class="'.$this->code_class_prefix.$classname.'"'; + } else { + $attr_str = $this->doExtraAttributes($this->code_attr_on_pre ? "pre" : "code", $attrs); + } + $pre_attr_str = $this->code_attr_on_pre ? $attr_str : ''; + $code_attr_str = $this->code_attr_on_pre ? '' : $attr_str; + $codeblock = "$codeblock
    "; + + return "\n\n".$this->hashBlock($codeblock)."\n\n"; + } + function _doFencedCodeBlocks_newlines($matches) { + return str_repeat("empty_element_suffix", + strlen($matches[0])); + } + + + # + # Redefining emphasis markers so that emphasis by underscore does not + # work in the middle of a word. + # + var $em_relist = array( + '' => '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? tags + # + # Strip leading and trailing lines: + $text = preg_replace('/\A\n+|\n+\z/', '', $text); + + $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY); + + # + # Wrap

    tags and unhashify HTML blocks + # + foreach ($grafs as $key => $value) { + $value = trim($this->runSpanGamut($value)); + + # Check if this should be enclosed in a paragraph. + # Clean tag hashes & block tag hashes are left alone. + $is_p = !preg_match('/^B\x1A[0-9]+B|^C\x1A[0-9]+C$/', $value); + + if ($is_p) { + $value = "

    $value

    "; + } + $grafs[$key] = $value; + } + + # Join grafs in one text, then unhash HTML tags. + $text = implode("\n\n", $grafs); + + # Finish by removing any tag hashes still present in $text. + $text = $this->unhash($text); + + return $text; + } + + + ### Footnotes + + function stripFootnotes($text) { + # + # Strips link definitions from text, stores the URLs and titles in + # hash references. + # + $less_than_tab = $this->tab_width - 1; + + # Link defs are in the form: [^id]: url "optional title" + $text = preg_replace_callback('{ + ^[ ]{0,'.$less_than_tab.'}\[\^(.+?)\][ ]?: # note_id = $1 + [ ]* + \n? # maybe *one* newline + ( # text = $2 (no blank lines allowed) + (?: + .+ # actual text + | + \n # newlines but + (?!\[\^.+?\]:\s)# negative lookahead for footnote marker. + (?!\n+[ ]{0,3}\S)# ensure line is not blank and followed + # by non-indented content + )* + ) + }xm', + array(&$this, '_stripFootnotes_callback'), + $text); + return $text; + } + function _stripFootnotes_callback($matches) { + $note_id = $this->fn_id_prefix . $matches[1]; + $this->footnotes[$note_id] = $this->outdent($matches[2]); + return ''; # String that will replace the block + } + + + function doFootnotes($text) { + # + # Replace footnote references in $text [^id] with a special text-token + # which will be replaced by the actual footnote marker in appendFootnotes. + # + if (!$this->in_anchor) { + $text = preg_replace('{\[\^(.+?)\]}', "F\x1Afn:\\1\x1A:", $text); + } + return $text; + } + + + function appendFootnotes($text) { + # + # Append footnote list to text. + # + $text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', + array(&$this, '_appendFootnotes_callback'), $text); + + if (!empty($this->footnotes_ordered)) { + $text .= "\n\n"; + $text .= "
    \n"; + $text .= "empty_element_suffix ."\n"; + $text .= "
      \n\n"; + + $attr = " rev=\"footnote\""; + if ($this->fn_backlink_class != "") { + $class = $this->fn_backlink_class; + $class = $this->encodeAttribute($class); + $attr .= " class=\"$class\""; + } + if ($this->fn_backlink_title != "") { + $title = $this->fn_backlink_title; + $title = $this->encodeAttribute($title); + $attr .= " title=\"$title\""; + } + $num = 0; + + while (!empty($this->footnotes_ordered)) { + $footnote = reset($this->footnotes_ordered); + $note_id = key($this->footnotes_ordered); + unset($this->footnotes_ordered[$note_id]); + $ref_count = $this->footnotes_ref_count[$note_id]; + unset($this->footnotes_ref_count[$note_id]); + unset($this->footnotes[$note_id]); + + $footnote .= "\n"; # Need to append newline before parsing. + $footnote = $this->runBlockGamut("$footnote\n"); + $footnote = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', + array(&$this, '_appendFootnotes_callback'), $footnote); + + $attr = str_replace("%%", ++$num, $attr); + $note_id = $this->encodeAttribute($note_id); + + # Prepare backlink, multiple backlinks if multiple references + $backlink = ""; + for ($ref_num = 2; $ref_num <= $ref_count; ++$ref_num) { + $backlink .= " "; + } + # Add backlink to last paragraph; create new paragraph if needed. + if (preg_match('{

      $}', $footnote)) { + $footnote = substr($footnote, 0, -4) . " $backlink

      "; + } else { + $footnote .= "\n\n

      $backlink

      "; + } + + $text .= "
    1. \n"; + $text .= $footnote . "\n"; + $text .= "
    2. \n\n"; + } + + $text .= "
    \n"; + $text .= "
    "; + } + return $text; + } + function _appendFootnotes_callback($matches) { + $node_id = $this->fn_id_prefix . $matches[1]; + + # Create footnote marker only if it has a corresponding footnote *and* + # the footnote hasn't been used by another marker. + if (isset($this->footnotes[$node_id])) { + $num =& $this->footnotes_numbers[$node_id]; + if (!isset($num)) { + # Transfer footnote content to the ordered list and give it its + # number + $this->footnotes_ordered[$node_id] = $this->footnotes[$node_id]; + $this->footnotes_ref_count[$node_id] = 1; + $num = $this->footnote_counter++; + $ref_count_mark = ''; + } else { + $ref_count_mark = $this->footnotes_ref_count[$node_id] += 1; + } + + $attr = " rel=\"footnote\""; + if ($this->fn_link_class != "") { + $class = $this->fn_link_class; + $class = $this->encodeAttribute($class); + $attr .= " class=\"$class\""; + } + if ($this->fn_link_title != "") { + $title = $this->fn_link_title; + $title = $this->encodeAttribute($title); + $attr .= " title=\"$title\""; + } + + $attr = str_replace("%%", $num, $attr); + $node_id = $this->encodeAttribute($node_id); + + return + "". + "$num". + ""; + } + + return "[^".$matches[1]."]"; + } + + + ### Abbreviations ### + + function stripAbbreviations($text) { + # + # Strips abbreviations from text, stores titles in hash references. + # + $less_than_tab = $this->tab_width - 1; + + # Link defs are in the form: [id]*: url "optional title" + $text = preg_replace_callback('{ + ^[ ]{0,'.$less_than_tab.'}\*\[(.+?)\][ ]?: # abbr_id = $1 + (.*) # text = $2 (no blank lines allowed) + }xm', + array(&$this, '_stripAbbreviations_callback'), + $text); + return $text; + } + function _stripAbbreviations_callback($matches) { + $abbr_word = $matches[1]; + $abbr_desc = $matches[2]; + if ($this->abbr_word_re) + $this->abbr_word_re .= '|'; + $this->abbr_word_re .= preg_quote($abbr_word); + $this->abbr_desciptions[$abbr_word] = trim($abbr_desc); + return ''; # String that will replace the block + } + + + function doAbbreviations($text) { + # + # Find defined abbreviations in text and wrap them in elements. + # + if ($this->abbr_word_re) { + // cannot use the /x modifier because abbr_word_re may + // contain significant spaces: + $text = preg_replace_callback('{'. + '(?abbr_word_re.')'. + '(?![\w\x1A])'. + '}', + array(&$this, '_doAbbreviations_callback'), $text); + } + return $text; + } + function _doAbbreviations_callback($matches) { + $abbr = $matches[0]; + if (isset($this->abbr_desciptions[$abbr])) { + $desc = $this->abbr_desciptions[$abbr]; + if (empty($desc)) { + return $this->hashPart("$abbr"); + } else { + $desc = $this->encodeAttribute($desc); + return $this->hashPart("$abbr"); + } + } else { + return $matches[0]; + } + } + +} + + +/* + +PHP Markdown Extra +================== + +Description +----------- + +This is a PHP port of the original Markdown formatter written in Perl +by John Gruber. This special "Extra" version of PHP Markdown features +further enhancements to the syntax for making additional constructs +such as tables and definition list. + +Markdown is a text-to-HTML filter; it translates an easy-to-read / +easy-to-write structured text format into HTML. Markdown's text format +is mostly similar to that of plain text email, and supports features such +as headers, *emphasis*, code blocks, blockquotes, and links. + +Markdown's syntax is designed not as a generic markup language, but +specifically to serve as a front-end to (X)HTML. You can use span-level +HTML tags anywhere in a Markdown document, and you can use block level +HTML tags (like
    and as well). + +For more information about Markdown's syntax, see: + + + + +Bugs +---- + +To file bug reports please send email to: + + + +Please include with your report: (1) the example input; (2) the output you +expected; (3) the output Markdown actually produced. + + +Version History +--------------- + +See the readme file for detailed release notes for this version. + + +Copyright and License +--------------------- + +PHP Markdown & Extra +Copyright (c) 2004-2013 Michel Fortin + +All rights reserved. + +Based on Markdown +Copyright (c) 2003-2006 John Gruber + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +* Neither the name "Markdown" nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +This software is provided by the copyright holders and contributors "as +is" and any express or implied warranties, including, but not limited +to, the implied warranties of merchantability and fitness for a +particular purpose are disclaimed. In no event shall the copyright owner +or contributors be liable for any direct, indirect, incidental, special, +exemplary, or consequential damages (including, but not limited to, +procurement of substitute goods or services; loss of use, data, or +profits; or business interruption) however caused and on any theory of +liability, whether in contract, strict liability, or tort (including +negligence or otherwise) arising in any way out of the use of this +software, even if advised of the possibility of such damage. + +*/ +?> diff --git a/pluf/src/Pluf/Text/MarkDown.php.old b/pluf/src/Pluf/Text/MarkDown.php.old new file mode 100644 index 0000000..3b91c3e --- /dev/null +++ b/pluf/src/Pluf/Text/MarkDown.php.old @@ -0,0 +1,2792 @@ + +# +# Original Markdown +# Copyright (c) 2004-2006 John Gruber +# +# + + +define( 'MARKDOWN_VERSION', "1.0.1o" ); # Sun 8 Jan 2012 +define( 'MARKDOWNEXTRA_VERSION', "1.2.5" ); # Sun 8 Jan 2012 + + +# +# Global default settings: +# + +# Change to ">" for HTML output +@define( 'MARKDOWN_EMPTY_ELEMENT_SUFFIX', " />"); + +# Define the width of a tab for code blocks. +@define( 'MARKDOWN_TAB_WIDTH', 4 ); + +# Optional title attribute for footnote links and backlinks. +@define( 'MARKDOWN_FN_LINK_TITLE', "" ); +@define( 'MARKDOWN_FN_BACKLINK_TITLE', "" ); + +# Optional class attribute for footnote links and backlinks. +@define( 'MARKDOWN_FN_LINK_CLASS', "" ); +@define( 'MARKDOWN_FN_BACKLINK_CLASS', "" ); + + +# +# WordPress settings: +# + +# Change to false to remove Markdown from posts and/or comments. +@define( 'MARKDOWN_WP_POSTS', true ); +@define( 'MARKDOWN_WP_COMMENTS', true ); + + + +### Standard Function Interface ### + +@define( 'MARKDOWN_PARSER_CLASS', 'MarkdownExtra_Parser' ); + +function Markdown($text) { +# +# Initialize the parser and return the result of its transform method. +# + # Setup static parser variable. + static $parser; + if (!isset($parser)) { + $parser_class = MARKDOWN_PARSER_CLASS; + $parser = new $parser_class; + } + + # Transform text using parser. + return $parser->transform($text); +} + +function Pluf_Text_MarkDown_parse($text) { + return Markdown($text); +} + +# +# Markdown Parser Class +# + +class Markdown_Parser { + + # Regex to match balanced [brackets]. + # Needed to insert a maximum bracked depth while converting to PHP. + var $nested_brackets_depth = 6; + var $nested_brackets_re; + + var $nested_url_parenthesis_depth = 4; + var $nested_url_parenthesis_re; + + # Table of hash values for escaped characters: + var $escape_chars = '\`*_{}[]()>#+-.!'; + var $escape_chars_re; + + # Change to ">" for HTML output. + var $empty_element_suffix = MARKDOWN_EMPTY_ELEMENT_SUFFIX; + var $tab_width = MARKDOWN_TAB_WIDTH; + + # Change to `true` to disallow markup or entities. + var $no_markup = false; + var $no_entities = false; + + # Predefined urls and titles for reference links and images. + var $predef_urls = array(); + var $predef_titles = array(); + + + function Markdown_Parser() { + # + # Constructor function. Initialize appropriate member variables. + # + $this->_initDetab(); + $this->prepareItalicsAndBold(); + + $this->nested_brackets_re = + str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth). + str_repeat('\])*', $this->nested_brackets_depth); + + $this->nested_url_parenthesis_re = + str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth). + str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth); + + $this->escape_chars_re = '['.preg_quote($this->escape_chars).']'; + + # Sort document, block, and span gamut in ascendent priority order. + asort($this->document_gamut); + asort($this->block_gamut); + asort($this->span_gamut); + } + + + # Internal hashes used during transformation. + var $urls = array(); + var $titles = array(); + var $html_hashes = array(); + + # Status flag to avoid invalid nesting. + var $in_anchor = false; + + + function setup() { + # + # Called before the transformation process starts to setup parser + # states. + # + # Clear global hashes. + $this->urls = $this->predef_urls; + $this->titles = $this->predef_titles; + $this->html_hashes = array(); + + $in_anchor = false; + } + + function teardown() { + # + # Called after the transformation process to clear any variable + # which may be taking up memory unnecessarly. + # + $this->urls = array(); + $this->titles = array(); + $this->html_hashes = array(); + } + + + function transform($text) { + # + # Main function. Performs some preprocessing on the input text + # and pass it through the document gamut. + # + $this->setup(); + + # Remove UTF-8 BOM and marker character in input, if present. + $text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text); + + # Standardize line endings: + # DOS to Unix and Mac to Unix + $text = preg_replace('{\r\n?}', "\n", $text); + + # Make sure $text ends with a couple of newlines: + $text .= "\n\n"; + + # Convert all tabs to spaces. + $text = $this->detab($text); + + # Turn block-level HTML blocks into hash entries + $text = $this->hashHTMLBlocks($text); + + # Strip any lines consisting only of spaces and tabs. + # This makes subsequent regexen easier to write, because we can + # match consecutive blank lines with /\n+/ instead of something + # contorted like /[ ]*\n+/ . + $text = preg_replace('/^[ ]+$/m', '', $text); + + # Run document gamut methods. + foreach ($this->document_gamut as $method => $priority) { + $text = $this->$method($text); + } + + $this->teardown(); + + return $text . "\n"; + } + + var $document_gamut = array( + # Strip link definitions, store in hashes. + "stripLinkDefinitions" => 20, + + "runBasicBlockGamut" => 30, + ); + + + function stripLinkDefinitions($text) { + # + # Strips link definitions from text, stores the URLs and titles in + # hash references. + # + $less_than_tab = $this->tab_width - 1; + + # Link defs are in the form: ^[id]: url "optional title" + $text = preg_replace_callback('{ + ^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?: # id = $1 + [ ]* + \n? # maybe *one* newline + [ ]* + (?: + <(.+?)> # url = $2 + | + (\S+?) # url = $3 + ) + [ ]* + \n? # maybe one newline + [ ]* + (?: + (?<=\s) # lookbehind for whitespace + ["(] + (.*?) # title = $4 + [")] + [ ]* + )? # title is optional + (?:\n+|\Z) + }xm', + array(&$this, '_stripLinkDefinitions_callback'), + $text); + return $text; + } + function _stripLinkDefinitions_callback($matches) { + $link_id = strtolower($matches[1]); + $url = $matches[2] == '' ? $matches[3] : $matches[2]; + $this->urls[$link_id] = $url; + $this->titles[$link_id] =& $matches[4]; + return ''; # String that will replace the block + } + + + function hashHTMLBlocks($text) { + if ($this->no_markup) return $text; + + $less_than_tab = $this->tab_width - 1; + + # Hashify HTML blocks: + # We only want to do this for block-level HTML tags, such as headers, + # lists, and tables. That's because we still want to wrap

    s around + # "paragraphs" that are wrapped in non-block-level tags, such as anchors, + # phrase emphasis, and spans. The list of tags we're looking for is + # hard-coded: + # + # * List "a" is made of tags which can be both inline or block-level. + # These will be treated block-level when the start tag is alone on + # its line, otherwise they're not matched here and will be taken as + # inline later. + # * List "b" is made of tags which are always block-level; + # + $block_tags_a_re = 'ins|del'; + $block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'. + 'script|noscript|form|fieldset|iframe|math'; + + # Regular expression for the content of a block tag. + $nested_tags_level = 4; + $attr = ' + (?> # optional tag attributes + \s # starts with whitespace + (?> + [^>"/]+ # text outside quotes + | + /+(?!>) # slash not followed by ">" + | + "[^"]*" # text inside double quotes (tolerate ">") + | + \'[^\']*\' # text inside single quotes (tolerate ">") + )* + )? + '; + $content = + str_repeat(' + (?> + [^<]+ # content without tag + | + <\2 # nested opening tag + '.$attr.' # attributes + (?> + /> + | + >', $nested_tags_level). # end of opening tag + '.*?'. # last level nested tag content + str_repeat(' + # closing nested tag + ) + | + <(?!/\2\s*> # other tags with a different name + ) + )*', + $nested_tags_level); + $content2 = str_replace('\2', '\3', $content); + + # First, look for nested blocks, e.g.: + #

    + #
    + # tags for inner block must be indented. + #
    + #
    + # + # The outermost tags must start at the left margin for this to match, and + # the inner nested divs must be indented. + # We need to do this before the next, more liberal match, because the next + # match will start at the first `
    ` and stop at the first `
    `. + $text = preg_replace_callback('{(?> + (?> + (?<=\n\n) # Starting after a blank line + | # or + \A\n? # the beginning of the doc + ) + ( # save in $1 + + # Match from `\n` to `\n`, handling nested tags + # in between. + + [ ]{0,'.$less_than_tab.'} + <('.$block_tags_b_re.')# start tag = $2 + '.$attr.'> # attributes followed by > and \n + '.$content.' # content, support nesting + # the matching end tag + [ ]* # trailing spaces/tabs + (?=\n+|\Z) # followed by a newline or end of document + + | # Special version for tags of group a. + + [ ]{0,'.$less_than_tab.'} + <('.$block_tags_a_re.')# start tag = $3 + '.$attr.'>[ ]*\n # attributes followed by > + '.$content2.' # content, support nesting + # the matching end tag + [ ]* # trailing spaces/tabs + (?=\n+|\Z) # followed by a newline or end of document + + | # Special case just for
    . It was easier to make a special + # case than to make the other regex more complicated. + + [ ]{0,'.$less_than_tab.'} + <(hr) # start tag = $2 + '.$attr.' # attributes + /?> # the matching end tag + [ ]* + (?=\n{2,}|\Z) # followed by a blank line or end of document + + | # Special case for standalone HTML comments: + + [ ]{0,'.$less_than_tab.'} + (?s: + + ) + [ ]* + (?=\n{2,}|\Z) # followed by a blank line or end of document + + | # PHP and ASP-style processor instructions ( + ) + [ ]* + (?=\n{2,}|\Z) # followed by a blank line or end of document + + ) + )}Sxmi', + array(&$this, '_hashHTMLBlocks_callback'), + $text); + + return $text; + } + function _hashHTMLBlocks_callback($matches) { + $text = $matches[1]; + $key = $this->hashBlock($text); + return "\n\n$key\n\n"; + } + + + function hashPart($text, $boundary = 'X') { + # + # Called whenever a tag must be hashed when a function insert an atomic + # element in the text stream. Passing $text to through this function gives + # a unique text-token which will be reverted back when calling unhash. + # + # The $boundary argument specify what character should be used to surround + # the token. By convension, "B" is used for block elements that needs not + # to be wrapped into paragraph tags at the end, ":" is used for elements + # that are word separators and "X" is used in the general case. + # + # Swap back any tag hash found in $text so we do not have to `unhash` + # multiple times at the end. + $text = $this->unhash($text); + + # Then hash the block. + static $i = 0; + $key = "$boundary\x1A" . ++$i . $boundary; + $this->html_hashes[$key] = $text; + return $key; # String that will replace the tag. + } + + + function hashBlock($text) { + # + # Shortcut function for hashPart with block-level boundaries. + # + return $this->hashPart($text, 'B'); + } + + + var $block_gamut = array( + # + # These are all the transformations that form block-level + # tags like paragraphs, headers, and list items. + # + "doHeaders" => 10, + "doHorizontalRules" => 20, + + "doLists" => 40, + "doCodeBlocks" => 50, + "doBlockQuotes" => 60, + ); + + function runBlockGamut($text) { + # + # Run block gamut tranformations. + # + # We need to escape raw HTML in Markdown source before doing anything + # else. This need to be done for each block, and not only at the + # begining in the Markdown function since hashed blocks can be part of + # list items and could have been indented. Indented blocks would have + # been seen as a code block in a previous pass of hashHTMLBlocks. + $text = $this->hashHTMLBlocks($text); + + return $this->runBasicBlockGamut($text); + } + + function runBasicBlockGamut($text) { + # + # Run block gamut tranformations, without hashing HTML blocks. This is + # useful when HTML blocks are known to be already hashed, like in the first + # whole-document pass. + # + foreach ($this->block_gamut as $method => $priority) { + $text = $this->$method($text); + } + + # Finally form paragraph and restore hashed blocks. + $text = $this->formParagraphs($text); + + return $text; + } + + + function doHorizontalRules($text) { + # Do Horizontal Rules: + return preg_replace( + '{ + ^[ ]{0,3} # Leading space + ([-*_]) # $1: First marker + (?> # Repeated marker group + [ ]{0,2} # Zero, one, or two spaces. + \1 # Marker character + ){2,} # Group repeated at least twice + [ ]* # Tailing spaces + $ # End of line. + }mx', + "\n".$this->hashBlock("empty_element_suffix")."\n", + $text); + } + + + var $span_gamut = array( + # + # These are all the transformations that occur *within* block-level + # tags like paragraphs, headers, and list items. + # + # Process character escapes, code spans, and inline HTML + # in one shot. + "parseSpan" => -30, + + # Process anchor and image tags. Images must come first, + # because ![foo][f] looks like an anchor. + "doImages" => 10, + "doAnchors" => 20, + + # Make links out of things like `` + # Must come after doAnchors, because you can use < and > + # delimiters in inline links like [this](). + "doAutoLinks" => 30, + "encodeAmpsAndAngles" => 40, + + "doItalicsAndBold" => 50, + "doHardBreaks" => 60, + ); + + function runSpanGamut($text) { + # + # Run span gamut tranformations. + # + foreach ($this->span_gamut as $method => $priority) { + $text = $this->$method($text); + } + + return $text; + } + + + function doHardBreaks($text) { + # Do hard breaks: + return preg_replace_callback('/ {2,}\n/', + array(&$this, '_doHardBreaks_callback'), $text); + } + function _doHardBreaks_callback($matches) { + return $this->hashPart("empty_element_suffix\n"); + } + + + function doAnchors($text) { + # + # Turn Markdown link shortcuts into XHTML tags. + # + if ($this->in_anchor) return $text; + $this->in_anchor = true; + + # + # First, handle reference-style links: [link text] [id] + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + \[ + ('.$this->nested_brackets_re.') # link text = $2 + \] + + [ ]? # one optional space + (?:\n[ ]*)? # one optional newline followed by spaces + + \[ + (.*?) # id = $3 + \] + ) + }xs', + array(&$this, '_doAnchors_reference_callback'), $text); + + # + # Next, inline-style links: [link text](url "optional title") + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + \[ + ('.$this->nested_brackets_re.') # link text = $2 + \] + \( # literal paren + [ \n]* + (?: + <(.+?)> # href = $3 + | + ('.$this->nested_url_parenthesis_re.') # href = $4 + ) + [ \n]* + ( # $5 + ([\'"]) # quote char = $6 + (.*?) # Title = $7 + \6 # matching quote + [ \n]* # ignore any spaces/tabs between closing quote and ) + )? # title is optional + \) + ) + }xs', + array(&$this, '_doAnchors_inline_callback'), $text); + + # + # Last, handle reference-style shortcuts: [link text] + # These must come last in case you've also got [link text][1] + # or [link text](/foo) + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + \[ + ([^\[\]]+) # link text = $2; can\'t contain [ or ] + \] + ) + }xs', + array(&$this, '_doAnchors_reference_callback'), $text); + + $this->in_anchor = false; + return $text; + } + function _doAnchors_reference_callback($matches) { + $whole_match = $matches[1]; + $link_text = $matches[2]; + $link_id =& $matches[3]; + + if ($link_id == "") { + # for shortcut links like [this][] or [this]. + $link_id = $link_text; + } + + # lower-case and turn embedded newlines into spaces + $link_id = strtolower($link_id); + $link_id = preg_replace('{[ ]?\n}', ' ', $link_id); + + if (isset($this->urls[$link_id])) { + $url = $this->urls[$link_id]; + $url = $this->encodeAttribute($url); + + $result = "titles[$link_id] ) ) { + $title = $this->titles[$link_id]; + $title = $this->encodeAttribute($title); + $result .= " title=\"$title\""; + } + + $link_text = $this->runSpanGamut($link_text); + $result .= ">$link_text"; + $result = $this->hashPart($result); + } + else { + $result = $whole_match; + } + return $result; + } + function _doAnchors_inline_callback($matches) { + $whole_match = $matches[1]; + $link_text = $this->runSpanGamut($matches[2]); + $url = $matches[3] == '' ? $matches[4] : $matches[3]; + $title =& $matches[7]; + + $url = $this->encodeAttribute($url); + + $result = "encodeAttribute($title); + $result .= " title=\"$title\""; + } + + $link_text = $this->runSpanGamut($link_text); + $result .= ">$link_text"; + + return $this->hashPart($result); + } + + + function doImages($text) { + # + # Turn Markdown image shortcuts into tags. + # + # + # First, handle reference-style labeled images: ![alt text][id] + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + !\[ + ('.$this->nested_brackets_re.') # alt text = $2 + \] + + [ ]? # one optional space + (?:\n[ ]*)? # one optional newline followed by spaces + + \[ + (.*?) # id = $3 + \] + + ) + }xs', + array(&$this, '_doImages_reference_callback'), $text); + + # + # Next, handle inline images: ![alt text](url "optional title") + # Don't forget: encode * and _ + # + $text = preg_replace_callback('{ + ( # wrap whole match in $1 + !\[ + ('.$this->nested_brackets_re.') # alt text = $2 + \] + \s? # One optional whitespace character + \( # literal paren + [ \n]* + (?: + <(\S*)> # src url = $3 + | + ('.$this->nested_url_parenthesis_re.') # src url = $4 + ) + [ \n]* + ( # $5 + ([\'"]) # quote char = $6 + (.*?) # title = $7 + \6 # matching quote + [ \n]* + )? # title is optional + \) + ) + }xs', + array(&$this, '_doImages_inline_callback'), $text); + + return $text; + } + function _doImages_reference_callback($matches) { + $whole_match = $matches[1]; + $alt_text = $matches[2]; + $link_id = strtolower($matches[3]); + + if ($link_id == "") { + $link_id = strtolower($alt_text); # for shortcut links like ![this][]. + } + + $alt_text = $this->encodeAttribute($alt_text); + if (isset($this->urls[$link_id])) { + $url = $this->encodeAttribute($this->urls[$link_id]); + $result = "\"$alt_text\"";titles[$link_id])) { + $title = $this->titles[$link_id]; + $title = $this->encodeAttribute($title); + $result .= " title=\"$title\""; + } + $result .= $this->empty_element_suffix; + $result = $this->hashPart($result); + } + else { + # If there's no such link ID, leave intact: + $result = $whole_match; + } + + return $result; + } + function _doImages_inline_callback($matches) { + $whole_match = $matches[1]; + $alt_text = $matches[2]; + $url = $matches[3] == '' ? $matches[4] : $matches[3]; + $title =& $matches[7]; + + $alt_text = $this->encodeAttribute($alt_text); + $url = $this->encodeAttribute($url); + $result = "\"$alt_text\"";encodeAttribute($title); + $result .= " title=\"$title\""; # $title already quoted + } + $result .= $this->empty_element_suffix; + + return $this->hashPart($result); + } + + + function doHeaders($text) { + # Setext-style headers: + # Header 1 + # ======== + # + # Header 2 + # -------- + # + $text = preg_replace_callback('{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx', + array(&$this, '_doHeaders_callback_setext'), $text); + + # atx-style headers: + # # Header 1 + # ## Header 2 + # ## Header 2 with closing hashes ## + # ... + # ###### Header 6 + # + $text = preg_replace_callback('{ + ^(\#{1,6}) # $1 = string of #\'s + [ ]* + (.+?) # $2 = Header text + [ ]* + \#* # optional closing #\'s (not counted) + \n+ + }xm', + array(&$this, '_doHeaders_callback_atx'), $text); + + return $text; + } + function _doHeaders_callback_setext($matches) { + # Terrible hack to check we haven't found an empty list item. + if ($matches[2] == '-' && preg_match('{^-(?: |$)}', $matches[1])) + return $matches[0]; + + $level = $matches[2]{0} == '=' ? 1 : 2; + $block = "".$this->runSpanGamut($matches[1]).""; + return "\n" . $this->hashBlock($block) . "\n\n"; + } + function _doHeaders_callback_atx($matches) { + $level = strlen($matches[1]); + $block = "".$this->runSpanGamut($matches[2]).""; + return "\n" . $this->hashBlock($block) . "\n\n"; + } + + + function doLists($text) { + # + # Form HTML ordered (numbered) and unordered (bulleted) lists. + # + $less_than_tab = $this->tab_width - 1; + + # Re-usable patterns to match list item bullets and number markers: + $marker_ul_re = '[*+-]'; + $marker_ol_re = '\d+[\.]'; + $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)"; + + $markers_relist = array( + $marker_ul_re => $marker_ol_re, + $marker_ol_re => $marker_ul_re, + ); + + foreach ($markers_relist as $marker_re => $other_marker_re) { + # Re-usable pattern to match any entirel ul or ol list: + $whole_list_re = ' + ( # $1 = whole list + ( # $2 + ([ ]{0,'.$less_than_tab.'}) # $3 = number of spaces + ('.$marker_re.') # $4 = first list item marker + [ ]+ + ) + (?s:.+?) + ( # $5 + \z + | + \n{2,} + (?=\S) + (?! # Negative lookahead for another list item marker + [ ]* + '.$marker_re.'[ ]+ + ) + | + (?= # Lookahead for another kind of list + \n + \3 # Must have the same indentation + '.$other_marker_re.'[ ]+ + ) + ) + ) + '; // mx + + # We use a different prefix before nested lists than top-level lists. + # See extended comment in _ProcessListItems(). + + if ($this->list_level) { + $text = preg_replace_callback('{ + ^ + '.$whole_list_re.' + }mx', + array(&$this, '_doLists_callback'), $text); + } + else { + $text = preg_replace_callback('{ + (?:(?<=\n)\n|\A\n?) # Must eat the newline + '.$whole_list_re.' + }mx', + array(&$this, '_doLists_callback'), $text); + } + } + + return $text; + } + function _doLists_callback($matches) { + # Re-usable patterns to match list item bullets and number markers: + $marker_ul_re = '[*+-]'; + $marker_ol_re = '\d+[\.]'; + $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)"; + + $list = $matches[1]; + $list_type = preg_match("/$marker_ul_re/", $matches[4]) ? "ul" : "ol"; + + $marker_any_re = ( $list_type == "ul" ? $marker_ul_re : $marker_ol_re ); + + $list .= "\n"; + $result = $this->processListItems($list, $marker_any_re); + + $result = $this->hashBlock("<$list_type>\n" . $result . ""); + return "\n". $result ."\n\n"; + } + + var $list_level = 0; + + function processListItems($list_str, $marker_any_re) { + # + # Process the contents of a single ordered or unordered list, splitting it + # into individual list items. + # + # The $this->list_level global keeps track of when we're inside a list. + # Each time we enter a list, we increment it; when we leave a list, + # we decrement. If it's zero, we're not in a list anymore. + # + # We do this because when we're not inside a list, we want to treat + # something like this: + # + # I recommend upgrading to version + # 8. Oops, now this line is treated + # as a sub-list. + # + # As a single paragraph, despite the fact that the second line starts + # with a digit-period-space sequence. + # + # Whereas when we're inside a list (or sub-list), that line will be + # treated as the start of a sub-list. What a kludge, huh? This is + # an aspect of Markdown's syntax that's hard to parse perfectly + # without resorting to mind-reading. Perhaps the solution is to + # change the syntax rules such that sub-lists must start with a + # starting cardinal number; e.g. "1." or "a.". + + $this->list_level++; + + # trim trailing blank lines: + $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str); + + $list_str = preg_replace_callback('{ + (\n)? # leading line = $1 + (^[ ]*) # leading whitespace = $2 + ('.$marker_any_re.' # list marker and space = $3 + (?:[ ]+|(?=\n)) # space only required if item is not empty + ) + ((?s:.*?)) # list item text = $4 + (?:(\n+(?=\n))|\n) # tailing blank line = $5 + (?= \n* (\z | \2 ('.$marker_any_re.') (?:[ ]+|(?=\n)))) + }xm', + array(&$this, '_processListItems_callback'), $list_str); + + $this->list_level--; + return $list_str; + } + function _processListItems_callback($matches) { + $item = $matches[4]; + $leading_line =& $matches[1]; + $leading_space =& $matches[2]; + $marker_space = $matches[3]; + $tailing_blank_line =& $matches[5]; + + if ($leading_line || $tailing_blank_line || + preg_match('/\n{2,}/', $item)) + { + # Replace marker with the appropriate whitespace indentation + $item = $leading_space . str_repeat(' ', strlen($marker_space)) . $item; + $item = $this->runBlockGamut($this->outdent($item)."\n"); + } + else { + # Recursion for sub-lists: + $item = $this->doLists($this->outdent($item)); + $item = preg_replace('/\n+$/', '', $item); + $item = $this->runSpanGamut($item); + } + + return "
  • " . $item . "
  • \n"; + } + + + function doCodeBlocks($text) { + # + # Process Markdown `
    ` blocks.
    +	#
    +		$text = preg_replace_callback('{
    +				(?:\n\n|\A\n?)
    +				(	            # $1 = the code block -- one or more lines, starting with a space/tab
    +				  (?>
    +					[ ]{'.$this->tab_width.'}  # Lines must start with a tab or a tab-width of spaces
    +					.*\n+
    +				  )+
    +				)
    +				((?=^[ ]{0,'.$this->tab_width.'}\S)|\Z)	# Lookahead for non-space at line-start, or end of doc
    +			}xm',
    +			array(&$this, '_doCodeBlocks_callback'), $text);
    +
    +		return $text;
    +	}
    +	function _doCodeBlocks_callback($matches) {
    +		$codeblock = $matches[1];
    +
    +		$codeblock = $this->outdent($codeblock);
    +		$codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
    +
    +		# trim leading newlines and trailing newlines
    +		$codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock);
    +
    +		$codeblock = "
    $codeblock\n
    "; + return "\n\n".$this->hashBlock($codeblock)."\n\n"; + } + + + function makeCodeSpan($code) { + # + # Create a code span markup for $code. Called from handleSpanToken. + # + $code = htmlspecialchars(trim($code), ENT_NOQUOTES); + return $this->hashPart("$code"); + } + + + var $em_relist = array( + '' => '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(?em_relist as $em => $em_re) { + foreach ($this->strong_relist as $strong => $strong_re) { + # Construct list of allowed token expressions. + $token_relist = array(); + if (isset($this->em_strong_relist["$em$strong"])) { + $token_relist[] = $this->em_strong_relist["$em$strong"]; + } + $token_relist[] = $em_re; + $token_relist[] = $strong_re; + + # Construct master expression from list. + $token_re = '{('. implode('|', $token_relist) .')}'; + $this->em_strong_prepared_relist["$em$strong"] = $token_re; + } + } + } + + function doItalicsAndBold($text) { + $token_stack = array(''); + $text_stack = array(''); + $em = ''; + $strong = ''; + $tree_char_em = false; + + while (1) { + # + # Get prepared regular expression for seraching emphasis tokens + # in current context. + # + $token_re = $this->em_strong_prepared_relist["$em$strong"]; + + # + # Each loop iteration search for the next emphasis token. + # Each token is then passed to handleSpanToken. + # + $parts = preg_split($token_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE); + $text_stack[0] .= $parts[0]; + $token =& $parts[1]; + $text =& $parts[2]; + + if (empty($token)) { + # Reached end of text span: empty stack without emitting. + # any more emphasis. + while ($token_stack[0]) { + $text_stack[1] .= array_shift($token_stack); + $text_stack[0] .= array_shift($text_stack); + } + break; + } + + $token_len = strlen($token); + if ($tree_char_em) { + # Reached closing marker while inside a three-char emphasis. + if ($token_len == 3) { + # Three-char closing marker, close em and strong. + array_shift($token_stack); + $span = array_shift($text_stack); + $span = $this->runSpanGamut($span); + $span = "$span"; + $text_stack[0] .= $this->hashPart($span); + $em = ''; + $strong = ''; + } else { + # Other closing marker: close one em or strong and + # change current token state to match the other + $token_stack[0] = str_repeat($token{0}, 3-$token_len); + $tag = $token_len == 2 ? "strong" : "em"; + $span = $text_stack[0]; + $span = $this->runSpanGamut($span); + $span = "<$tag>$span"; + $text_stack[0] = $this->hashPart($span); + $$tag = ''; # $$tag stands for $em or $strong + } + $tree_char_em = false; + } else if ($token_len == 3) { + if ($em) { + # Reached closing marker for both em and strong. + # Closing strong marker: + for ($i = 0; $i < 2; ++$i) { + $shifted_token = array_shift($token_stack); + $tag = strlen($shifted_token) == 2 ? "strong" : "em"; + $span = array_shift($text_stack); + $span = $this->runSpanGamut($span); + $span = "<$tag>$span"; + $text_stack[0] .= $this->hashPart($span); + $$tag = ''; # $$tag stands for $em or $strong + } + } else { + # Reached opening three-char emphasis marker. Push on token + # stack; will be handled by the special condition above. + $em = $token{0}; + $strong = "$em$em"; + array_unshift($token_stack, $token); + array_unshift($text_stack, ''); + $tree_char_em = true; + } + } else if ($token_len == 2) { + if ($strong) { + # Unwind any dangling emphasis marker: + if (strlen($token_stack[0]) == 1) { + $text_stack[1] .= array_shift($token_stack); + $text_stack[0] .= array_shift($text_stack); + } + # Closing strong marker: + array_shift($token_stack); + $span = array_shift($text_stack); + $span = $this->runSpanGamut($span); + $span = "$span"; + $text_stack[0] .= $this->hashPart($span); + $strong = ''; + } else { + array_unshift($token_stack, $token); + array_unshift($text_stack, ''); + $strong = $token; + } + } else { + # Here $token_len == 1 + if ($em) { + if (strlen($token_stack[0]) == 1) { + # Closing emphasis marker: + array_shift($token_stack); + $span = array_shift($text_stack); + $span = $this->runSpanGamut($span); + $span = "$span"; + $text_stack[0] .= $this->hashPart($span); + $em = ''; + } else { + $text_stack[0] .= $token; + } + } else { + array_unshift($token_stack, $token); + array_unshift($text_stack, ''); + $em = $token; + } + } + } + return $text_stack[0]; + } + + + function doBlockQuotes($text) { + $text = preg_replace_callback('/ + ( # Wrap whole match in $1 + (?> + ^[ ]*>[ ]? # ">" at the start of a line + .+\n # rest of the first line + (.+\n)* # subsequent consecutive lines + \n* # blanks + )+ + ) + /xm', + array(&$this, '_doBlockQuotes_callback'), $text); + + return $text; + } + function _doBlockQuotes_callback($matches) { + $bq = $matches[1]; + # trim one level of quoting - trim whitespace-only lines + $bq = preg_replace('/^[ ]*>[ ]?|^[ ]+$/m', '', $bq); + $bq = $this->runBlockGamut($bq); # recurse + + $bq = preg_replace('/^/m', " ", $bq); + # These leading spaces cause problem with
     content, 
    +		# so we need to fix that:
    +		$bq = preg_replace_callback('{(\s*
    .+?
    )}sx', + array(&$this, '_doBlockQuotes_callback2'), $bq); + + return "\n". $this->hashBlock("
    \n$bq\n
    ")."\n\n"; + } + function _doBlockQuotes_callback2($matches) { + $pre = $matches[1]; + $pre = preg_replace('/^ /m', '', $pre); + return $pre; + } + + + function formParagraphs($text) { + # + # Params: + # $text - string to process with html

    tags + # + # Strip leading and trailing lines: + $text = preg_replace('/\A\n+|\n+\z/', '', $text); + + $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY); + + # + # Wrap

    tags and unhashify HTML blocks + # + foreach ($grafs as $key => $value) { + if (!preg_match('/^B\x1A[0-9]+B$/', $value)) { + # Is a paragraph. + $value = $this->runSpanGamut($value); + $value = preg_replace('/^([ ]*)/', "

    ", $value); + $value .= "

    "; + $grafs[$key] = $this->unhash($value); + } + else { + # Is a block. + # Modify elements of @grafs in-place... + $graf = $value; + $block = $this->html_hashes[$graf]; + $graf = $block; +// if (preg_match('{ +// \A +// ( # $1 =
    tag +//
    ]* +// \b +// markdown\s*=\s* ([\'"]) # $2 = attr quote char +// 1 +// \2 +// [^>]* +// > +// ) +// ( # $3 = contents +// .* +// ) +// (
    ) # $4 = closing tag +// \z +// }xs', $block, $matches)) +// { +// list(, $div_open, , $div_content, $div_close) = $matches; +// +// # We can't call Markdown(), because that resets the hash; +// # that initialization code should be pulled into its own sub, though. +// $div_content = $this->hashHTMLBlocks($div_content); +// +// # Run document gamut methods on the content. +// foreach ($this->document_gamut as $method => $priority) { +// $div_content = $this->$method($div_content); +// } +// +// $div_open = preg_replace( +// '{\smarkdown\s*=\s*([\'"]).+?\1}', '', $div_open); +// +// $graf = $div_open . "\n" . $div_content . "\n" . $div_close; +// } + $grafs[$key] = $graf; + } + } + + return implode("\n\n", $grafs); + } + + + function encodeAttribute($text) { + # + # Encode text for a double-quoted HTML attribute. This function + # is *not* suitable for attributes enclosed in single quotes. + # + $text = $this->encodeAmpsAndAngles($text); + $text = str_replace('"', '"', $text); + return $text; + } + + + function encodeAmpsAndAngles($text) { + # + # Smart processing for ampersands and angle brackets that need to + # be encoded. Valid character entities are left alone unless the + # no-entities mode is set. + # + if ($this->no_entities) { + $text = str_replace('&', '&', $text); + } else { + # Ampersand-encoding based entirely on Nat Irons's Amputator + # MT plugin: + $text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/', + '&', $text);; + } + # Encode remaining <'s + $text = str_replace('<', '<', $text); + + return $text; + } + + + function doAutoLinks($text) { + $text = preg_replace_callback('{<((https?|ftp|dict):[^\'">\s]+)>}i', + array(&$this, '_doAutoLinks_url_callback'), $text); + + # Email addresses: + $text = preg_replace_callback('{ + < + (?:mailto:)? + ( + (?: + [-!#$%&\'*+/=?^_`.{|}~\w\x80-\xFF]+ + | + ".*?" + ) + \@ + (?: + [-a-z0-9\x80-\xFF]+(\.[-a-z0-9\x80-\xFF]+)*\.[a-z]+ + | + \[[\d.a-fA-F:]+\] # IPv4 & IPv6 + ) + ) + > + }xi', + array(&$this, '_doAutoLinks_email_callback'), $text); + + return $text; + } + function _doAutoLinks_url_callback($matches) { + $url = $this->encodeAttribute($matches[1]); + $link = "$url"; + return $this->hashPart($link); + } + function _doAutoLinks_email_callback($matches) { + $address = $matches[1]; + $link = $this->encodeEmailAddress($address); + return $this->hashPart($link); + } + + + function encodeEmailAddress($addr) { + # + # Input: an email address, e.g. "foo@example.com" + # + # Output: the email address as a mailto link, with each character + # of the address encoded as either a decimal or hex entity, in + # the hopes of foiling most address harvesting spam bots. E.g.: + # + #

    foo@exampl + # e.com

    + # + # Based by a filter by Matthew Wickline, posted to BBEdit-Talk. + # With some optimizations by Milian Wolff. + # + $addr = "mailto:" . $addr; + $chars = preg_split('/(? $char) { + $ord = ord($char); + # Ignore non-ascii chars. + if ($ord < 128) { + $r = ($seed * (1 + $key)) % 100; # Pseudo-random function. + # roughly 10% raw, 45% hex, 45% dec + # '@' *must* be encoded. I insist. + if ($r > 90 && $char != '@') /* do nothing */; + else if ($r < 45) $chars[$key] = '&#x'.dechex($ord).';'; + else $chars[$key] = '&#'.$ord.';'; + } + } + + $addr = implode('', $chars); + $text = implode('', array_slice($chars, 7)); # text without `mailto:` + $addr = "$text"; + + return $addr; + } + + + function parseSpan($str) { + # + # Take the string $str and parse it into tokens, hashing embeded HTML, + # escaped characters and handling code spans. + # + $output = ''; + + $span_re = '{ + ( + \\\\'.$this->escape_chars_re.' + | + (?no_markup ? '' : ' + | + # comment + | + <\?.*?\?> | <%.*?%> # processing instruction + | + <[/!$]?[-a-zA-Z0-9:_]+ # regular tags + (?> + \s + (?>[^"\'>]+|"[^"]*"|\'[^\']*\')* + )? + > + ').' + ) + }xs'; + + while (1) { + # + # Each loop iteration seach for either the next tag, the next + # openning code span marker, or the next escaped character. + # Each token is then passed to handleSpanToken. + # + $parts = preg_split($span_re, $str, 2, PREG_SPLIT_DELIM_CAPTURE); + + # Create token from text preceding tag. + if ($parts[0] != "") { + $output .= $parts[0]; + } + + # Check if we reach the end. + if (isset($parts[1])) { + $output .= $this->handleSpanToken($parts[1], $parts[2]); + $str = $parts[2]; + } + else { + break; + } + } + + return $output; + } + + + function handleSpanToken($token, &$str) { + # + # Handle $token provided by parseSpan by determining its nature and + # returning the corresponding value that should replace it. + # + switch ($token{0}) { + case "\\": + return $this->hashPart("&#". ord($token{1}). ";"); + case "`": + # Search for end marker in remaining text. + if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm', + $str, $matches)) + { + $str = $matches[2]; + $codespan = $this->makeCodeSpan($matches[1]); + return $this->hashPart($codespan); + } + return $token; // return as text since no ending marker found. + default: + return $this->hashPart($token); + } + } + + + function outdent($text) { + # + # Remove one level of line-leading tabs or spaces + # + return preg_replace('/^(\t|[ ]{1,'.$this->tab_width.'})/m', '', $text); + } + + + # String length function for detab. `_initDetab` will create a function to + # hanlde UTF-8 if the default function does not exist. + var $utf8_strlen = 'mb_strlen'; + + function detab($text) { + # + # Replace tabs with the appropriate amount of space. + # + # For each line we separate the line in blocks delemited by + # tab characters. Then we reconstruct every line by adding the + # appropriate number of space between each blocks. + + $text = preg_replace_callback('/^.*\t.*$/m', + array(&$this, '_detab_callback'), $text); + + return $text; + } + function _detab_callback($matches) { + $line = $matches[0]; + $strlen = $this->utf8_strlen; # strlen function for UTF-8. + + # Split in blocks. + $blocks = explode("\t", $line); + # Add each blocks to the line. + $line = $blocks[0]; + unset($blocks[0]); # Do not add first block twice. + foreach ($blocks as $block) { + # Calculate amount of space, insert spaces, insert block. + $amount = $this->tab_width - + $strlen($line, 'UTF-8') % $this->tab_width; + $line .= str_repeat(" ", $amount) . $block; + } + return $line; + } + function _initDetab() { + # + # Check for the availability of the function in the `utf8_strlen` property + # (initially `mb_strlen`). If the function is not available, create a + # function that will loosely count the number of UTF-8 characters with a + # regular expression. + # + if (function_exists($this->utf8_strlen)) return; + $this->utf8_strlen = create_function('$text', 'return preg_match_all( + "/[\\\\x00-\\\\xBF]|[\\\\xC0-\\\\xFF][\\\\x80-\\\\xBF]*/", + $text, $m);'); + } + + + function unhash($text) { + # + # Swap back in all the tags hashed by _HashHTMLBlocks. + # + return preg_replace_callback('/(.)\x1A[0-9]+\1/', + array(&$this, '_unhash_callback'), $text); + } + function _unhash_callback($matches) { + return $this->html_hashes[$matches[0]]; + } + +} + + +# +# Markdown Extra Parser Class +# + +class MarkdownExtra_Parser extends Markdown_Parser { + + # Prefix for footnote ids. + var $fn_id_prefix = ""; + + # Optional title attribute for footnote links and backlinks. + var $fn_link_title = MARKDOWN_FN_LINK_TITLE; + var $fn_backlink_title = MARKDOWN_FN_BACKLINK_TITLE; + + # Optional class attribute for footnote links and backlinks. + var $fn_link_class = MARKDOWN_FN_LINK_CLASS; + var $fn_backlink_class = MARKDOWN_FN_BACKLINK_CLASS; + + # Predefined abbreviations. + var $predef_abbr = array(); + + + function MarkdownExtra_Parser() { + # + # Constructor function. Initialize the parser object. + # + # Add extra escapable characters before parent constructor + # initialize the table. + $this->escape_chars .= ':|'; + + # Insert extra document, block, and span transformations. + # Parent constructor will do the sorting. + $this->document_gamut += array( + "doFencedCodeBlocks" => 5, + "stripFootnotes" => 15, + "stripAbbreviations" => 25, + "appendFootnotes" => 50, + ); + $this->block_gamut += array( + "doFencedCodeBlocks" => 5, + "doTables" => 15, + "doDefLists" => 45, + ); + $this->span_gamut += array( + "doFootnotes" => 5, + "doAbbreviations" => 70, + ); + + parent::Markdown_Parser(); + } + + + # Extra variables used during extra transformations. + var $footnotes = array(); + var $footnotes_ordered = array(); + var $abbr_desciptions = array(); + var $abbr_word_re = ''; + + # Give the current footnote number. + var $footnote_counter = 1; + + + function setup() { + # + # Setting up Extra-specific variables. + # + parent::setup(); + + $this->footnotes = array(); + $this->footnotes_ordered = array(); + $this->abbr_desciptions = array(); + $this->abbr_word_re = ''; + $this->footnote_counter = 1; + + foreach ($this->predef_abbr as $abbr_word => $abbr_desc) { + if ($this->abbr_word_re) + $this->abbr_word_re .= '|'; + $this->abbr_word_re .= preg_quote($abbr_word); + $this->abbr_desciptions[$abbr_word] = trim($abbr_desc); + } + } + + function teardown() { + # + # Clearing Extra-specific variables. + # + $this->footnotes = array(); + $this->footnotes_ordered = array(); + $this->abbr_desciptions = array(); + $this->abbr_word_re = ''; + + parent::teardown(); + } + + + ### HTML Block Parser ### + + # Tags that are always treated as block tags: + var $block_tags_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|form|fieldset|iframe|hr|legend'; + + # Tags treated as block tags only if the opening tag is alone on it's line: + var $context_block_tags_re = 'script|noscript|math|ins|del'; + + # Tags where markdown="1" default to span mode: + var $contain_span_tags_re = 'p|h[1-6]|li|dd|dt|td|th|legend|address'; + + # Tags which must not have their contents modified, no matter where + # they appear: + var $clean_tags_re = 'script|math'; + + # Tags that do not need to be closed. + var $auto_close_tags_re = 'hr|img'; + + + function hashHTMLBlocks($text) { + # + # Hashify HTML Blocks and "clean tags". + # + # We only want to do this for block-level HTML tags, such as headers, + # lists, and tables. That's because we still want to wrap

    s around + # "paragraphs" that are wrapped in non-block-level tags, such as anchors, + # phrase emphasis, and spans. The list of tags we're looking for is + # hard-coded. + # + # This works by calling _HashHTMLBlocks_InMarkdown, which then calls + # _HashHTMLBlocks_InHTML when it encounter block tags. When the markdown="1" + # attribute is found whitin a tag, _HashHTMLBlocks_InHTML calls back + # _HashHTMLBlocks_InMarkdown to handle the Markdown syntax within the tag. + # These two functions are calling each other. It's recursive! + # + # + # Call the HTML-in-Markdown hasher. + # + list($text, ) = $this->_hashHTMLBlocks_inMarkdown($text); + + return $text; + } + function _hashHTMLBlocks_inMarkdown($text, $indent = 0, + $enclosing_tag_re = '', $span = false) + { + # + # Parse markdown text, calling _HashHTMLBlocks_InHTML for block tags. + # + # * $indent is the number of space to be ignored when checking for code + # blocks. This is important because if we don't take the indent into + # account, something like this (which looks right) won't work as expected: + # + #

    + #
    + # Hello World. <-- Is this a Markdown code block or text? + #
    <-- Is this a Markdown code block or a real tag? + #
    + # + # If you don't like this, just don't indent the tag on which + # you apply the markdown="1" attribute. + # + # * If $enclosing_tag_re is not empty, stops at the first unmatched closing + # tag with that name. Nested tags supported. + # + # * If $span is true, text inside must treated as span. So any double + # newline will be replaced by a single newline so that it does not create + # paragraphs. + # + # Returns an array of that form: ( processed text , remaining text ) + # + if ($text === '') return array('', ''); + + # Regex to check for the presense of newlines around a block tag. + $newline_before_re = '/(?:^\n?|\n\n)*$/'; + $newline_after_re = + '{ + ^ # Start of text following the tag. + (?>[ ]*)? # Optional comment. + [ ]*\n # Must be followed by newline. + }xs'; + + # Regex to match any tag. + $block_tag_re = + '{ + ( # $2: Capture hole tag. + # Tag name. + '.$this->block_tags_re.' | + '.$this->context_block_tags_re.' | + '.$this->clean_tags_re.' | + (?!\s)'.$enclosing_tag_re.' + ) + (?: + (?=[\s"\'/a-zA-Z0-9]) # Allowed characters after tag name. + (?> + ".*?" | # Double quotes (can contain `>`) + \'.*?\' | # Single quotes (can contain `>`) + .+? # Anything but quotes and `>`. + )*? + )? + > # End of tag. + | + # HTML Comment + | + <\?.*?\?> | <%.*?%> # Processing instruction + | + # CData Block + | + # Code span marker + `+ + '. ( !$span ? ' # If not in span. + | + # Indented code block + (?: ^[ ]*\n | ^ | \n[ ]*\n ) + [ ]{'.($indent+4).'}[^\n]* \n + (?> + (?: [ ]{'.($indent+4).'}[^\n]* | [ ]* ) \n + )* + | + # Fenced code block marker + (?> ^ | \n ) + [ ]{0,'.($indent).'}~~~+[ ]*\n + ' : '' ). ' # End (if not is span). + ) + }xs'; + + + $depth = 0; # Current depth inside the tag tree. + $parsed = ""; # Parsed text that will be returned. + + # + # Loop through every tag until we find the closing tag of the parent + # or loop until reaching the end of text if no parent tag specified. + # + do { + # + # Split the text using the first $tag_match pattern found. + # Text before pattern will be first in the array, text after + # pattern will be at the end, and between will be any catches made + # by the pattern. + # + $parts = preg_split($block_tag_re, $text, 2, + PREG_SPLIT_DELIM_CAPTURE); + + # If in Markdown span mode, add a empty-string span-level hash + # after each newline to prevent triggering any block element. + if ($span) { + $void = $this->hashPart("", ':'); + $newline = "$void\n"; + $parts[0] = $void . str_replace("\n", $newline, $parts[0]) . $void; + } + + $parsed .= $parts[0]; # Text before current tag. + + # If end of $text has been reached. Stop loop. + if (count($parts) < 3) { + $text = ""; + break; + } + + $tag = $parts[1]; # Tag to handle. + $text = $parts[2]; # Remaining text after current tag. + $tag_re = preg_quote($tag); # For use in a regular expression. + + # + # Check for: Code span marker + # + if ($tag{0} == "`") { + # Find corresponding end marker. + $tag_re = preg_quote($tag); + if (preg_match('{^(?>.+?|\n(?!\n))*?(?.*\n)+?[ ]{0,'.($indent).'}'.$tag_re.'[ ]*\n}', $text, + $matches)) + { + # End marker found: pass text unchanged until marker. + $parsed .= $tag . $matches[0]; + $text = substr($text, strlen($matches[0])); + } + else { + # No end marker: just skip it. + $parsed .= $tag; + } + } + # + # Check for: Indented code block. + # + else if ($tag{0} == "\n" || $tag{0} == " ") { + # Indented code block: pass it unchanged, will be handled + # later. + $parsed .= $tag; + } + # + # Check for: Opening Block level tag or + # Opening Context Block tag (like ins and del) + # used as a block tag (tag is alone on it's line). + # + else if (preg_match('{^<(?:'.$this->block_tags_re.')\b}', $tag) || + ( preg_match('{^<(?:'.$this->context_block_tags_re.')\b}', $tag) && + preg_match($newline_before_re, $parsed) && + preg_match($newline_after_re, $text) ) + ) + { + # Need to parse tag and following text using the HTML parser. + list($block_text, $text) = + $this->_hashHTMLBlocks_inHTML($tag . $text, "hashBlock", true); + + # Make sure it stays outside of any paragraph by adding newlines. + $parsed .= "\n\n$block_text\n\n"; + } + # + # Check for: Clean tag (like script, math) + # HTML Comments, processing instructions. + # + else if (preg_match('{^<(?:'.$this->clean_tags_re.')\b}', $tag) || + $tag{1} == '!' || $tag{1} == '?') + { + # Need to parse tag and following text using the HTML parser. + # (don't check for markdown attribute) + list($block_text, $text) = + $this->_hashHTMLBlocks_inHTML($tag . $text, "hashClean", false); + + $parsed .= $block_text; + } + # + # Check for: Tag with same name as enclosing tag. + # + else if ($enclosing_tag_re !== '' && + # Same name as enclosing tag. + preg_match('{^= 0); + + return array($parsed, $text); + } + function _hashHTMLBlocks_inHTML($text, $hash_method, $md_attr) { + # + # Parse HTML, calling _HashHTMLBlocks_InMarkdown for block tags. + # + # * Calls $hash_method to convert any blocks. + # * Stops when the first opening tag closes. + # * $md_attr indicate if the use of the `markdown="1"` attribute is allowed. + # (it is not inside clean tags) + # + # Returns an array of that form: ( processed text , remaining text ) + # + if ($text === '') return array('', ''); + + # Regex to match `markdown` attribute inside of a tag. + $markdown_attr_re = ' + { + \s* # Eat whitespace before the `markdown` attribute + markdown + \s*=\s* + (?> + (["\']) # $1: quote delimiter + (.*?) # $2: attribute value + \1 # matching delimiter + | + ([^\s>]*) # $3: unquoted attribute value + ) + () # $4: make $3 always defined (avoid warnings) + }xs'; + + # Regex to match any tag. + $tag_re = '{ + ( # $2: Capture hole tag. + + ".*?" | # Double quotes (can contain `>`) + \'.*?\' | # Single quotes (can contain `>`) + .+? # Anything but quotes and `>`. + )*? + )? + > # End of tag. + | + # HTML Comment + | + <\?.*?\?> | <%.*?%> # Processing instruction + | + # CData Block + ) + }xs'; + + $original_text = $text; # Save original text in case of faliure. + + $depth = 0; # Current depth inside the tag tree. + $block_text = ""; # Temporary text holder for current text. + $parsed = ""; # Parsed text that will be returned. + + # + # Get the name of the starting tag. + # (This pattern makes $base_tag_name_re safe without quoting.) + # + if (preg_match('/^<([\w:$]*)\b/', $text, $matches)) + $base_tag_name_re = $matches[1]; + + # + # Loop through every tag until we find the corresponding closing tag. + # + do { + # + # Split the text using the first $tag_match pattern found. + # Text before pattern will be first in the array, text after + # pattern will be at the end, and between will be any catches made + # by the pattern. + # + $parts = preg_split($tag_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE); + + if (count($parts) < 3) { + # + # End of $text reached with unbalenced tag(s). + # In that case, we return original text unchanged and pass the + # first character as filtered to prevent an infinite loop in the + # parent function. + # + return array($original_text{0}, substr($original_text, 1)); + } + + $block_text .= $parts[0]; # Text before current tag. + $tag = $parts[1]; # Tag to handle. + $text = $parts[2]; # Remaining text after current tag. + + # + # Check for: Auto-close tag (like
    ) + # Comments and Processing Instructions. + # + if (preg_match('{^auto_close_tags_re.')\b}', $tag) || + $tag{1} == '!' || $tag{1} == '?') + { + # Just add the tag to the block as if it was text. + $block_text .= $tag; + } + else { + # + # Increase/decrease nested tag count. Only do so if + # the tag's name match base tag's. + # + if (preg_match('{^mode = $attr_m[2] . $attr_m[3]; + $span_mode = $this->mode == 'span' || $this->mode != 'block' && + preg_match('{^<(?:'.$this->contain_span_tags_re.')\b}', $tag); + + # Calculate indent before tag. + if (preg_match('/(?:^|\n)( *?)(?! ).*?$/', $block_text, $matches)) { + $strlen = $this->utf8_strlen; + $indent = $strlen($matches[1], 'UTF-8'); + } else { + $indent = 0; + } + + # End preceding block with this tag. + $block_text .= $tag; + $parsed .= $this->$hash_method($block_text); + + # Get enclosing tag name for the ParseMarkdown function. + # (This pattern makes $tag_name_re safe without quoting.) + preg_match('/^<([\w:$]*)\b/', $tag, $matches); + $tag_name_re = $matches[1]; + + # Parse the content using the HTML-in-Markdown parser. + list ($block_text, $text) + = $this->_hashHTMLBlocks_inMarkdown($text, $indent, + $tag_name_re, $span_mode); + + # Outdent markdown text. + if ($indent > 0) { + $block_text = preg_replace("/^[ ]{1,$indent}/m", "", + $block_text); + } + + # Append tag content to parsed text. + if (!$span_mode) $parsed .= "\n\n$block_text\n\n"; + else $parsed .= "$block_text"; + + # Start over a new block. + $block_text = ""; + } + else $block_text .= $tag; + } + + } while ($depth > 0); + + # + # Hash last block text that wasn't processed inside the loop. + # + $parsed .= $this->$hash_method($block_text); + + return array($parsed, $text); + } + + + function hashClean($text) { + # + # Called whenever a tag must be hashed when a function insert a "clean" tag + # in $text, it pass through this function and is automaticaly escaped, + # blocking invalid nested overlap. + # + return $this->hashPart($text, 'C'); + } + + + function doHeaders($text) { + # + # Redefined to add id attribute support. + # + # Setext-style headers: + # Header 1 {#header1} + # ======== + # + # Header 2 {#header2} + # -------- + # + $text = preg_replace_callback( + '{ + (^.+?) # $1: Header text + (?:[ ]+\{\#([-_:a-zA-Z0-9]+)\})? # $2: Id attribute + [ ]*\n(=+|-+)[ ]*\n+ # $3: Header footer + }mx', + array(&$this, '_doHeaders_callback_setext'), $text); + + # atx-style headers: + # # Header 1 {#header1} + # ## Header 2 {#header2} + # ## Header 2 with closing hashes ## {#header3} + # ... + # ###### Header 6 {#header2} + # + $text = preg_replace_callback('{ + ^(\#{1,6}) # $1 = string of #\'s + [ ]* + (.+?) # $2 = Header text + [ ]* + \#* # optional closing #\'s (not counted) + (?:[ ]+\{\#([-_:a-zA-Z0-9]+)\})? # id attribute + [ ]* + \n+ + }xm', + array(&$this, '_doHeaders_callback_atx'), $text); + + return $text; + } + function _doHeaders_attr($attr) { + if (empty($attr)) return ""; + return " id=\"$attr\""; + } + function _doHeaders_callback_setext($matches) { + if ($matches[3] == '-' && preg_match('{^- }', $matches[1])) + return $matches[0]; + $level = $matches[3]{0} == '=' ? 1 : 2; + $attr = $this->_doHeaders_attr($id =& $matches[2]); + $block = "".$this->runSpanGamut($matches[1]).""; + return "\n" . $this->hashBlock($block) . "\n\n"; + } + function _doHeaders_callback_atx($matches) { + $level = strlen($matches[1]); + $attr = $this->_doHeaders_attr($id =& $matches[3]); + $block = "".$this->runSpanGamut($matches[2]).""; + return "\n" . $this->hashBlock($block) . "\n\n"; + } + + + function doTables($text) { + # + # Form HTML tables. + # + $less_than_tab = $this->tab_width - 1; + # + # Find tables with leading pipe. + # + # | Header 1 | Header 2 + # | -------- | -------- + # | Cell 1 | Cell 2 + # | Cell 3 | Cell 4 + # + $text = preg_replace_callback(' + { + ^ # Start of a line + [ ]{0,'.$less_than_tab.'} # Allowed whitespace. + [|] # Optional leading pipe (present) + (.+) \n # $1: Header row (at least one pipe) + + [ ]{0,'.$less_than_tab.'} # Allowed whitespace. + [|] ([ ]*[-:]+[-| :]*) \n # $2: Header underline + + ( # $3: Cells + (?> + [ ]* # Allowed whitespace. + [|] .* \n # Row content. + )* + ) + (?=\n|\Z) # Stop at final double newline. + }xm', + array(&$this, '_doTable_leadingPipe_callback'), $text); + + # + # Find tables without leading pipe. + # + # Header 1 | Header 2 + # -------- | -------- + # Cell 1 | Cell 2 + # Cell 3 | Cell 4 + # + $text = preg_replace_callback(' + { + ^ # Start of a line + [ ]{0,'.$less_than_tab.'} # Allowed whitespace. + (\S.*[|].*) \n # $1: Header row (at least one pipe) + + [ ]{0,'.$less_than_tab.'} # Allowed whitespace. + ([-:]+[ ]*[|][-| :]*) \n # $2: Header underline + + ( # $3: Cells + (?> + .* [|] .* \n # Row content + )* + ) + (?=\n|\Z) # Stop at final double newline. + }xm', + array(&$this, '_DoTable_callback'), $text); + + return $text; + } + function _doTable_leadingPipe_callback($matches) { + $head = $matches[1]; + $underline = $matches[2]; + $content = $matches[3]; + + # Remove leading pipe for each row. + $content = preg_replace('/^ *[|]/m', '', $content); + + return $this->_doTable_callback(array($matches[0], $head, $underline, $content)); + } + function _doTable_callback($matches) { + $head = $matches[1]; + $underline = $matches[2]; + $content = $matches[3]; + + # Remove any tailing pipes for each line. + $head = preg_replace('/[|] *$/m', '', $head); + $underline = preg_replace('/[|] *$/m', '', $underline); + $content = preg_replace('/[|] *$/m', '', $content); + + # Reading alignement from header underline. + $separators = preg_split('/ *[|] */', $underline); + foreach ($separators as $n => $s) { + if (preg_match('/^ *-+: *$/', $s)) $attr[$n] = ' align="right"'; + else if (preg_match('/^ *:-+: *$/', $s))$attr[$n] = ' align="center"'; + else if (preg_match('/^ *:-+ *$/', $s)) $attr[$n] = ' align="left"'; + else $attr[$n] = ''; + } + + # Parsing span elements, including code spans, character escapes, + # and inline HTML tags, so that pipes inside those gets ignored. + $head = $this->parseSpan($head); + $headers = preg_split('/ *[|] */', $head); + $col_count = count($headers); + + # Write column headers. + $text = "
    \n"; + $text .= "\n"; + $text .= "\n"; + foreach ($headers as $n => $header) + $text .= " ".$this->runSpanGamut(trim($header))."\n"; + $text .= "\n"; + $text .= "\n"; + + # Split content by row. + $rows = explode("\n", trim($content, "\n")); + + $text .= "\n"; + foreach ($rows as $row) { + # Parsing span elements, including code spans, character escapes, + # and inline HTML tags, so that pipes inside those gets ignored. + $row = $this->parseSpan($row); + + # Split row by cell. + $row_cells = preg_split('/ *[|] */', $row, $col_count); + $row_cells = array_pad($row_cells, $col_count, ''); + + $text .= "\n"; + foreach ($row_cells as $n => $cell) + $text .= " ".$this->runSpanGamut(trim($cell))."\n"; + $text .= "\n"; + } + $text .= "\n"; + $text .= "
    "; + + return $this->hashBlock($text) . "\n"; + } + + + function doDefLists($text) { + # + # Form HTML definition lists. + # + $less_than_tab = $this->tab_width - 1; + + # Re-usable pattern to match any entire dl list: + $whole_list_re = '(?> + ( # $1 = whole list + ( # $2 + [ ]{0,'.$less_than_tab.'} + ((?>.*\S.*\n)+) # $3 = defined term + \n? + [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition + ) + (?s:.+?) + ( # $4 + \z + | + \n{2,} + (?=\S) + (?! # Negative lookahead for another term + [ ]{0,'.$less_than_tab.'} + (?: \S.*\n )+? # defined term + \n? + [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition + ) + (?! # Negative lookahead for another definition + [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition + ) + ) + ) + )'; // mx + + $text = preg_replace_callback('{ + (?>\A\n?|(?<=\n\n)) + '.$whole_list_re.' + }mx', + array(&$this, '_doDefLists_callback'), $text); + + return $text; + } + function _doDefLists_callback($matches) { + # Re-usable patterns to match list item bullets and number markers: + $list = $matches[1]; + + # Turn double returns into triple returns, so that we can make a + # paragraph for the last item in a list, if necessary: + $result = trim($this->processDefListItems($list)); + $result = "
    \n" . $result . "\n
    "; + return $this->hashBlock($result) . "\n\n"; + } + + + function processDefListItems($list_str) { + # + # Process the contents of a single definition list, splitting it + # into individual term and definition list items. + # + $less_than_tab = $this->tab_width - 1; + + # trim trailing blank lines: + $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str); + + # Process definition terms. + $list_str = preg_replace_callback('{ + (?>\A\n?|\n\n+) # leading line + ( # definition terms = $1 + [ ]{0,'.$less_than_tab.'} # leading whitespace + (?![:][ ]|[ ]) # negative lookahead for a definition + # mark (colon) or more whitespace. + (?> \S.* \n)+? # actual term (not whitespace). + ) + (?=\n?[ ]{0,3}:[ ]) # lookahead for following line feed + # with a definition mark. + }xm', + array(&$this, '_processDefListItems_callback_dt'), $list_str); + + # Process actual definitions. + $list_str = preg_replace_callback('{ + \n(\n+)? # leading line = $1 + ( # marker space = $2 + [ ]{0,'.$less_than_tab.'} # whitespace before colon + [:][ ]+ # definition mark (colon) + ) + ((?s:.+?)) # definition text = $3 + (?= \n+ # stop at next definition mark, + (?: # next term or end of text + [ ]{0,'.$less_than_tab.'} [:][ ] | +
    | \z + ) + ) + }xm', + array(&$this, '_processDefListItems_callback_dd'), $list_str); + + return $list_str; + } + function _processDefListItems_callback_dt($matches) { + $terms = explode("\n", trim($matches[1])); + $text = ''; + foreach ($terms as $term) { + $term = $this->runSpanGamut(trim($term)); + $text .= "\n
    " . $term . "
    "; + } + return $text . "\n"; + } + function _processDefListItems_callback_dd($matches) { + $leading_line = $matches[1]; + $marker_space = $matches[2]; + $def = $matches[3]; + + if ($leading_line || preg_match('/\n{2,}/', $def)) { + # Replace marker with the appropriate whitespace indentation + $def = str_repeat(' ', strlen($marker_space)) . $def; + $def = $this->runBlockGamut($this->outdent($def . "\n\n")); + $def = "\n". $def ."\n"; + } + else { + $def = rtrim($def); + $def = $this->runSpanGamut($this->outdent($def)); + } + + return "\n
    " . $def . "
    \n"; + } + + + function doFencedCodeBlocks($text) { + # + # Adding the fenced code block syntax to regular Markdown: + # + # ~~~ + # Code block + # ~~~ + # + $less_than_tab = $this->tab_width; + + $text = preg_replace_callback('{ + (?:\n|\A) + # 1: Opening marker + ( + ~{3,} # Marker: three tilde or more. + ) + [ ]* \n # Whitespace and newline following marker. + + # 2: Content + ( + (?> + (?!\1 [ ]* \n) # Not a closing marker. + .*\n+ + )+ + ) + + # Closing marker. + \1 [ ]* \n + }xm', + array(&$this, '_doFencedCodeBlocks_callback'), $text); + + return $text; + } + function _doFencedCodeBlocks_callback($matches) { + $codeblock = $matches[2]; + $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES); + $codeblock = preg_replace_callback('/^\n+/', + array(&$this, '_doFencedCodeBlocks_newlines'), $codeblock); + $codeblock = "
    $codeblock
    "; + return "\n\n".$this->hashBlock($codeblock)."\n\n"; + } + function _doFencedCodeBlocks_newlines($matches) { + return str_repeat("empty_element_suffix", + strlen($matches[0])); + } + + + # + # Redefining emphasis markers so that emphasis by underscore does not + # work in the middle of a word. + # + var $em_relist = array( + '' => '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? '(?:(? '(?<=\S|^)(? '(?<=\S|^)(? tags + # + # Strip leading and trailing lines: + $text = preg_replace('/\A\n+|\n+\z/', '', $text); + + $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY); + + # + # Wrap

    tags and unhashify HTML blocks + # + foreach ($grafs as $key => $value) { + $value = trim($this->runSpanGamut($value)); + + # Check if this should be enclosed in a paragraph. + # Clean tag hashes & block tag hashes are left alone. + $is_p = !preg_match('/^B\x1A[0-9]+B|^C\x1A[0-9]+C$/', $value); + + if ($is_p) { + $value = "

    $value

    "; + } + $grafs[$key] = $value; + } + + # Join grafs in one text, then unhash HTML tags. + $text = implode("\n\n", $grafs); + + # Finish by removing any tag hashes still present in $text. + $text = $this->unhash($text); + + return $text; + } + + + ### Footnotes + + function stripFootnotes($text) { + # + # Strips link definitions from text, stores the URLs and titles in + # hash references. + # + $less_than_tab = $this->tab_width - 1; + + # Link defs are in the form: [^id]: url "optional title" + $text = preg_replace_callback('{ + ^[ ]{0,'.$less_than_tab.'}\[\^(.+?)\][ ]?: # note_id = $1 + [ ]* + \n? # maybe *one* newline + ( # text = $2 (no blank lines allowed) + (?: + .+ # actual text + | + \n # newlines but + (?!\[\^.+?\]:\s)# negative lookahead for footnote marker. + (?!\n+[ ]{0,3}\S)# ensure line is not blank and followed + # by non-indented content + )* + ) + }xm', + array(&$this, '_stripFootnotes_callback'), + $text); + return $text; + } + function _stripFootnotes_callback($matches) { + $note_id = $this->fn_id_prefix . $matches[1]; + $this->footnotes[$note_id] = $this->outdent($matches[2]); + return ''; # String that will replace the block + } + + + function doFootnotes($text) { + # + # Replace footnote references in $text [^id] with a special text-token + # which will be replaced by the actual footnote marker in appendFootnotes. + # + if (!$this->in_anchor) { + $text = preg_replace('{\[\^(.+?)\]}', "F\x1Afn:\\1\x1A:", $text); + } + return $text; + } + + + function appendFootnotes($text) { + # + # Append footnote list to text. + # + $text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', + array(&$this, '_appendFootnotes_callback'), $text); + + if (!empty($this->footnotes_ordered)) { + $text .= "\n\n"; + $text .= "
    \n"; + $text .= "empty_element_suffix ."\n"; + $text .= "
      \n\n"; + + $attr = " rev=\"footnote\""; + if ($this->fn_backlink_class != "") { + $class = $this->fn_backlink_class; + $class = $this->encodeAttribute($class); + $attr .= " class=\"$class\""; + } + if ($this->fn_backlink_title != "") { + $title = $this->fn_backlink_title; + $title = $this->encodeAttribute($title); + $attr .= " title=\"$title\""; + } + $num = 0; + + while (!empty($this->footnotes_ordered)) { + $footnote = reset($this->footnotes_ordered); + $note_id = key($this->footnotes_ordered); + unset($this->footnotes_ordered[$note_id]); + + $footnote .= "\n"; # Need to append newline before parsing. + $footnote = $this->runBlockGamut("$footnote\n"); + $footnote = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}', + array(&$this, '_appendFootnotes_callback'), $footnote); + + $attr = str_replace("%%", ++$num, $attr); + $note_id = $this->encodeAttribute($note_id); + + # Add backlink to last paragraph; create new paragraph if needed. + $backlink = ""; + if (preg_match('{

      $}', $footnote)) { + $footnote = substr($footnote, 0, -4) . " $backlink

      "; + } else { + $footnote .= "\n\n

      $backlink

      "; + } + + $text .= "
    1. \n"; + $text .= $footnote . "\n"; + $text .= "
    2. \n\n"; + } + + $text .= "
    \n"; + $text .= "
    "; + } + return $text; + } + function _appendFootnotes_callback($matches) { + $node_id = $this->fn_id_prefix . $matches[1]; + + # Create footnote marker only if it has a corresponding footnote *and* + # the footnote hasn't been used by another marker. + if (isset($this->footnotes[$node_id])) { + # Transfert footnote content to the ordered list. + $this->footnotes_ordered[$node_id] = $this->footnotes[$node_id]; + unset($this->footnotes[$node_id]); + + $num = $this->footnote_counter++; + $attr = " rel=\"footnote\""; + if ($this->fn_link_class != "") { + $class = $this->fn_link_class; + $class = $this->encodeAttribute($class); + $attr .= " class=\"$class\""; + } + if ($this->fn_link_title != "") { + $title = $this->fn_link_title; + $title = $this->encodeAttribute($title); + $attr .= " title=\"$title\""; + } + + $attr = str_replace("%%", $num, $attr); + $node_id = $this->encodeAttribute($node_id); + + return + "". + "$num". + ""; + } + + return "[^".$matches[1]."]"; + } + + + ### Abbreviations ### + + function stripAbbreviations($text) { + # + # Strips abbreviations from text, stores titles in hash references. + # + $less_than_tab = $this->tab_width - 1; + + # Link defs are in the form: [id]*: url "optional title" + $text = preg_replace_callback('{ + ^[ ]{0,'.$less_than_tab.'}\*\[(.+?)\][ ]?: # abbr_id = $1 + (.*) # text = $2 (no blank lines allowed) + }xm', + array(&$this, '_stripAbbreviations_callback'), + $text); + return $text; + } + function _stripAbbreviations_callback($matches) { + $abbr_word = $matches[1]; + $abbr_desc = $matches[2]; + if ($this->abbr_word_re) + $this->abbr_word_re .= '|'; + $this->abbr_word_re .= preg_quote($abbr_word); + $this->abbr_desciptions[$abbr_word] = trim($abbr_desc); + return ''; # String that will replace the block + } + + + function doAbbreviations($text) { + # + # Find defined abbreviations in text and wrap them in elements. + # + if ($this->abbr_word_re) { + // cannot use the /x modifier because abbr_word_re may + // contain significant spaces: + $text = preg_replace_callback('{'. + '(?abbr_word_re.')'. + '(?![\w\x1A])'. + '}', + array(&$this, '_doAbbreviations_callback'), $text); + } + return $text; + } + function _doAbbreviations_callback($matches) { + $abbr = $matches[0]; + if (isset($this->abbr_desciptions[$abbr])) { + $desc = $this->abbr_desciptions[$abbr]; + if (empty($desc)) { + return $this->hashPart("$abbr"); + } else { + $desc = $this->encodeAttribute($desc); + return $this->hashPart("$abbr"); + } + } else { + return $matches[0]; + } + } + +} + + +/* + +PHP Markdown Extra +================== + +Description +----------- + +This is a PHP port of the original Markdown formatter written in Perl +by John Gruber. This special "Extra" version of PHP Markdown features +further enhancements to the syntax for making additional constructs +such as tables and definition list. + +Markdown is a text-to-HTML filter; it translates an easy-to-read / +easy-to-write structured text format into HTML. Markdown's text format +is most similar to that of plain text email, and supports features such +as headers, *emphasis*, code blocks, blockquotes, and links. + +Markdown's syntax is designed not as a generic markup language, but +specifically to serve as a front-end to (X)HTML. You can use span-level +HTML tags anywhere in a Markdown document, and you can use block level +HTML tags (like
    and as well). + +For more information about Markdown's syntax, see: + + + + +Bugs +---- + +To file bug reports please send email to: + + + +Please include with your report: (1) the example input; (2) the output you +expected; (3) the output Markdown actually produced. + + +Version History +--------------- + +See the readme file for detailed release notes for this version. + + +Copyright and License +--------------------- + +PHP Markdown & Extra +Copyright (c) 2004-2009 Michel Fortin + +All rights reserved. + +Based on Markdown +Copyright (c) 2003-2006 John Gruber + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +* Neither the name "Markdown" nor the names of its contributors may + be used to endorse or promote products derived from this software + without specific prior written permission. + +This software is provided by the copyright holders and contributors "as +is" and any express or implied warranties, including, but not limited +to, the implied warranties of merchantability and fitness for a +particular purpose are disclaimed. In no event shall the copyright owner +or contributors be liable for any direct, indirect, incidental, special, +exemplary, or consequential damages (including, but not limited to, +procurement of substitute goods or services; loss of use, data, or +profits; or business interruption) however caused and on any theory of +liability, whether in contract, strict liability, or tort (including +negligence or otherwise) arising in any way out of the use of this +software, even if advised of the possibility of such damage. + +*/ +?> \ No newline at end of file diff --git a/pluf/src/Pluf/Text/Stemmer/Porter.php b/pluf/src/Pluf/Text/Stemmer/Porter.php new file mode 100644 index 0000000..4d0c64a --- /dev/null +++ b/pluf/src/Pluf/Text/Stemmer/Porter.php @@ -0,0 +1,433 @@ + 1) { + self::replace($word, 'e', ''); + + } else if (self::m(substr($word, 0, -1)) == 1) { + + if (!self::cvc(substr($word, 0, -1))) { + self::replace($word, 'e', ''); + } + } + } + + // Part b + if (self::m($word) > 1 AND self::doubleConsonant($word) AND substr($word, -1) == 'l') { + $word = substr($word, 0, -1); + } + + return $word; + } + + + /** + * Replaces the first string with the second, at the end of the string. If third + * arg is given, then the preceding string must match that m count at least. + * + * @param string $str String to check + * @param string $check Ending to check for + * @param string $repl Replacement string + * @param int $m Optional minimum number of m() to meet + * @return bool Whether the $check string was at the end + * of the $str string. True does not necessarily mean + * that it was replaced. + */ + private static function replace(&$str, $check, $repl, $m = null) + { + $len = 0 - strlen($check); + + if (substr($str, $len) == $check) { + $substr = substr($str, 0, $len); + if (is_null($m) OR self::m($substr) > $m) { + $str = $substr . $repl; + } + + return true; + } + + return false; + } + + + /** + * What, you mean it's not obvious from the name? + * + * m() measures the number of consonant sequences in $str. if c is + * a consonant sequence and v a vowel sequence, and <..> indicates arbitrary + * presence, + * + * gives 0 + * vc gives 1 + * vcvc gives 2 + * vcvcvc gives 3 + * + * @param string $str The string to return the m count for + * @return int The m count + */ + private static function m($str) + { + $c = self::$regex_consonant; + $v = self::$regex_vowel; + + $str = preg_replace("#^$c+#", '', $str); + $str = preg_replace("#$v+$#", '', $str); + + preg_match_all("#($v+$c+)#", $str, $matches); + + return count($matches[1]); + } + + + /** + * Returns true/false as to whether the given string contains two + * of the same consonant next to each other at the end of the string. + * + * @param string $str String to check + * @return bool Result + */ + private static function doubleConsonant($str) + { + $c = self::$regex_consonant; + + return preg_match("#$c{2}$#", $str, $matches) AND $matches[0]{0} == $matches[0]{1}; + } + + + /** + * Checks for ending CVC sequence where second C is not W, X or Y + * + * @param string $str String to check + * @return bool Result + */ + private static function cvc($str) + { + $c = self::$regex_consonant; + $v = self::$regex_vowel; + return preg_match("#($c$v$c)$#", $str, $matches) + AND strlen($matches[1]) == 3 + AND $matches[1]{2} != 'w' + AND $matches[1]{2} != 'x' + AND $matches[1]{2} != 'y'; + } +} + diff --git a/pluf/src/Pluf/Text/UTF8.php b/pluf/src/Pluf/Text/UTF8.php new file mode 100644 index 0000000..f47d3cb --- /dev/null +++ b/pluf/src/Pluf/Text/UTF8.php @@ -0,0 +1,649 @@ + + */ + + +class Pluf_Text_UTF8 +{ + /** + * URL-Encode a filename/URL to allow unicodecharacters + * + * Slashes are not encoded + * + * When the second parameter is true the string will + * be encoded only if non ASCII characters are detected - + * This makes it safe to run it multiple times on the + * same string (default is true) + * + * @author Andreas Gohr + * @see urlencode + */ + public static function filename($file, $safe=true) + { + if ($safe && preg_match('#^[a-zA-Z0-9/_\-.%]+$#', $file)) { + return $file; + } + return str_replace('%2F', '/', urlencode($file)); + } + + /** + * Checks if a string contains 7bit ASCII only + * + * @author Andreas Gohr + */ + public static function is_ascii($str) + { + $n = strlen($str); + for ($i=0; $i<$n; $i++) { + if (ord($str{$i}) >127) return false; + } + return true; + } + + /** + * Strips all highbyte chars + * + * Returns a pure ASCII7 string + * + * @author Andreas Gohr + */ + public static function strip($str) + { + $ascii = ''; + $n = strlen($str); + for ($i=0; $i<$n; $i++) { + if (ord($str{$i}) < 128) { + $ascii .= $str{$i}; + } + } + return $ascii; + } + + /** + * Tries to detect if a string is in Unicode encoding + * + * @author + * @link http://www.php.net/manual/en/function.utf8-encode.php + */ + public static function check($str) + { + $k = strlen($str); + for ($i=0; $i<$k; $i++) { + $b = ord($str[$i]); + if ($b < 0x80) continue; // 0bbbbbbb + elseif (($b & 0xE0) == 0xC0) $n = 1; // 110bbbbb + elseif (($b & 0xF0) == 0xE0) $n = 2; // 1110bbbb + elseif (($b & 0xF8) == 0xF0) $n = 3; // 11110bbb + elseif (($b & 0xFC) == 0xF8) $n = 4; // 111110bb + elseif (($b & 0xFE) == 0xFC) $n = 5; // 1111110b + else return false; // Does not match any model + for ($j=0; $j<$n; $j++) { // n bytes matching 10bbbbbb follow ? + if ((++$i == $k) || ((ord($str[$i]) & 0xC0) != 0x80)) { + return false; + } + } + } + return true; + } + + /** + * Detect if a string is in a Russian charset. + * + * This should be used when the mb_string detection encoding is + * failing. For example: + * + *
    +     * $encoding = mb_detect_encoding($string, mb_detect_order(), true);
    +     * if ($encoding == false) {
    +     *     $encoding = Pluf_Text_UTF8::detect_cyr_charset($string);
    +     * }
    +     * 
    + * + * @link http://forum.php.su/topic.php?forum=1&topic=1346 + * + * @param string + * @return string Possible Russian encoding + */ + public static function detect_cyr_charset($str) + { + $charsets = array( + 'KOI8-R' => 0, + 'Windows-1251' => 0, + 'CP-866' => 0, + 'ISO-8859-5' => 0, + ); + $length = strlen($str); + for ($i=0; $i<$length; $i++) { + $char = ord($str[$i]); + //non-russian characters + if ($char < 128 || $char > 256) continue; + + //CP866 + if (($char > 159 && $char < 176) || ($char > 223 && $char < 242)) + $charsets['CP-866']+=3; + if (($char > 127 && $char < 160)) $charsets['CP-866']+=1; + + //KOI8-R + if (($char > 191 && $char < 223)) $charsets['KOI8-R']+=3; + if (($char > 222 && $char < 256)) $charsets['KOI8-R']+=1; + + //WIN-1251 + if ($char > 223 && $char < 256) $charsets['Windows-1251']+=3; + if ($char > 191 && $char < 224) $charsets['Windows-1251']+=1; + + //ISO-8859-5 + if ($char > 207 && $char < 240) $charsets['ISO-8859-5']+=3; + if ($char > 175 && $char < 208) $charsets['ISO-8859-5']+=1; + + } + arsort($charsets); + return key($charsets); + } + + + /** + * Replace accented UTF-8 characters by unaccented ASCII-7 equivalents. + * + * @author Andreas Gohr + */ + public static function deaccent($string) + { + return strtr($string, self::accents()); + } + + /** + * Romanize a non-latin string + * + * FIXME + * @author Andreas Gohr + */ + public static function romanize($string) + { + if (self::is_ascii($string)) return $string; + return strtr($string, self::romanization()); + } + + /** + * Removes special characters (nonalphanumeric) from a UTF-8 string + * + * This function adds the controlchars 0x00 to 0x19 to the array of + * stripped chars (they are not included in $UTF8_SPECIAL_CHARS) + * + * @author Andreas Gohr + * @param string $string The UTF8 string to strip of special chars + * @param string $repl Replace special with this string + * @param string $additional Additional chars to strip (used in regexp char class) + */ + function stripspecials($string, $repl='', $additional='') + { + static $specials = null; + if (is_null($specials)) { + $specials = preg_quote(self::special_chars(), '/'); + } + return preg_replace('/['.$additional.'\x00-\x19'.$specials.']/u',$repl,$string); + } + + + /** + * UTF-8 lookup table for lower case accented letters + * + * This lookuptable defines replacements for accented characters from the ASCII-7 + * range. This are lower case letters only. + * + * @author Andreas Gohr + * @see utf8_deaccent() + */ + public static function accents() + { + return array( + 'à' => 'a', 'ô' => 'o', 'ď' => 'd', 'ḟ' => 'f', + 'ë' => 'e', 'š' => 's', 'ơ' => 'o', 'ß' => 'ss', + 'ă' => 'a', 'ř' => 'r', 'ț' => 't', 'ň' => 'n', + 'ā' => 'a', 'ķ' => 'k', 'ŝ' => 's', 'ỳ' => 'y', + 'ņ' => 'n', 'ĺ' => 'l', 'ħ' => 'h', 'ṗ' => 'p', + 'ó' => 'o', 'ú' => 'u', 'ě' => 'e', 'é' => 'e', + 'ç' => 'c', 'ẁ' => 'w', 'ċ' => 'c', 'õ' => 'o', + 'ṡ' => 's', 'ø' => 'o', 'ģ' => 'g', 'ŧ' => 't', + 'ș' => 's', 'ė' => 'e', 'ĉ' => 'c', 'ś' => 's', + 'î' => 'i', 'ű' => 'u', 'ć' => 'c', 'ę' => 'e', + 'ŵ' => 'w', 'ṫ' => 't', 'ū' => 'u', 'č' => 'c', + 'ö' => 'oe', 'è' => 'e', 'ŷ' => 'y', 'ą' => 'a', + 'ł' => 'l', 'ų' => 'u', 'ů' => 'u', 'ş' => 's', + 'ğ' => 'g', 'ļ' => 'l', 'ƒ' => 'f', 'ž' => 'z', + 'ẃ' => 'w', 'ḃ' => 'b', 'å' => 'a', 'ì' => 'i', + 'ï' => 'i', 'ḋ' => 'd', 'ť' => 't', 'ŗ' => 'r', + 'ä' => 'ae', 'í' => 'i', 'ŕ' => 'r', 'ê' => 'e', + 'ü' => 'ue', 'ò' => 'o', 'ē' => 'e', 'ñ' => 'n', + 'ń' => 'n', 'ĥ' => 'h', 'ĝ' => 'g', 'đ' => 'd', + 'ĵ' => 'j', 'ÿ' => 'y', 'ũ' => 'u', 'ŭ' => 'u', + 'ư' => 'u', 'ţ' => 't', 'ý' => 'y', 'ő' => 'o', + 'â' => 'a', 'ľ' => 'l', 'ẅ' => 'w', 'ż' => 'z', + 'ī' => 'i', 'ã' => 'a', 'ġ' => 'g', 'ṁ' => 'm', + 'ō' => 'o', 'ĩ' => 'i', 'ù' => 'u', 'į' => 'i', + 'ź' => 'z', 'á' => 'a', 'û' => 'u', 'þ' => 'th', + 'ð' => 'dh', 'æ' => 'ae', 'µ' => 'u', 'ĕ' => 'e', + 'À' => 'A', 'Ô' => 'O', 'Ď' => 'D', 'Ḟ' => 'F', + 'Ë' => 'E', 'Š' => 'S', 'Ơ' => 'O', 'Ă' => 'A', + 'Ř' => 'R', 'Ț' => 'T', 'Ň' => 'N', 'Ā' => 'A', + 'Ķ' => 'K', 'Ŝ' => 'S', 'Ỳ' => 'Y', 'Ņ' => 'N', + 'Ĺ' => 'L', 'Ħ' => 'H', 'Ṗ' => 'P', 'Ó' => 'O', + 'Ú' => 'U', 'Ě' => 'E', 'É' => 'E', 'Ç' => 'C', + 'Ẁ' => 'W', 'Ċ' => 'C', 'Õ' => 'O', 'Ṡ' => 'S', + 'Ø' => 'O', 'Ģ' => 'G', 'Ŧ' => 'T', 'Ș' => 'S', + 'Ė' => 'E', 'Ĉ' => 'C', 'Ś' => 'S', 'Î' => 'I', + 'Ű' => 'U', 'Ć' => 'C', 'Ę' => 'E', 'Ŵ' => 'W', + 'Ṫ' => 'T', 'Ū' => 'U', 'Č' => 'C', 'Ö' => 'Oe', + 'È' => 'E', 'Ŷ' => 'Y', 'Ą' => 'A', 'Ł' => 'L', + 'Ų' => 'U', 'Ů' => 'U', 'Ş' => 'S', 'Ğ' => 'G', + 'Ļ' => 'L', 'Ƒ' => 'F', 'Ž' => 'Z', 'Ẃ' => 'W', + 'Ḃ' => 'B', 'Å' => 'A', 'Ì' => 'I', 'Ï' => 'I', + 'Ḋ' => 'D', 'Ť' => 'T', 'Ŗ' => 'R', 'Ä' => 'Ae', + 'Í' => 'I', 'Ŕ' => 'R', 'Ê' => 'E', 'Ü' => 'Ue', + 'Ò' => 'O', 'Ē' => 'E', 'Ñ' => 'N', 'Ń' => 'N', + 'Ĥ' => 'H', 'Ĝ' => 'G', 'Đ' => 'D', 'Ĵ' => 'J', + 'Ÿ' => 'Y', 'Ũ' => 'U', 'Ŭ' => 'U', 'Ư' => 'U', + 'Ţ' => 'T', 'Ý' => 'Y', 'Ő' => 'O', 'Â' => 'A', + 'Ľ' => 'L', 'Ẅ' => 'W', 'Ż' => 'Z', 'Ī' => 'I', + 'Ã' => 'A', 'Ġ' => 'G', 'Ṁ' => 'M', 'Ō' => 'O', + 'Ĩ' => 'I', 'Ù' => 'U', 'Į' => 'I', 'Ź' => 'Z', + 'Á' => 'A', 'Û' => 'U', 'Þ' => 'Th', 'Ð' => 'Dh', + 'Æ' => 'Ae', 'Ĕ' => 'E', + ); + } + + public static function special_chars() + { + return "\x1A".' !"#$%&\'()+,/;<=>?@[\]^`{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•�'. + '�—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½�'. + '�¿×÷ˇ˘˙˚˛˜˝̣̀́̃̉΄΅·βφϑϒϕϖְֱֲֳִֵֶַָֹֻּֽ־ֿ�'. + '�ׁׂ׃׳״،؛؟ـًٌٍَُِّْ٪฿‌‍‎‏–—―‗‘’‚“”�'. + '��†‡•…‰′″‹›⁄₧₪₫€№℘™Ωℵ←↑→↓↔↕↵'. + '⇐⇑⇒⇓⇔∀∂∃∅∆∇∈∉∋∏∑−∕∗∙√∝∞∠∧∨�'. + '�∪∫∴∼≅≈≠≡≤≥⊂⊃⊄⊆⊇⊕⊗⊥⋅⌐⌠⌡〈〉⑩─�'. + '��┌┐└┘├┤┬┴┼═║╒╓╔╕╖╗╘╙╚╛╜╝╞╟╠'. + '╡╢╣╤╥╦╧╨╩╪╫╬▀▄█▌▐░▒▓■▲▼◆◊●�'. + '�★☎☛☞♠♣♥♦✁✂✃✄✆✇✈✉✌✍✎✏✐✑✒✓✔✕�'. + '��✗✘✙✚✛✜✝✞✟✠✡✢✣✤✥✦✧✩✪✫✬✭✮✯✰✱'. + '✲✳✴✵✶✷✸✹✺✻✼✽✾✿❀❁❂❃❄❅❆❇❈❉❊❋�'. + '�❏❐❑❒❖❘❙❚❛❜❝❞❡❢❣❤❥❦❧❿➉➓➔➘➙➚�'. + '��➜➝➞➟➠➡➢➣➤➥➦➧➨➩➪➫➬➭➮➯➱➲➳➴➵➶'. + '➷➸➹➺➻➼➽➾'. + ' 、。〃〈〉《》「」『』【】〒〔〕〖〗〘〙〚〛〶'. + '�'. + '�ﹼﹽ'. + '!"#$%&'()*+,-./:;<=>?@[\]^`{|}~'. + '⦅⦆。「」、・¢£¬ ̄¦¥₩│←↑→↓■○'; + } + + /** + * Romanization lookup table + * + * This lookup tables provides a way to transform strings written + * in a language different from the ones based upon latin letters + * into plain ASCII. + * + * Please note: this is not a scientific transliteration table. It + * only works oneway from nonlatin to ASCII and it works by simple + * character replacement only. Specialities of each language are + * not supported. + * + * @author Andreas Gohr + * @author Vitaly Blokhin + * @link http://www.uconv.com/translit.htm + * @author Bisqwit + * @link http://kanjidict.stc.cx/hiragana.php?src=2 + * @link http://www.translatum.gr/converter/greek-transliteration.htm + * @link http://en.wikipedia.org/wiki/Royal_Thai_General_System_of_Transcription + * @link http://www.btranslations.com/resources/romanization/korean.asp + * @author Arthit Suriyawongkul + * @author Denis Scheither + */ + public static function romanization() + { + return array( + //russian cyrillic + 'а'=>'a','А'=>'A','б'=>'b','Б'=>'B','в'=>'v','В'=>'V','г'=>'g','Г'=>'G', + 'д'=>'d','Д'=>'D','е'=>'e','Е'=>'E','ё'=>'jo','Ё'=>'Jo','ж'=>'zh','Ж'=>'Zh', + 'з'=>'z','З'=>'Z','и'=>'i','И'=>'I','й'=>'j','Й'=>'J','к'=>'k','К'=>'K', + 'л'=>'l','Л'=>'L','м'=>'m','М'=>'M','н'=>'n','Н'=>'N','о'=>'o','О'=>'O', + 'п'=>'p','П'=>'P','р'=>'r','Р'=>'R','с'=>'s','С'=>'S','т'=>'t','Т'=>'T', + 'у'=>'u','У'=>'U','ф'=>'f','Ф'=>'F','х'=>'x','Х'=>'X','ц'=>'c','Ц'=>'C', + 'ч'=>'ch','Ч'=>'Ch','ш'=>'sh','Ш'=>'Sh','щ'=>'sch','Щ'=>'Sch','ъ'=>'', + 'Ъ'=>'','ы'=>'y','Ы'=>'Y','ь'=>'','Ь'=>'','э'=>'eh','Э'=>'Eh','ю'=>'ju', + 'Ю'=>'Ju','я'=>'ja','Я'=>'Ja', + // Ukrainian cyrillic + 'Ґ'=>'Gh','ґ'=>'gh','Є'=>'Je','є'=>'je','І'=>'I','і'=>'i','Ї'=>'Ji','ї'=>'ji', + // Georgian + 'ა'=>'a','ბ'=>'b','გ'=>'g','დ'=>'d','ე'=>'e','ვ'=>'v','ზ'=>'z','თ'=>'th', + 'ი'=>'i','კ'=>'p','ლ'=>'l','მ'=>'m','ნ'=>'n','ო'=>'o','პ'=>'p','ჟ'=>'zh', + 'რ'=>'r','ს'=>'s','ტ'=>'t','უ'=>'u','ფ'=>'ph','ქ'=>'kh','ღ'=>'gh','ყ'=>'q', + 'შ'=>'sh','ჩ'=>'ch','ც'=>'c','ძ'=>'dh','წ'=>'w','ჭ'=>'j','ხ'=>'x','ჯ'=>'jh', + 'ჰ'=>'xh', + //Sanskrit + 'अ'=>'a','आ'=>'ah','इ'=>'i','ई'=>'ih','उ'=>'u','ऊ'=>'uh','ऋ'=>'ry', + 'ॠ'=>'ryh','ऌ'=>'ly','ॡ'=>'lyh','ए'=>'e','ऐ'=>'ay','ओ'=>'o','औ'=>'aw', + 'अं'=>'amh','अः'=>'aq','क'=>'k','ख'=>'kh','ग'=>'g','घ'=>'gh','ङ'=>'nh', + 'च'=>'c','छ'=>'ch','ज'=>'j','झ'=>'jh','ञ'=>'ny','ट'=>'tq','ठ'=>'tqh', + 'ड'=>'dq','ढ'=>'dqh','ण'=>'nq','त'=>'t','थ'=>'th','द'=>'d','ध'=>'dh', + 'न'=>'n','प'=>'p','फ'=>'ph','ब'=>'b','भ'=>'bh','म'=>'m','य'=>'z','र'=>'r', + 'ल'=>'l','व'=>'v','श'=>'sh','ष'=>'sqh','स'=>'s','ह'=>'x', + //Hebrew + 'א'=>'a', 'ב'=>'b','ג'=>'g','ד'=>'d','ה'=>'h','ו'=>'v','ז'=>'z','ח'=>'kh','ט'=>'th', + 'י'=>'y','ך'=>'h','כ'=>'k','ל'=>'l','ם'=>'m','מ'=>'m','ן'=>'n','נ'=>'n', + 'ס'=>'s','ע'=>'ah','ף'=>'f','פ'=>'p','ץ'=>'c','צ'=>'c','ק'=>'q','ר'=>'r', + 'ש'=>'sh','ת'=>'t', + //Arabic + 'ا'=>'a','ب'=>'b','ت'=>'t','ث'=>'th','ج'=>'g','ح'=>'xh','خ'=>'x','د'=>'d', + 'ذ'=>'dh','ر'=>'r','ز'=>'z','س'=>'s','ش'=>'sh','ص'=>'s\'','ض'=>'d\'', + 'ط'=>'t\'','ظ'=>'z\'','ع'=>'y','غ'=>'gh','ف'=>'f','ق'=>'q','ك'=>'k', + 'ل'=>'l','م'=>'m','ن'=>'n','ه'=>'x\'','و'=>'u','ي'=>'i', + // Japanese hiragana + // 3 character syllables, っ doubles the consonant after + 'っちゃ'=>'ccha','っちぇ'=>'cche','っちょ'=>'ccho','っちゅ'=>'cchu', + 'っびゃ'=>'bya','っびぇ'=>'bye','っびぃ'=>'byi','っびょ'=>'byo','っびゅ'=>'byu', + 'っちゃ'=>'cha','っちぇ'=>'che','っち'=>'chi','っちょ'=>'cho','っちゅ'=>'chu', + 'っひゃ'=>'hya','っひぇ'=>'hye','っひぃ'=>'hyi','っひょ'=>'hyo','っひゅ'=>'hyu', + 'っきゃ'=>'kya','っきぇ'=>'kye','っきぃ'=>'kyi','っきょ'=>'kyo','っきゅ'=>'kyu', + 'っぎゃ'=>'gya','っぎぇ'=>'gye','っぎぃ'=>'gyi','っぎょ'=>'gyo','っぎゅ'=>'gyu', + 'っみゃ'=>'mya','っみぇ'=>'mye','っみぃ'=>'myi','っみょ'=>'myo','っみゅ'=>'myu', + 'っにゃ'=>'nya','っにぇ'=>'nye','っにぃ'=>'nyi','っにょ'=>'nyo','っにゅ'=>'nyu', + 'っりゃ'=>'rya','っりぇ'=>'rye','っりぃ'=>'ryi','っりょ'=>'ryo','っりゅ'=>'ryu', + 'っしゃ'=>'sha','っしぇ'=>'she','っし'=>'shi','っしょ'=>'sho','っしゅ'=>'shu', + // 2 character syllables - normal + 'ふぁ'=>'fa','ふぇ'=>'fe','ふぃ'=>'fi','ふぉ'=>'fo','ふ'=>'fu', + 'ヴぁ'=>'va','ヴぇ'=>'ve','ヴぃ'=>'vi','ヴぉ'=>'vo','ヴ'=>'vu', + 'びゃ'=>'bya','びぇ'=>'bye','びぃ'=>'byi','びょ'=>'byo','びゅ'=>'byu', + 'ちゃ'=>'cha','ちぇ'=>'che','ち'=>'chi','ちょ'=>'cho','ちゅ'=>'chu', + 'ひゃ'=>'hya','ひぇ'=>'hye','ひぃ'=>'hyi','ひょ'=>'hyo','ひゅ'=>'hyu', + 'きゃ'=>'kya','きぇ'=>'kye','きぃ'=>'kyi','きょ'=>'kyo','きゅ'=>'kyu', + 'ぎゃ'=>'gya','ぎぇ'=>'gye','ぎぃ'=>'gyi','ぎょ'=>'gyo','ぎゅ'=>'gyu', + 'みゃ'=>'mya','みぇ'=>'mye','みぃ'=>'myi','みょ'=>'myo','みゅ'=>'myu', + 'にゃ'=>'nya','にぇ'=>'nye','にぃ'=>'nyi','にょ'=>'nyo','にゅ'=>'nyu', + 'りゃ'=>'rya','りぇ'=>'rye','りぃ'=>'ryi','りょ'=>'ryo','りゅ'=>'ryu', + 'しゃ'=>'sha','しぇ'=>'she','し'=>'shi','しょ'=>'sho','しゅ'=>'shu', + 'じゃ'=>'ja','じぇ'=>'je','じ'=>'ji','じょ'=>'jo','じゅ'=>'ju', + + // 2 character syllables, っ doubles the consonant after + 'っば'=>'bba','っべ'=>'bbe','っび'=>'bbi','っぼ'=>'bbo','っぶ'=>'bbu', + 'っぱ'=>'ppa','っぺ'=>'ppe','っぴ'=>'ppi','っぽ'=>'ppo','っぷ'=>'ppu', + 'った'=>'tta','って'=>'tte','っち'=>'cchi','っと'=>'tto','っつ'=>'ttsu', + 'っだ'=>'dda','っで'=>'dde','っぢ'=>'ddi','っど'=>'ddo','っづ'=>'ddu', + 'っが'=>'gga','っげ'=>'gge','っぎ'=>'ggi','っご'=>'ggo','っぐ'=>'ggu', + 'っか'=>'kka','っけ'=>'kke','っき'=>'kki','っこ'=>'kko','っく'=>'kku', + 'っま'=>'mma','っめ'=>'mme','っみ'=>'mmi','っも'=>'mmo','っむ'=>'mmu', + 'っな'=>'nna','っね'=>'nne','っに'=>'nni','っの'=>'nno','っぬ'=>'nnu', + 'っら'=>'rra','っれ'=>'rre','っり'=>'rri','っろ'=>'rro','っる'=>'rru', + 'っさ'=>'ssa','っせ'=>'sse','っし'=>'sshi','っそ'=>'sso','っす'=>'ssu', + 'っざ'=>'zza','っぜ'=>'zze','っじ'=>'zzi','っぞ'=>'zzo','っず'=>'zzu', + + // 1 character syllabels + 'あ'=>'a','え'=>'e','い'=>'i','お'=>'o','う'=>'u','ん'=>'n', + 'は'=>'ha','へ'=>'he','ひ'=>'hi','ほ'=>'ho','ふ'=>'hu', + 'ば'=>'ba','べ'=>'be','び'=>'bi','ぼ'=>'bo','ぶ'=>'bu', + 'ぱ'=>'pa','ぺ'=>'pe','ぴ'=>'pi','ぽ'=>'po','ぷ'=>'pu', + 'た'=>'ta','て'=>'te','ち'=>'ti','と'=>'to','つ'=>'tu', + 'だ'=>'da','で'=>'de','ぢ'=>'di','ど'=>'do','づ'=>'du', + 'が'=>'ga','げ'=>'ge','ぎ'=>'gi','ご'=>'go','ぐ'=>'gu', + 'か'=>'ka','け'=>'ke','き'=>'ki','こ'=>'ko','く'=>'ku', + 'ま'=>'ma','め'=>'me','み'=>'mi','も'=>'mo','む'=>'mu', + 'な'=>'na','ね'=>'ne','に'=>'ni','の'=>'no','ぬ'=>'nu', + 'ら'=>'ra','れ'=>'re','り'=>'ri','ろ'=>'ro','る'=>'ru', + 'さ'=>'sa','せ'=>'se','し'=>'shi','そ'=>'so','す'=>'su', + 'わ'=>'wa','うぇ'=>'we','うぃ'=>'wi','を'=>'wo', + 'ざ'=>'za','ぜ'=>'ze','じ'=>'zi','ぞ'=>'zo','ず'=>'zu', + 'や'=>'ya','いぇ'=>'ye','よ'=>'yo','ゆ'=>'yu', + + // never seen one of those, but better save than sorry + 'でゃ'=>'dha','でぇ'=>'dhe','でぃ'=>'dhi','でょ'=>'dho','でゅ'=>'dhu', + 'どぁ'=>'dwa','どぇ'=>'dwe','どぃ'=>'dwi','どぉ'=>'dwo','どぅ'=>'dwu', + 'ぢゃ'=>'dya','ぢぇ'=>'dye','ぢぃ'=>'dyi','ぢょ'=>'dyo','ぢゅ'=>'dyu', + 'ふぁ'=>'fwa','ふぇ'=>'fwe','ふぃ'=>'fwi','ふぉ'=>'fwo','ふぅ'=>'fwu', + 'ふゃ'=>'fya','ふぇ'=>'fye','ふぃ'=>'fyi','ふょ'=>'fyo','ふゅ'=>'fyu', + 'ぴゃ'=>'pya','ぴぇ'=>'pye','ぴぃ'=>'pyi','ぴょ'=>'pyo','ぴゅ'=>'pyu', + 'すぁ'=>'swa','すぇ'=>'swe','すぃ'=>'swi','すぉ'=>'swo','すぅ'=>'swu', + 'てゃ'=>'tha','てぇ'=>'the','てぃ'=>'thi','てょ'=>'tho','てゅ'=>'thu', + 'つゃ'=>'tsa','つぇ'=>'tse','つぃ'=>'tsi','つょ'=>'tso','つ'=>'tsu', + 'とぁ'=>'twa','とぇ'=>'twe','とぃ'=>'twi','とぉ'=>'two','とぅ'=>'twu', + 'ヴゃ'=>'vya','ヴぇ'=>'vye','ヴぃ'=>'vyi','ヴょ'=>'vyo','ヴゅ'=>'vyu', + 'うぁ'=>'wha','うぇ'=>'whe','うぃ'=>'whi','うぉ'=>'who','うぅ'=>'whu', + 'ゑ'=>'wye','ゐ'=>'wyi', + 'じゃ'=>'zha','じぇ'=>'zhe','じぃ'=>'zhi','じょ'=>'zho','じゅ'=>'zhu', + 'じゃ'=>'zya','じぇ'=>'zye','じぃ'=>'zyi','じょ'=>'zyo','じゅ'=>'zyu', + + // convert what's left (probably only kicks in when something's missing above + 'ぁ'=>'a','ぇ'=>'e','ぃ'=>'i','ぉ'=>'o','ぅ'=>'u', + 'ゃ'=>'ya','ょ'=>'yo','ゅ'=>'yu', + + // 'spare' characters from other romanization systems + // 'だ'=>'da','で'=>'de','ぢ'=>'di','ど'=>'do','づ'=>'du', + // 'ら'=>'la','れ'=>'le','り'=>'li','ろ'=>'lo','る'=>'lu', + // 'さ'=>'sa','せ'=>'se','し'=>'si','そ'=>'so','す'=>'su', + // 'ちゃ'=>'cya','ちぇ'=>'cye','ちぃ'=>'cyi','ちょ'=>'cyo','ちゅ'=>'cyu', + //'じゃ'=>'jya','じぇ'=>'jye','じぃ'=>'jyi','じょ'=>'jyo','じゅ'=>'jyu', + //'りゃ'=>'lya','りぇ'=>'lye','りぃ'=>'lyi','りょ'=>'lyo','りゅ'=>'lyu', + //'しゃ'=>'sya','しぇ'=>'sye','しぃ'=>'syi','しょ'=>'syo','しゅ'=>'syu', + //'ちゃ'=>'tya','ちぇ'=>'tye','ちぃ'=>'tyi','ちょ'=>'tyo','ちゅ'=>'tyu', + //'し'=>'ci',,い'=>'yi','ぢ'=>'dzi', + //'っじゃ'=>'jja','っじぇ'=>'jje','っじ'=>'jji','っじょ'=>'jjo','っじゅ'=>'jju', + + + // Japanese katakana + + // 4 character syllables: ッ doubles the consonant after, ー doubles the vowel before (usualy written with macron, but we don't want that in our URLs) + 'ッビャー'=>'bbyaa','ッビェー'=>'bbyee','ッビィー'=>'bbyii','ッビョー'=>'bbyoo','ッビュー'=>'bbyuu', + 'ッピャー'=>'ppyaa','ッピェー'=>'ppyee','ッピィー'=>'ppyii','ッピョー'=>'ppyoo','ッピュー'=>'ppyuu', + 'ッキャー'=>'kkyaa','ッキェー'=>'kkyee','ッキィー'=>'kkyii','ッキョー'=>'kkyoo','ッキュー'=>'kkyuu', + 'ッギャー'=>'ggyaa','ッギェー'=>'ggyee','ッギィー'=>'ggyii','ッギョー'=>'ggyoo','ッギュー'=>'ggyuu', + 'ッミャー'=>'mmyaa','ッミェー'=>'mmyee','ッミィー'=>'mmyii','ッミョー'=>'mmyoo','ッミュー'=>'mmyuu', + 'ッニャー'=>'nnyaa','ッニェー'=>'nnyee','ッニィー'=>'nnyii','ッニョー'=>'nnyoo','ッニュー'=>'nnyuu', + 'ッリャー'=>'rryaa','ッリェー'=>'rryee','ッリィー'=>'rryii','ッリョー'=>'rryoo','ッリュー'=>'rryuu', + 'ッシャー'=>'sshaa','ッシェー'=>'sshee','ッシー'=>'sshii','ッショー'=>'sshoo','ッシュー'=>'sshuu', + 'ッチャー'=>'cchaa','ッチェー'=>'cchee','ッチー'=>'cchii','ッチョー'=>'cchoo','ッチュー'=>'cchuu', + + // 3 character syllables - doubled vowels + 'ファー'=>'faa','フェー'=>'fee','フィー'=>'fii','フォー'=>'foo', + 'フャー'=>'fyaa','フェー'=>'fyee','フィー'=>'fyii','フョー'=>'fyoo','フュー'=>'fyuu', + 'ヒャー'=>'hyaa','ヒェー'=>'hyee','ヒィー'=>'hyii','ヒョー'=>'hyoo','ヒュー'=>'hyuu', + 'ビャー'=>'byaa','ビェー'=>'byee','ビィー'=>'byii','ビョー'=>'byoo','ビュー'=>'byuu', + 'ピャー'=>'pyaa','ピェー'=>'pyee','ピィー'=>'pyii','ピョー'=>'pyoo','ピュー'=>'pyuu', + 'キャー'=>'kyaa','キェー'=>'kyee','キィー'=>'kyii','キョー'=>'kyoo','キュー'=>'kyuu', + 'ギャー'=>'gyaa','ギェー'=>'gyee','ギィー'=>'gyii','ギョー'=>'gyoo','ギュー'=>'gyuu', + 'ミャー'=>'myaa','ミェー'=>'myee','ミィー'=>'myii','ミョー'=>'myoo','ミュー'=>'myuu', + 'ニャー'=>'nyaa','ニェー'=>'nyee','ニィー'=>'nyii','ニョー'=>'nyoo','ニュー'=>'nyuu', + 'リャー'=>'ryaa','リェー'=>'ryee','リィー'=>'ryii','リョー'=>'ryoo','リュー'=>'ryuu', + 'シャー'=>'shaa','シェー'=>'shee','シー'=>'shii','ショー'=>'shoo','シュー'=>'shuu', + 'ジャー'=>'jaa','ジェー'=>'jee','ジー'=>'jii','ジョー'=>'joo','ジュー'=>'juu', + 'スァー'=>'swaa','スェー'=>'swee','スィー'=>'swii','スォー'=>'swoo','スゥー'=>'swuu', + 'デァー'=>'daa','デェー'=>'dee','ディー'=>'dii','デォー'=>'doo','デゥー'=>'duu', + 'チャー'=>'chaa','チェー'=>'chee','チー'=>'chii','チョー'=>'choo','チュー'=>'chuu', + 'ヂャー'=>'dyaa','ヂェー'=>'dyee','ヂィー'=>'dyii','ヂョー'=>'dyoo','ヂュー'=>'dyuu', + 'ツャー'=>'tsaa','ツェー'=>'tsee','ツィー'=>'tsii','ツョー'=>'tsoo','ツー'=>'tsuu', + 'トァー'=>'twaa','トェー'=>'twee','トィー'=>'twii','トォー'=>'twoo','トゥー'=>'twuu', + 'ドァー'=>'dwaa','ドェー'=>'dwee','ドィー'=>'dwii','ドォー'=>'dwoo','ドゥー'=>'dwuu', + 'ウァー'=>'whaa','ウェー'=>'whee','ウィー'=>'whii','ウォー'=>'whoo','ウゥー'=>'whuu', + 'ヴャー'=>'vyaa','ヴェー'=>'vyee','ヴィー'=>'vyii','ヴョー'=>'vyoo','ヴュー'=>'vyuu', + 'ヴァー'=>'vaa','ヴェー'=>'vee','ヴィー'=>'vii','ヴォー'=>'voo','ヴー'=>'vuu', + 'ウェー'=>'wee','ウィー'=>'wii', + 'イェー'=>'yee', + + // 3 character syllables - doubled consonants + 'ッビャ'=>'bbya','ッビェ'=>'bbye','ッビィ'=>'bbyi','ッビョ'=>'bbyo','ッビュ'=>'bbyu', + 'ッピャ'=>'ppya','ッピェ'=>'ppye','ッピィ'=>'ppyi','ッピョ'=>'ppyo','ッピュ'=>'ppyu', + 'ッキャ'=>'kkya','ッキェ'=>'kkye','ッキィ'=>'kkyi','ッキョ'=>'kkyo','ッキュ'=>'kkyu', + 'ッギャ'=>'ggya','ッギェ'=>'ggye','ッギィ'=>'ggyi','ッギョ'=>'ggyo','ッギュ'=>'ggyu', + 'ッミャ'=>'mmya','ッミェ'=>'mmye','ッミィ'=>'mmyi','ッミョ'=>'mmyo','ッミュ'=>'mmyu', + 'ッニャ'=>'nnya','ッニェ'=>'nnye','ッニィ'=>'nnyi','ッニョ'=>'nnyo','ッニュ'=>'nnyu', + 'ッリャ'=>'rrya','ッリェ'=>'rrye','ッリィ'=>'rryi','ッリョ'=>'rryo','ッリュ'=>'rryu', + 'ッシャ'=>'ssha','ッシェ'=>'sshe','ッシ'=>'sshi','ッショ'=>'ssho','ッシュ'=>'sshu', + 'ッチャ'=>'ccha','ッチェ'=>'cche','ッチ'=>'cchi','ッチョ'=>'ccho','ッチュ'=>'cchu', + + // 3 character syllables - doubled vowel and consonants + 'ッバー'=>'bbaa','ッベー'=>'bbee','ッビー'=>'bbii','ッボー'=>'bboo','ッブー'=>'bbuu', + 'ッパー'=>'ppaa','ッペー'=>'ppee','ッピー'=>'ppii','ッポー'=>'ppoo','ップー'=>'ppuu', + 'ッケー'=>'kkee','ッキー'=>'kkii','ッコー'=>'kkoo','ックー'=>'kkuu','ッカー'=>'kkaa', + 'ッガー'=>'ggaa','ッゲー'=>'ggee','ッギー'=>'ggii','ッゴー'=>'ggoo','ッグー'=>'gguu', + 'ッマー'=>'maa','ッメー'=>'mee','ッミー'=>'mii','ッモー'=>'moo','ッムー'=>'muu', + 'ッナー'=>'nnaa','ッネー'=>'nnee','ッニー'=>'nnii','ッノー'=>'nnoo','ッヌー'=>'nnuu', + 'ッラー'=>'rraa','ッレー'=>'rree','ッリー'=>'rrii','ッロー'=>'rroo','ッルー'=>'rruu', + 'ッサー'=>'ssaa','ッセー'=>'ssee','ッシー'=>'sshii','ッソー'=>'ssoo','ッスー'=>'ssuu', + 'ッザー'=>'zzaa','ッゼー'=>'zzee','ッジー'=>'zzii','ッゾー'=>'zzoo','ッズー'=>'zzuu', + 'ッター'=>'ttaa','ッテー'=>'ttee','ッチー'=>'chii','ットー'=>'ttoo','ッツー'=>'ttssuu', + 'ッダー'=>'ddaa','ッデー'=>'ddee','ッヂー'=>'ddii','ッドー'=>'ddoo','ッヅー'=>'dduu', + + // 2 character syllables - normal + 'ファ'=>'fa','フェ'=>'fe','フィ'=>'fi','フォ'=>'fo', + 'フャ'=>'fya','フェ'=>'fye','フィ'=>'fyi','フョ'=>'fyo','フュ'=>'fyu', + 'ヒャ'=>'hya','ヒェ'=>'hye','ヒィ'=>'hyi','ヒョ'=>'hyo','ヒュ'=>'hyu', + 'ビャ'=>'bya','ビェ'=>'bye','ビィ'=>'byi','ビョ'=>'byo','ビュ'=>'byu', + 'ピャ'=>'pya','ピェ'=>'pye','ピィ'=>'pyi','ピョ'=>'pyo','ピュ'=>'pyu', + 'キャ'=>'kya','キェ'=>'kye','キィ'=>'kyi','キョ'=>'kyo','キュ'=>'kyu', + 'ギャ'=>'gya','ギェ'=>'gye','ギィ'=>'gyi','ギョ'=>'gyo','ギュ'=>'gyu', + 'ミャ'=>'mya','ミェ'=>'mye','ミィ'=>'myi','ミョ'=>'myo','ミュ'=>'myu', + 'ニャ'=>'nya','ニェ'=>'nye','ニィ'=>'nyi','ニョ'=>'nyo','ニュ'=>'nyu', + 'リャ'=>'rya','リェ'=>'rye','リィ'=>'ryi','リョ'=>'ryo','リュ'=>'ryu', + 'シャ'=>'sha','シェ'=>'she','シ'=>'shi','ショ'=>'sho','シュ'=>'shu', + 'ジャ'=>'ja','ジェ'=>'je','ジ'=>'ji','ジョ'=>'jo','ジュ'=>'ju', + 'スァ'=>'swa','スェ'=>'swe','スィ'=>'swi','スォ'=>'swo','スゥ'=>'swu', + 'デァ'=>'da','デェ'=>'de','ディ'=>'di','デォ'=>'do','デゥ'=>'du', + 'チャ'=>'cha','チェ'=>'che','チ'=>'chi','チョ'=>'cho','チュ'=>'chu', + 'ヂャ'=>'dya','ヂェ'=>'dye','ヂィ'=>'dyi','ヂョ'=>'dyo','ヂュ'=>'dyu', + 'ツャ'=>'tsa','ツェ'=>'tse','ツィ'=>'tsi','ツョ'=>'tso','ツ'=>'tsu', + 'トァ'=>'twa','トェ'=>'twe','トィ'=>'twi','トォ'=>'two','トゥ'=>'twu', + 'ドァ'=>'dwa','ドェ'=>'dwe','ドィ'=>'dwi','ドォ'=>'dwo','ドゥ'=>'dwu', + 'ウァ'=>'wha','ウェ'=>'whe','ウィ'=>'whi','ウォ'=>'who','ウゥ'=>'whu', + 'ヴャ'=>'vya','ヴェ'=>'vye','ヴィ'=>'vyi','ヴョ'=>'vyo','ヴュ'=>'vyu', + 'ヴァ'=>'va','ヴェ'=>'ve','ヴィ'=>'vi','ヴォ'=>'vo','ヴ'=>'vu', + 'ウェ'=>'we','ウィ'=>'wi', + 'イェ'=>'ye', + + // 2 character syllables - doubled vocal + 'アー'=>'aa','エー'=>'ee','イー'=>'ii','オー'=>'oo','ウー'=>'uu', + 'ダー'=>'daa','デー'=>'dee','ヂー'=>'dii','ドー'=>'doo','ヅー'=>'duu', + 'ハー'=>'haa','ヘー'=>'hee','ヒー'=>'hii','ホー'=>'hoo','フー'=>'fuu', + 'バー'=>'baa','ベー'=>'bee','ビー'=>'bii','ボー'=>'boo','ブー'=>'buu', + 'パー'=>'paa','ペー'=>'pee','ピー'=>'pii','ポー'=>'poo','プー'=>'puu', + 'ケー'=>'kee','キー'=>'kii','コー'=>'koo','クー'=>'kuu','カー'=>'kaa', + 'ガー'=>'gaa','ゲー'=>'gee','ギー'=>'gii','ゴー'=>'goo','グー'=>'guu', + 'マー'=>'maa','メー'=>'mee','ミー'=>'mii','モー'=>'moo','ムー'=>'muu', + 'ナー'=>'naa','ネー'=>'nee','ニー'=>'nii','ノー'=>'noo','ヌー'=>'nuu', + 'ラー'=>'raa','レー'=>'ree','リー'=>'rii','ロー'=>'roo','ルー'=>'ruu', + 'サー'=>'saa','セー'=>'see','シー'=>'shii','ソー'=>'soo','スー'=>'suu', + 'ザー'=>'zaa','ゼー'=>'zee','ジー'=>'zii','ゾー'=>'zoo','ズー'=>'zuu', + 'ター'=>'taa','テー'=>'tee','チー'=>'chii','トー'=>'too','ツー'=>'tsuu', + 'ワー'=>'waa','ヲー'=>'woo', + 'ヤー'=>'yaa','ヨー'=>'yoo','ユー'=>'yuu', + 'ヱー'=>'wyee','ヰー'=>'wyii', + 'ヵー'=>'kaa','ヶー'=>'kee', + + // 2 character syllables - doubled consonants + 'ッバ'=>'bba','ッベ'=>'bbe','ッビ'=>'bbi','ッボ'=>'bbo','ッブ'=>'bbu', + 'ッパ'=>'ppa','ッペ'=>'ppe','ッピ'=>'ppi','ッポ'=>'ppo','ップ'=>'ppu', + 'ッケ'=>'kke','ッキ'=>'kki','ッコ'=>'kko','ック'=>'kku','ッカ'=>'kka', + 'ッガ'=>'gga','ッゲ'=>'gge','ッギ'=>'ggi','ッゴ'=>'ggo','ッグ'=>'ggu', + 'ッマ'=>'ma','ッメ'=>'me','ッミ'=>'mi','ッモ'=>'mo','ッム'=>'mu', + 'ッナ'=>'nna','ッネ'=>'nne','ッニ'=>'nni','ッノ'=>'nno','ッヌ'=>'nnu', + 'ッラ'=>'rra','ッレ'=>'rre','ッリ'=>'rri','ッロ'=>'rro','ッル'=>'rru', + 'ッサ'=>'ssa','ッセ'=>'sse','ッシ'=>'sshi','ッソ'=>'sso','ッス'=>'ssu', + 'ッザ'=>'zza','ッゼ'=>'zze','ッジ'=>'zzi','ッゾ'=>'zzo','ッズ'=>'zzu', + 'ッタ'=>'tta','ッテ'=>'tte','ッチ'=>'chi','ット'=>'tto','ッツ'=>'ttssu', + 'ッダ'=>'dda','ッデ'=>'dde','ッヂ'=>'ddi','ッド'=>'ddo','ッヅ'=>'ddu', + + // 1 character syllables + 'ア'=>'a','エ'=>'e','イ'=>'i','オ'=>'o','ウ'=>'u','ン'=>'n', + 'ハ'=>'ha','ヘ'=>'he','ヒ'=>'hi','ホ'=>'ho','フ'=>'fu', + 'バ'=>'ba','ベ'=>'be','ビ'=>'bi','ボ'=>'bo','ブ'=>'bu', + 'パ'=>'pa','ペ'=>'pe','ピ'=>'pi','ポ'=>'po','プ'=>'pu', + 'ケ'=>'ke','キ'=>'ki','コ'=>'ko','ク'=>'ku','カ'=>'ka', + 'ガ'=>'ga','ゲ'=>'ge','ギ'=>'gi','ゴ'=>'go','グ'=>'gu', + 'マ'=>'ma','メ'=>'me','ミ'=>'mi','モ'=>'mo','ム'=>'mu', + 'ナ'=>'na','ネ'=>'ne','ニ'=>'ni','ノ'=>'no','ヌ'=>'nu', + 'ラ'=>'ra','レ'=>'re','リ'=>'ri','ロ'=>'ro','ル'=>'ru', + 'サ'=>'sa','セ'=>'se','シ'=>'shi','ソ'=>'so','ス'=>'su', + 'ザ'=>'za','ゼ'=>'ze','ジ'=>'zi','ゾ'=>'zo','ズ'=>'zu', + 'タ'=>'ta','テ'=>'te','チ'=>'chi','ト'=>'to','ツ'=>'tsu', + 'ダ'=>'da','デ'=>'de','ヂ'=>'di','ド'=>'do','ヅ'=>'du', + 'ワ'=>'wa','ヲ'=>'wo', + 'ヤ'=>'ya','ヨ'=>'yo','ユ'=>'yu', + 'ヱ'=>'wye','ヰ'=>'wyi', + 'ヵ'=>'ka','ヶ'=>'ke', + + // convert what's left (probably only kicks in when something's missing above + 'ァ'=>'a','ェ'=>'e','ィ'=>'i','ォ'=>'o','ゥ'=>'u', + 'ャ'=>'ya','ョ'=>'yo','ュ'=>'yu', + + // 'ラ'=>'la','レ'=>'le','リ'=>'li','ロ'=>'lo','ル'=>'lu', + // 'チャ'=>'cya','チェ'=>'cye','チィ'=>'cyi','チョ'=>'cyo','チュ'=>'cyu', + //'デャ'=>'dha','デェ'=>'dhe','ディ'=>'dhi','デョ'=>'dho','デュ'=>'dhu', + // 'リャ'=>'lya','リェ'=>'lye','リィ'=>'lyi','リョ'=>'lyo','リュ'=>'lyu', + // 'テャ'=>'tha','テェ'=>'the','ティ'=>'thi','テョ'=>'tho','テュ'=>'thu', + //'ファ'=>'fwa','フェ'=>'fwe','フィ'=>'fwi','フォ'=>'fwo','フゥ'=>'fwu', + //'チャ'=>'tya','チェ'=>'tye','チィ'=>'tyi','チョ'=>'tyo','チュ'=>'tyu', + // 'ジャ'=>'jya','ジェ'=>'jye','ジィ'=>'jyi','ジョ'=>'jyo','ジュ'=>'jyu', + // 'ジャ'=>'zha','ジェ'=>'zhe','ジィ'=>'zhi','ジョ'=>'zho','ジュ'=>'zhu', + //'ジャ'=>'zya','ジェ'=>'zye','ジィ'=>'zyi','ジョ'=>'zyo','ジュ'=>'zyu', + //'シャ'=>'sya','シェ'=>'sye','シィ'=>'syi','ショ'=>'syo','シュ'=>'syu', + //'シ'=>'ci','フ'=>'hu',シ'=>'si','チ'=>'ti','ツ'=>'tu','イ'=>'yi','ヂ'=>'dzi', + + // "Greeklish" + 'Γ'=>'G','Δ'=>'E','Θ'=>'Th','Λ'=>'L','Ξ'=>'X','Π'=>'P','Σ'=>'S','Φ'=>'F','Ψ'=>'Ps', + 'γ'=>'g','δ'=>'e','θ'=>'th','λ'=>'l','ξ'=>'x','π'=>'p','σ'=>'s','φ'=>'f','ψ'=>'ps', + + // Thai + 'ก'=>'k','ข'=>'kh','ฃ'=>'kh','ค'=>'kh','ฅ'=>'kh','ฆ'=>'kh','ง'=>'ng','จ'=>'ch', + 'ฉ'=>'ch','ช'=>'ch','ซ'=>'s','ฌ'=>'ch','ญ'=>'y','ฎ'=>'d','ฏ'=>'t','ฐ'=>'th', + 'ฑ'=>'d','ฒ'=>'th','ณ'=>'n','ด'=>'d','ต'=>'t','ถ'=>'th','ท'=>'th','ธ'=>'th', + 'น'=>'n','บ'=>'b','ป'=>'p','ผ'=>'ph','ฝ'=>'f','พ'=>'ph','ฟ'=>'f','ภ'=>'ph', + 'ม'=>'m','ย'=>'y','ร'=>'r','ฤ'=>'rue','ฤๅ'=>'rue','ล'=>'l','ฦ'=>'lue', + 'ฦๅ'=>'lue','ว'=>'w','ศ'=>'s','ษ'=>'s','ส'=>'s','ห'=>'h','ฬ'=>'l','ฮ'=>'h', + 'ะ'=>'a','ั'=>'a','รร'=>'a','า'=>'a','ๅ'=>'a','ำ'=>'am','ํา'=>'am', + 'ิ'=>'i','ี'=>'i','ึ'=>'ue','ี'=>'ue','ุ'=>'u','ู'=>'u', + 'เ'=>'e','แ'=>'ae','โ'=>'o','อ'=>'o', + 'ียะ'=>'ia','ีย'=>'ia','ือะ'=>'uea','ือ'=>'uea','ัวะ'=>'ua','ัว'=>'ua', + 'ใ'=>'ai','ไ'=>'ai','ัย'=>'ai','าย'=>'ai','าว'=>'ao', + 'ุย'=>'ui','อย'=>'oi','ือย'=>'ueai','วย'=>'uai', + 'ิว'=>'io','็ว'=>'eo','ียว'=>'iao', + '่'=>'','้'=>'','๊'=>'','๋'=>'','็'=>'', + '์'=>'','๎'=>'','ํ'=>'','ฺ'=>'', + 'ๆ'=>'2','๏'=>'o','ฯ'=>'-','๚'=>'-','๛'=>'-', + '๐'=>'0','๑'=>'1','๒'=>'2','๓'=>'3','๔'=>'4', + '๕'=>'5','๖'=>'6','๗'=>'7','๘'=>'8','๙'=>'9', + + // Korean + 'ㄱ'=>'k','ㅋ'=>'kh','ㄲ'=>'kk','ㄷ'=>'t','ㅌ'=>'th','ㄸ'=>'tt','ㅂ'=>'p', + 'ㅍ'=>'ph','ㅃ'=>'pp','ㅈ'=>'c','ㅊ'=>'ch','ㅉ'=>'cc','ㅅ'=>'s','ㅆ'=>'ss', + 'ㅎ'=>'h','ㅇ'=>'ng','ㄴ'=>'n','ㄹ'=>'l','ㅁ'=>'m', 'ㅏ'=>'a','ㅓ'=>'e','ㅗ'=>'o', + 'ㅜ'=>'wu','ㅡ'=>'u','ㅣ'=>'i','ㅐ'=>'ay','ㅔ'=>'ey','ㅚ'=>'oy','ㅘ'=>'wa','ㅝ'=>'we', + 'ㅟ'=>'wi','ㅙ'=>'way','ㅞ'=>'wey','ㅢ'=>'uy','ㅑ'=>'ya','ㅕ'=>'ye','ㅛ'=>'oy', + 'ㅠ'=>'yu','ㅒ'=>'yay','ㅖ'=>'yey', + ); + } +} \ No newline at end of file diff --git a/pluf/src/Pluf/Text/Wiki/Block/Blockquote.php b/pluf/src/Pluf/Text/Wiki/Block/Blockquote.php new file mode 100644 index 0000000..5611daa --- /dev/null +++ b/pluf/src/Pluf/Text/Wiki/Block/Blockquote.php @@ -0,0 +1,76 @@ +type = 'bq'; + $this->regexp = "/^(\>+)(.*)/"; + } + + function open() { + $this->_previousTag = $this->_detectMatch[1]; + $this->_firstTagLen = strlen($this->_previousTag); + $this->_firstLine = true; + return str_repeat('
    ',$this->_firstTagLen).'

    '; + } + + function close() { + return '

    '.str_repeat('
    ',strlen($this->_previousTag)); + } + + function getRenderedLine() { + + $d=strlen($this->_previousTag) - strlen($this->_detectMatch[1]); + $str=''; + + if( $d > 0 ){ // on remonte d'un cran dans la hierarchie... + $str='

    '.str_repeat('',$d).'

    '; + $this->_previousTag=$this->_detectMatch[1]; + } + elseif( $d < 0 ) { // un niveau de plus + $this->_previousTag=$this->_detectMatch[1]; + $str='

    '.str_repeat('
    ',-$d).'

    '; + } + else { + if($this->_firstLine) + $this->_firstLine=false; + else + $str='
    '; + } + return $str.$this->_renderInlineTag($this->_detectMatch[2]); + } +} \ No newline at end of file diff --git a/pluf/src/Pluf/Text/Wiki/Block/Definition.php b/pluf/src/Pluf/Text/Wiki/Block/Definition.php new file mode 100644 index 0000000..cf6063a --- /dev/null +++ b/pluf/src/Pluf/Text/Wiki/Block/Definition.php @@ -0,0 +1,49 @@ +type = 'dfn'; + $this->regexp = "/^;(.*) : (.*)/i"; + $this->_openTag = '

    '; + $this->_closeTag ='
    '; + } + + function getRenderedLine() + { + $dt=$this->_renderInlineTag($this->_detectMatch[1]); + $dd=$this->_renderInlineTag($this->_detectMatch[2]); + return "
    $dt
    \n
    $dd
    \n"; + } +} diff --git a/pluf/src/Pluf/Text/Wiki/Block/Hr.php b/pluf/src/Pluf/Text/Wiki/Block/Hr.php new file mode 100644 index 0000000..d18abf8 --- /dev/null +++ b/pluf/src/Pluf/Text/Wiki/Block/Hr.php @@ -0,0 +1,47 @@ +type = 'hr'; + $this->regexp = '/^={4,} *$/'; + $this->_closeNow = true; + } + + function getRenderedLine() + { + return '
    '; + } + +} diff --git a/pluf/src/Pluf/Text/Wiki/Block/List.php b/pluf/src/Pluf/Text/Wiki/Block/List.php new file mode 100644 index 0000000..65c4029 --- /dev/null +++ b/pluf/src/Pluf/Text/Wiki/Block/List.php @@ -0,0 +1,95 @@ +type = 'list'; + $this->regexp = "/^([\*#-]+)(.*)/"; + } + + function open() + { + $this->_previousTag = $this->_detectMatch[1]; + $this->_firstTagLen = strlen($this->_previousTag); + $this->_firstItem=true; + + if(substr($this->_previousTag,-1,1) == '#') + return "
      \n"; + else + return "
        \n"; + } + + function close() + { + $t=$this->_previousTag; + $str=''; + + for($i=strlen($t); $i >= $this->_firstTagLen; $i--) { + $str.=($t{$i-1}== '#'?"
    \n":"\n"); + } + return $str; + } + + function getRenderedLine() + { + $t=$this->_previousTag; + $d=strlen($t) - strlen($this->_detectMatch[1]); + $str=''; + + if( $d > 0 ){ // on remonte d'un ou plusieurs cran dans la hierarchie... + $l=strlen($this->_detectMatch[1]); + for($i=strlen($t); $i>$l; $i--){ + $str.=($t{$i-1}== '#'?"\n":"\n"); + } + $str.="\n
  • "; + $this->_previousTag=substr($this->_previousTag,0,-$d); // pour être sur... + + } + elseif( $d < 0 ) { // un niveau de plus + $c=substr($this->_detectMatch[1],-1,1); + $this->_previousTag.=$c; + $str=($c == '#'?"
      \n
    1. ":"
        \n
      • "); + } + else { + $str=($this->_firstItem ? '
      • ':'
      • '); + } + $this->_firstItem=false; + return $str.$this->_renderInlineTag($this->_detectMatch[2]); + } + +} diff --git a/pluf/src/Pluf/Text/Wiki/Block/P.php b/pluf/src/Pluf/Text/Wiki/Block/P.php new file mode 100644 index 0000000..d763d77 --- /dev/null +++ b/pluf/src/Pluf/Text/Wiki/Block/P.php @@ -0,0 +1,42 @@ +type = 'p'; + $this->regexp = "/(.*)/"; + $this->_openTag = '

        '; + $this->_closeTag ='

        '; + } +} diff --git a/pluf/src/Pluf/Text/Wiki/Block/Pre.php b/pluf/src/Pluf/Text/Wiki/Block/Pre.php new file mode 100644 index 0000000..c32460a --- /dev/null +++ b/pluf/src/Pluf/Text/Wiki/Block/Pre.php @@ -0,0 +1,48 @@ +type = 'pre'; + $this->regexp = "/^ (.*)/"; + $this->_openTag = '
        ';
        +        $this->_closeTag ='
        '; + } + + function getRenderedLine() + { + return $this->_renderInlineTag($this->_detectMatch[1]); + } + +} diff --git a/pluf/src/Pluf/Text/Wiki/Block/Table.php b/pluf/src/Pluf/Text/Wiki/Block/Table.php new file mode 100644 index 0000000..5744202 --- /dev/null +++ b/pluf/src/Pluf/Text/Wiki/Block/Table.php @@ -0,0 +1,68 @@ +type = 'table'; + $this->regexp = "/^\| ?(.*)/"; + $this->_openTag = '
  • '; + $this->_closeTag = '
    '; + } + + function open() + { + $this->_colcount=0; + return $this->_openTag; + } + + function getRenderedLine() + { + $result=explode(' | ',trim($this->_detectMatch[1])); + $str=''; + $t=''; + if((count($result) != $this->_colcount) && ($this->_colcount!=0)) + $t=''; + $this->_colcount=count($result); + + for($i=0; $i < $this->_colcount; $i++) { + $str.=''; + } + $str=$t.''.$str.''; + + return $str; + } + +} diff --git a/pluf/src/Pluf/Text/Wiki/Block/Title.php b/pluf/src/Pluf/Text/Wiki/Block/Title.php new file mode 100644 index 0000000..7383588 --- /dev/null +++ b/pluf/src/Pluf/Text/Wiki/Block/Title.php @@ -0,0 +1,56 @@ +type = 'title'; + $this->regexp = "/^(\!{1,3})(.*)/"; + $this->_closeNow = true; + $cfg = $wr->getConfig(); + $this->_minlevel = $cfg->minHeaderLevel; + $this->_order = $cfg->headerOrder; + } + + function getRenderedLine() + { + if($this->_order) + $hx= $this->_minlevel + strlen($this->_detectMatch[1])-1; + else + $hx= $this->_minlevel + 3-strlen($this->_detectMatch[1]); + return ''.$this->_renderInlineTag($this->_detectMatch[2]).''; + } +} diff --git a/pluf/src/Pluf/Text/Wiki/BlockRenderer.php b/pluf/src/Pluf/Text/Wiki/BlockRenderer.php new file mode 100644 index 0000000..b152850 --- /dev/null +++ b/pluf/src/Pluf/Text/Wiki/BlockRenderer.php @@ -0,0 +1,198 @@ +engine = $wr; + } + + /** + * renvoi une chaine correspondant à l'ouverture du bloc + * @return string + * @access public + */ + + function open() { + return $this->_openTag; + } + + /** + * renvoi une chaine correspondant à la fermeture du bloc + * @return string + * @access public + */ + + function close() { + return $this->_closeTag; + } + + /** + * indique si le bloc doit etre immédiatement fermé + * @return string + * @access public + */ + + function closeNow() { + return $this->_closeNow; + } + + /** + * test si la chaine correspond au debut ou au contenu d'un bloc + * @param string $string + * @return boolean true: appartient au bloc + * @access public + */ + + function detect($string) { + return preg_match($this->regexp, $string, $this->_detectMatch); + } + + /** + * renvoi la ligne, traitée pour le bloc. A surcharger éventuellement. + * @return string + * @access public + */ + + function getRenderedLine() { + return $this->_renderInlineTag($this->_detectMatch[1]); + } + + /** + * renvoi le type du bloc en cours de traitement + * @return string + * @access public + */ + + function getType() { + return $this->type; + } + + /** + * définit la liste des élements trouvés par l'expression régulière regexp + * @return array + * @access public + */ + + function setMatch($match) { + $this->_detectMatch = $match; + } + + /** + * renvoi la liste des élements trouvés par l'expression régulière regexp + * @return array + * @access public + */ + + function getMatch() { + return $this->_detectMatch; + } + + /** + * traite le rendu des signes de type inline (qui se trouvent necessairement dans des blocs + * @param string $string une chaine contenant une ou plusieurs balises wiki + * @return string la chaine transformée en XHTML + * @access protected + * @see WikiRendererInline + */ + + function _renderInlineTag($string) { + $parser = $this->engine->getInlineParser(); + return $parser->parse($string); + } + + /** + * détection d'attributs de bloc (ex: >°°attr1|attr2|attr3°° la citation ) + * @todo à terminer pour une version ulterieure + * @access protected + */ + + function _checkAttributes(&$string) { + $bat=$this->engine->config->blocAttributeTag; + if(preg_match("/^$bat(.*)$bat(.*)$/",$string,$result)) { + $string=$result[2]; + return explode($this->engine->config->inlineTagSeparator,$result[1]); + } else + return false; + } + +} diff --git a/pluf/src/Pluf/Text/Wiki/Configuration.php b/pluf/src/Pluf/Text/Wiki/Configuration.php new file mode 100644 index 0000000..e375f81 --- /dev/null +++ b/pluf/src/Pluf/Text/Wiki/Configuration.php @@ -0,0 +1,178 @@ + array('__','__', + null,null), + 'em' => array('\'\'','\'\'', + null,null), + 'code' => array('@@','@@', + null,null), + 'q' => array('^^','^^', + array('lang','cite'), null), + 'cite' => array('{{','}}', + array('title'), null), + 'acronym'=> array('??','??', + array('title'), null), + 'link' => array('[',']', + array('href','hreflang','title'), + 'Pluf_Text_Wiki_Configuration_buildlink'), + 'image' => array('((','))', + array('src','alt','align','longdesc'), + 'Pluf_Text_Wiki_Configuration_buildimage'), + 'anchor' => array('~~','~~', + array('name'), + 'Pluf_Text_Wiki_Configuration_buildanchor') + ); + + /** + * liste des balises de type bloc autorises. Attention, ordre + * important (p en dernier, car c'est le bloc par defaut..) + */ + + public $bloctags = array( + 'Pluf_Text_Wiki_Block_Title' => true, + 'Pluf_Text_Wiki_Block_List' => true, + 'Pluf_Text_Wiki_Block_Pre' => true, + 'Pluf_Text_Wiki_Block_Hr' => true, + 'Pluf_Text_Wiki_Block_Blockquote' => true, + 'Pluf_Text_Wiki_Block_Definition' => true, + 'Pluf_Text_Wiki_Block_Table' => true, + 'Pluf_Text_Wiki_Block_P' => true + ); + + + public $simpletags = array('%%%'=>'
    ', ':-)'=>':-)'); + + /** + * @var integer niveau minimum pour les balises titres + */ + + public $minHeaderLevel=3; + + + /** + * indique le sens dans lequel il faut interpreter le nombre de + * signe de titre + * + * true -> ! = titre , !! = sous titre, !!! = sous-sous-titre + * false-> !!! = titre , !! = sous titre, ! = sous-sous-titre + */ + + public $headerOrder=false; + public $escapeSpecialChars=true; + public $inlineTagSeparator='|'; + public $blocAttributeTag=''; + + public $checkWikiWord = false; + public $checkWikiWordFunction = null; + +} + +// ===================================== +// fonctions de gnrateur de +// code HTML spcifiques certaines balises inlines +/** + * Generate a link. + * + * If the configuration variable 'wiki_create_action' is set to true and + * the URL starts with '/' and does not contains a dot '.' an action is + * created out of it, with 'app_base' as the base url. + */ +function Pluf_Text_Wiki_Configuration_buildlink($contents, $attr) +{ + $cnt = count($contents); + $attribut = ''; + if ($cnt == 0) return '[]'; + if ($cnt == 1) { + $contents[1] = $contents[0]; + if (strlen($contents[0]) > 40) { + $contents[0] = substr($contents[0], 0, 40).'(..)'; + } + $cnt = 2; + } + if ($cnt > count($attr)) { + $cnt = count($attr)+1; + } + if (strpos($contents[1], 'javascript:') !== false) { + // for security reason + $contents[1] = '#'; + } + if ('/' == $contents[1]{0} and false === strpos($contents[1], '.')) { + if (true === Pluf::f('wiki_create_action')) { + $murl = new Pluf_HTTP_URL(); + $contents[1] = Pluf::f('app_base').$murl->generate($contents[1]); + } + } + for ($i=1; $i<$cnt; $i++) { + $attribut .= ' '.$attr[$i-1].'="'.$contents[$i].'"'; + } + return ''.$contents[0].''; +} + +function Pluf_Text_Wiki_Configuration_buildanchor($contents, $attr) +{ + return ''; +} + +function Pluf_Text_Wiki_Configuration_builddummie($contents, $attr) +{ + return (isset($contents[0])?$contents[0]:''); +} + +function Pluf_Text_Wiki_Configuration_buildimage($contents, $attr) +{ + $cnt=count($contents); + $attribut=''; + if($cnt > 4) $cnt=4; + switch($cnt){ + case 4: + $attribut.=' longdesc="'.$contents[3].'"'; + case 3: + if($contents[2]=='l' ||$contents[2]=='L' || $contents[2]=='g' || $contents[2]=='G') + $attribut.=' style="float:left;"'; + elseif($contents[2]=='r' ||$contents[2]=='R' || $contents[2]=='d' || $contents[2]=='D') + $attribut.=' style="float:right;"'; + case 2: + $attribut.=' alt="'.$contents[1].'"'; + case 1: + default: + $attribut.=' src="'.$contents[0].'"'; + if($cnt == 1) $attribut.=' alt=""'; + } + return ''; + +} diff --git a/pluf/src/Pluf/Text/Wiki/InlineParser.php b/pluf/src/Pluf/Text/Wiki/InlineParser.php new file mode 100644 index 0000000..132f2b6 --- /dev/null +++ b/pluf/src/Pluf/Text/Wiki/InlineParser.php @@ -0,0 +1,207 @@ +$prop){ + $this->listTag[$prop[0]] = new Pluf_Text_Wiki_Tag($name, $prop); + + $this->splitPattern.=preg_replace ( '/([^\w\s\d])/', '\\\\\\1',$prop[0]).')|('; + if ($prop[1] != $prop[0]) + $this->splitPattern.=preg_replace ( '/([^\w\s\d])/', '\\\\\\1',$prop[1]).')|('; + } + foreach ($simpletags as $tag=>$html){ + $this->splitPattern.=preg_replace ( '/([^\w\s\d])/', '\\\\\\1',$tag).')|('; + } + + $this->simpletags = $simpletags; + $this->_separator = $separator; + $this->checkWikiWord = $checkWikiWord; + $this->checkWikiWordFunction = $funcCheckWikiWord; + $this->escapeHtml = $escapeHtml; + } + + /** + * fonction principale du parser. + * @param string $line avec des eventuels tag wiki + * @return string chaine $line avec les tags wiki transformé en HTML + */ + function parse($line) { + $this->error = false; + + $this->str = preg_split('/('.$this->splitPattern.'\\'.$this->_separator.')|(\\\\)/',$line, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + $this->end = count($this->str); + if ($this->end > 1) { + $firsttag = new Pluf_Text_Wiki_Tag('dummie',array('','', null,'Pluf_Text_Wiki_Configuration_builddummie')); + $pos=-1; + return $this->_parse($firsttag, $pos); + } + else { + if ($this->escapeHtml) { + if ($this->checkWikiWord && $this->checkWikiWordFunction !== null) + return $this->_doCheckWikiWord(htmlspecialchars($line)); + else + return htmlspecialchars($line); + } + else { + if ($this->checkWikiWord && $this->checkWikiWordFunction !== null) + return $this->_doCheckWikiWord($line); + else + return $line; + } + + } + } + + /** + * coeur du parseur. Appelé récursivement + */ + + function _parse($tag, &$posstart) { + + $checkNextTag = true; + $checkBeginTag = true; + + // on parcours la chaine, morceau aprés morceau + for($i=$posstart+1; $i < $this->end; $i++) { + + $t=&$this->str[$i]; + // a t-on un antislash ? + if ($t=='\\'){ + if ($checkNextTag){ + $t=''; // oui -> on l'efface et on ignore le tag (on continue) + $checkNextTag = false; + } + else { + $tag->addContent('\\',false); + } + + // est-ce un séparateur ? + } + elseif ($t == $this->_separator) { + if ($tag->isDummy() || !$checkNextTag) + $tag->addContent($this->_separator,false); + elseif ($tag->useSeparator()) { + $checkBeginTag = false; + $tag->addSeparator(); + } + else { + $tag->addContent($this->_separator,false); + } + // a-t-on une balise de fin du tag ? + } + elseif ($checkNextTag && $tag->getEndTag() == $t && !$tag->isDummy()) { + $posstart = $i; + return $tag->getHtmlContent(); + + // a-t-on une balise de debut de tag quelconque ? + } + elseif ($checkBeginTag && $checkNextTag && isset($this->listTag[$t]) ) { + + $content = $this->_parse(clone($this->listTag[$t]),$i); // clone indispensable sinon plantage !!! + if ($content) + $tag->addContent($content,false); + else { + if ($tag->getNumberSeparator() == 0 && $this->checkWikiWord && $this->checkWikiWordFunction !== null) { + if ($this->escapeHtml) + $tag->addContent($this->_doCheckWikiWord(htmlspecialchars($t)),false); + else + $tag->addContent($this->_doCheckWikiWord($t),false); + } + else + $tag->addContent($t,$this->escapeHtml); + } + + // a-t-on un saut de ligne forcé ? + } + elseif ($checkNextTag && $checkBeginTag && isset($this->simpletags[$t])) { + $tag->addContent($this->simpletags[$t],false); + } + else { + if ($tag->getNumberSeparator() == 0 && $this->checkWikiWord && $this->checkWikiWordFunction !== null) { + if ($this->escapeHtml) + $tag->addContent($this->_doCheckWikiWord(htmlspecialchars($t)),false); + else + $tag->addContent($this->_doCheckWikiWord($t),false); + } + else + $tag->addContent($t,$this->escapeHtml); + $checkNextTag = true; + } + } + if (!$tag->isDummy()) { + //--- on n'a pas trouvé le tag de fin + // on met en erreur + $this->error = true; + return false; + } + else + return $tag->getHtmlContent(); + } + + function _doCheckWikiWord($string) { + if (preg_match_all("/(?<=\b)[A-Z][a-z]+[A-Z0-9]\w*/", $string, $matches)){ + $fct = $this->checkWikiWordFunction; + $match = array_unique($matches[0]); // il faut avoir une liste sans doublon, à cause du str_replace plus loin... + $string = str_replace($match, $fct($match), $string); + } + return $string; + } + + function getError() { + return $this->error; + } + +} diff --git a/pluf/src/Pluf/Text/Wiki/Renderer.php b/pluf/src/Pluf/Text/Wiki/Renderer.php new file mode 100644 index 0000000..9492f7e --- /dev/null +++ b/pluf/src/Pluf/Text/Wiki/Renderer.php @@ -0,0 +1,235 @@ + + * $ctr = Pluf::factory('Pluf_Text_Wiki_Renderer'); + * $xhtml_text = $ctr->render($wiki_text); + * + */ + +class Pluf_Text_Wiki_Renderer { + + /** + * HTML version of analysed text. + */ + private $_newtext; + + private $_isBlocOpen=false; + + /** + * Current opened block element. + */ + private $_currentBloc; + + /** + * List of available blocks. + */ + private $_blocList=array(); + + /** + * List of parameters for the engine. + */ + public $params=array(); + + /** + * Inline parser for the Wiki Inline tags. + */ + public $inlineParser=null; + + /** + * List of lines with wiki errors. + */ + public $errors; + + /** + * Config object to customized the renderer. + */ + public $config=null; + + /** + * Constructor of the renderer. + * + * Create the needed objects for the rendering. + * + * @param Configuration Custom configuration object (null) + */ + function __construct($config=null) + { + if (is_null($config)) { + $this->config = new Pluf_Text_Wiki_Configuration(); + } else { + $this->config = $config; + } + // Gost block + $this->_currentBloc = new Pluf_Text_Wiki_BlockRenderer($this); + $this->inlineParser = new Pluf_Text_Wiki_InlineParser( + $this->config->inlinetags, + $this->config->simpletags, + $this->config->inlineTagSeparator, + $this->config->checkWikiWord, + $this->config->checkWikiWordFunction, + $this->config->escapeSpecialChars + ); + + foreach ($this->config->bloctags as $name=>$ok) { + if ($ok) { + $this->_blocList[] = new $name($this); + } + } + } + + /** + * Main method to convert the wiki text into XHTML. + * + * @param string Text to be converted. + * @return string Converted text into XHTML. + */ + function render($text) + { + // Split on \r (mac), \n (unix) or \r\n (windows) + $lignes = preg_split("/\015\012|\015|\012/", $text); + $this->_newtext = array(); + $this->_isBlocOpen = false; + $this->errors = false; + $this->_currentBloc = new Pluf_Text_Wiki_BlockRenderer($this); + // Go through all the lines. + foreach ($lignes as $num=>$ligne) { + if ($ligne == '') { // pas de trim cause des pre + // ligne vide + $this->_closeBloc(); + } else { + // detection de debut de bloc (liste, tableau, hr, titre) + foreach ($this->_blocList as $bloc) { + if ($bloc->detect($ligne)) { + break; + } + } + // c'est le debut d'un bloc (ou ligne d'un bloc en cours) + if ($bloc->getType() != $this->_currentBloc->getType()) { + // on ferme le precedent si c'etait un different + $this->_closeBloc(); + $this->_currentBloc = $bloc; + if($this->_openBloc()) { + $this->_newtext[] = $this->_currentBloc->getRenderedLine(); + } else { + $this->_newtext[] = $this->_currentBloc->getRenderedLine(); + $this->_newtext[] = $this->_currentBloc->close(); + $this->_isBlocOpen = false; + $this->_currentBloc = new Pluf_Text_Wiki_BlockRenderer($this); + } + } else { + $this->_currentBloc->setMatch($bloc->getMatch()); + $this->_newtext[] = $this->_currentBloc->getRenderedLine(); + } + if($this->inlineParser->getError()) { + $this->errors[$num+1] = $ligne; + } + } + } + $this->_closeBloc(); + return implode("\n", $this->_newtext); + } + + /** + * Returns configuration object. + * + * @return WikiRendererConfig + */ + function getConfig() + { + return $this->config; + } + + /** + * Retourne l'objet inlineParser (WikiInlineParser) utilis dans le moteur + * @access public + * @see WikiInlineParser + * @return WikiInlineParser + */ + function getInlineParser() + { + return $this->inlineParser; + } + + /** + * renvoi la liste des erreurs detectes par le moteur + * @access public + * @return array + */ + function getErrors() + { + return $this->errors; + } + + /** + * renvoi la version de wikirenderer + * @access public + * @return string version + */ + function getVersion() + { + return '2.1'; + } + + /** + * ferme un bloc + * @access private + */ + function _closeBloc() + { + if ($this->_isBlocOpen) { + $this->_isBlocOpen = false; + $this->_newtext[] = $this->_currentBloc->close(); + $this->_currentBloc = new Pluf_Text_Wiki_BlockRenderer($this); + } + } + + /** + * ouvre un bloc et le referme eventuellement suivant sa nature + * @return boolean indique si le bloc reste ouvert ou pas + * @access private + */ + function _openBloc() + { + if (!$this->_isBlocOpen) { + $this->_newtext[] = $this->_currentBloc->open(); + $this->_isBlocOpen = true; + return !$this->_currentBloc->closeNow(); + } else { + return true; + } + } +} diff --git a/pluf/src/Pluf/Text/Wiki/Tag.php b/pluf/src/Pluf/Text/Wiki/Tag.php new file mode 100644 index 0000000..c06c8a6 --- /dev/null +++ b/pluf/src/Pluf/Text/Wiki/Tag.php @@ -0,0 +1,131 @@ +name = $name; + $this->beginTag = $properties[0]; + $this->endTag = $properties[1]; + if ($this->name == 'dummie') + $this->isDummy = true; + + if (is_null($properties[2])) { + $this->attribute = array(); + $this->useSeparator = false; + } + else { + $this->attribute = $properties[2]; + $this->useSeparator = (count($this->attribute)>0); + } + $this->builderFunction = $properties[3]; + } + + function addContent($string, $escape=true) + { + if (!isset($this->contents[$this->separatorCount])) + $this->contents[$this->separatorCount] = ''; + + if ($escape) { + $this->contents[$this->separatorCount] .= htmlspecialchars($string); + } else { + $this->contents[$this->separatorCount] .= $string; + } + } + + function addSeparator() + { + $this->separatorCount++; + } + + function getBeginTag() + { + return $this->beginTag; + } + + function getEndTag() + { + return $this->endTag; + } + + function getNumberSeparator() + { + return $this->separatorCount; + } + + function useSeparator() + { + return $this->useSeparator; + } + + function isDummy() + { + return $this->isDummy; + } + + function getHtmlContent() + { + if (is_null($this->builderFunction)) { + $attr = ''; + if ($this->useSeparator) { + $cntattr = count($this->attribute); + $count = ($this->separatorCount > $cntattr?$cntattr:$this->separatorCount); + for ($i=1; $i<=$count; $i++) { + $attr .= ' '.$this->attribute[$i-1].'="'.$this->contents[$i].'"'; + } + } + if (isset($this->contents[0])) + return '<'.$this->name.$attr.'>'.$this->contents[0].'name.'>'; + else + return '<'.$this->name.$attr.' />'; + } + else { + $fct = $this->builderFunction; + return $fct($this->contents, $this->attribute); + } + } + +} diff --git a/pluf/src/Pluf/Translation.php b/pluf/src/Pluf/Translation.php new file mode 100644 index 0000000..7ce37de --- /dev/null +++ b/pluf/src/Pluf/Translation.php @@ -0,0 +1,321 @@ + 'plural_2gt1', + 'en' => 'plural_2not1', // This is the default. + 'de' => 'plural_2not1', + ); + + public static function loadSetLocale($lang) + { + $GLOBALS['_PX_current_locale'] = $lang; + setlocale(LC_TIME, array($lang.'.UTF-8', + $lang.'_'.strtoupper($lang).'.UTF-8')); + if (isset($GLOBALS['_PX_locale'][$lang])) { + return; // We consider that it was already loaded. + } + $GLOBALS['_PX_locale'][$lang] = array(); + foreach (Pluf::f('installed_apps') as $app) { + if (false != ($pofile=Pluf::fileExists($app.'/locale/'.$lang.'/'.strtolower($app).'.po'))) { + $GLOBALS['_PX_locale'][$lang] += Pluf_Translation::readPoFile($pofile); + } + } + } + + public static function getLocale() + { + return $GLOBALS['_PX_current_locale']; + } + + /** + * Get the plural form for a given locale. + */ + public static function getPluralForm($locale) + { + if (isset(self::$plural_forms[$locale])) { + return self::$plural_forms[$locale]; + } + if (isset(self::$plural_forms[substr($locale, 0, 2)])) { + return self::$plural_forms[substr($locale, 0, 2)]; + } + return 'plural_2not1'; + } + + /** + * Return the "best" accepted language from the list of available + * languages. + * + * Use $_SERVER['HTTP_ACCEPT_LANGUAGE'] if the accepted language + * list is empty. The list must be something like: + * 'da, en-gb;q=0.8, en;q=0.7' + * + * @param array Available languages in the system + * @param string String of comma separated accepted languages ('') + * @return string Language 2 or 5 letter iso code, default is 'en' + */ + public static function getAcceptedLanguage($available, $accepted ='') + { + if (empty($accepted)) { + if (!empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { + $accepted = $_SERVER['HTTP_ACCEPT_LANGUAGE']; + } else { + return 'en'; + } + } + $acceptedlist = explode(',', $accepted); + foreach ($acceptedlist as $lang) { + $lang = explode(';', $lang); + $lang = trim($lang[0]); + if (in_array($lang, $available)) { + return $lang; + } + // for the xx-XX cases we may have only the "main" language + // form like xx is available + $lang = substr($lang, 0, 2); + if (in_array($lang, $available)) { + return $lang; + } + } + $langs = Pluf::f('languages', array('en')); + return $langs[0]; + } + + /** + * Given a key indexed array, do replacement using the %%key%% in + * the string. + */ + public static function sprintf($string, $words=array()) + { + foreach ($words as $key=>$word) { + $string = mb_ereg_replace('%%'.$key.'%%', $word, $string, 'm'); + } + return $string; + } + + /** + * French, Brazilian Portuguese + */ + public static function plural_2gt1($n) + { + return (int) ($n>1); + } + + public static function plural_2not1($n) + { + return (int) ($n!=1); + } + + /** + * Read a .po file. + * + * Based on the work by Matthias Bauer with some little cosmetic fixes. + * + * @source http://wordpress-soc-2007.googlecode.com/svn/trunk/moeffju/php-msgfmt/msgfmt-functions.php + * @copyright 2007 Matthias Bauer + * @author Matthias Bauer + * @license http://opensource.org/licenses/lgpl-license.php GNU Lesser General Public License 2.1 + * @license http://opensource.org/licenses/apache2.0.php Apache License 2.0 + */ + public static function readPoFile($file) + { + if (false !== ($hash=self::getCachedFile($file))) { + return $hash; + } + // read .po file + $fc= file_get_contents($file); + // normalize newlines + $fc= str_replace(array("\r\n", "\r"), array("\n", "\n"), $fc); + + // results array + $hash= array (); + // temporary array + $temp= array (); + // state + $state= null; + $fuzzy= false; + + // iterate over lines + foreach (explode("\n", $fc) as $line) { + $line= trim($line); + if ($line === '') + continue; + if (false === strpos($line, ' ')) { + $key = $line; + $data = ''; + } else { + list ($key, $data)= explode(' ', $line, 2); + } + switch ($key) { + case '#,' : // flag... + $fuzzy= in_array('fuzzy', preg_split('/,\s*/', $data)); + case '#' : // translator-comments + case '#.' : // extracted-comments + case '#:' : // reference... + case '#|' : // msgid previous-untranslated-string + case '#~' : // deprecated translations + // start a new entry + if (sizeof($temp) && array_key_exists('msgid', $temp) && array_key_exists('msgstr', $temp)) { + if (!$fuzzy) + $hash[]= $temp; + $temp= array (); + $state= null; + $fuzzy= false; + } + break; + case 'msgctxt' : + // context + case 'msgid' : + // untranslated-string + case 'msgid_plural' : + // untranslated-string-plural + $state= $key; + $temp[$state]= $data; + break; + case 'msgstr' : + // translated-string + $state= 'msgstr'; + $temp[$state][]= $data; + break; + default : + if (strpos($key, 'msgstr[') !== False) { + // translated-string-case-n + $state= 'msgstr'; + $temp[$state][]= $data; + } else { + // continued lines + switch ($state) { + case 'msgctxt' : + case 'msgid' : + case 'msgid_plural' : + $temp[$state] .= "\n" . $line; + break; + case 'msgstr' : + $temp[$state][sizeof($temp[$state]) - 1] .= "\n" . $line; + break; + default : + // parse error + return False; + } + } + break; + } + } + + // add final entry + if ($state == 'msgstr') + $hash[]= $temp; + + // Cleanup data, merge multiline entries, reindex hash for ksort + $temp= $hash; + $hash= array (); + foreach ($temp as $entry) { + foreach ($entry as &$v) { + $v = Pluf_Translation_poCleanHelper($v); + if ($v === False) { + // parse error + return False; + } + } + if (isset($entry['msgid_plural'])) { + $hash[$entry['msgid'].'#'.$entry['msgid_plural']]= $entry['msgstr']; + } else { + $hash[$entry['msgid']]= $entry['msgstr']; + } + } + self::cacheFile($file, $hash); + return $hash; + } + + /** + * Load optimized version of a language file if available. + * + * @return mixed false or array with value + */ + public static function getCachedFile($file) + { + $phpfile = Pluf::f('tmp_folder').'/Pluf_L10n-'.md5($file).'.phps'; + if (file_exists($phpfile) + && (filemtime($file) < filemtime($phpfile))) { + return include $phpfile; + } + return false; + } + + /** + * Cache an optimized version of a language file. + * + * @param string File + * @param array Parsed hash + */ + public static function cacheFile($file, $hash) + { + $phpfile = Pluf::f('tmp_folder').'/Pluf_L10n-'.md5($file).'.phps'; + file_put_contents($phpfile, + '', + LOCK_EX); + @chmod($phpfile, 0666); + } +} + + +function Pluf_Translation_poCleanHelper($x) +{ + if (is_array($x)) { + foreach ($x as $k => $v) { + $x[$k]= Pluf_Translation_poCleanHelper($v); + } + } else { + if ($x[0] == '"') + $x= substr($x, 1, -1); + $x= str_replace("\"\n\"", '', $x); + $x= str_replace('$', '\\$', $x); + $x= @eval("return \"$x\";"); + } + return $x; +} diff --git a/pluf/src/Pluf/Translation/Generator.php b/pluf/src/Pluf/Translation/Generator.php new file mode 100644 index 0000000..f736237 --- /dev/null +++ b/pluf/src/Pluf/Translation/Generator.php @@ -0,0 +1,179 @@ +=0 && ($d < $maxdepth || $maxdepth < 0)) { + $result = self::list_dir($file.'/', $maxdepth, $mode, + $exclude, $d+1); + $dirlist = array_merge($dirlist, $result); + } + } + } + closedir($handle); + } + if ($d == 0) { + natcasesort($dirlist); + } + return $dirlist; + } + + + /** + * Recursive make of a directory. + * + * @credits http://php.net/mkdir + * + * @param string Directory to make + * @param octal Chmod of the directory (0777) + * @return bool Success + */ + public static function rmkdir($dir, $mode=0777) + { + if (is_dir($dir) || @mkdir($dir, $mode)) return true; + if (!self::rmkdir(dirname($dir), $mode)) return false; + return @mkdir($dir, $mode); + } + + + public static function is_pathrelative($dir) + { + if (strtoupper(substr(PHP_OS,0,3) == 'WIN')) { + return (preg_match('/^\w+:/', $dir) <= 0); + } else { + return (preg_match('/^\//', $dir) <= 0); + } + } + + public static function unifypath($path) + { + if (strtoupper(substr(PHP_OS,0,3) == 'WIN')) { + return str_replace('\\', DIRECTORY_SEPARATOR, $path); + } + return $path; + } + + + public static function real_path($path) + { + $_path = self::unifypath($path); + if (self::is_pathrelative($path)) { + $_curdir = self::unifypath(realpath('.')); + $_path = $_curdir.$_path; + } + $_startPoint = ''; + if (strtoupper(substr(PHP_OS,0,3) == 'WIN')) { + list($_startPoint, $_path) = explode(':', $_path, 2); + $_startPoint .= ':'; + } + // From now processing is the same for WIndows and Unix, + // and hopefully for others. + $_realparts = array(); + $_parts = explode(DIRECTORY_SEPARATOR, $_path); + for ($i=0; $i 0) { + array_pop($_realparts); + } + } else { + array_push($_realparts, $_parts[$i]); + } + } + return $_startPoint.DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $_realparts); + } + + + /** + * Generate the files. + */ + public function generate($outputdir) + { + $dest_files = array(); + foreach (Pluf::f('template_folders') as $folder) { + $src_files = self::list_dir($folder, -1, 'FULL'); + foreach ($src_files as $file) { + // Build an associative array where the key is the + // source file and the value is the destination file. + $dest_files[$file] = str_replace($folder, $outputdir, $file); + } + } + foreach ($dest_files as $src=>$dest) { + if (is_dir($src)) { + self::rmkdir($dest); + @chmod($dest, 0775); + print 'Create folder: '.$dest."\n"; + continue; + } + self::rmkdir(dirname($dest)); + print 'Parse to: '.$dest.'.php'; + $compiler = new Pluf_Translation_TemplateExtractor(self::real_path($src), array(''), true); + $content = $compiler->compile(); + $file = fopen($dest.'.php', 'wb'); + fwrite($file, $content); + fclose($file); + @chmod($dest.'.php', 0664); + print ' - Ok'."\n"; + continue; + } + } +} diff --git a/pluf/src/Pluf/Translation/TemplateExtractor.php b/pluf/src/Pluf/Translation/TemplateExtractor.php new file mode 100644 index 0000000..e278d01 --- /dev/null +++ b/pluf/src/Pluf/Translation/TemplateExtractor.php @@ -0,0 +1,417 @@ + 'strtoupper', + 'lower' => 'strtolower', + 'escxml' => 'htmlspecialchars', + 'escape' => 'Pluf_Template_htmlspecialchars', + 'strip_tags' => 'strip_tags', + 'escurl' => 'rawurlencode', + 'capitalize' => 'ucwords', + // Not var_export because of recursive issues. + 'debug' => 'print_r', + 'fulldebug' => 'var_export', + 'count' => 'count', + 'nl2br' => 'nl2br', + 'trim' => 'trim', + 'unsafe' => 'Pluf_Template_unsafe', + 'safe' => 'Pluf_Template_unsafe', + 'date' => 'Pluf_Template_dateFormat', + 'time' => 'Pluf_Template_timeFormat', + ); + + /** + * After the compilation is completed, this contains the list of + * modifiers used in the template. The GetCompiledTemplate method + * will add a series of Pluf::loadFunction at the top to preload + * these modifiers. + */ + public $_usedModifiers = array(); + + /** + * Default allowed extra tags/functions. + * + * These default tags are merged with the 'template_tags' defined + * in the configuration of the application. + */ + protected $_allowedTags = array( + 'url' => 'Pluf_Template_Tag_Url', + ); + /** + * During compilation, all the tags are created once so to query + * their interface easily. + */ + protected $_extraTags = array(); + + /** + * The block stack to see if the blocks are correctly closed. + */ + protected $_blockStack = array(); + + /** + * Special stack for the translation handling in blocktrans. + */ + protected $_transStack = array(); + protected $_transPlural = false; + + /** + * Current template source file. + */ + protected $_sourceFile; + + /** + * Current tag. + */ + protected $_currentTag; + + /** + * Template folders. + */ + public $templateFolders = array(); + + /** + * Template content. It can be set directly from a string. + */ + public $templateContent = ''; + + /** + * Construct the compiler. + * + * @param string Basename of the template file. + * @param array Base folders in which the templates files + * should be found. (array()) + * @param bool Load directly the template content. (true) + */ + function __construct($template_file, $folders=array(), $load=true) + { + $allowedtags = Pluf::f('template_tags', array()); + $this->_allowedTags = array_merge($allowedtags, $this->_allowedTags); + $modifiers = Pluf::f('template_modifiers', array()); + $this->_modifier = array_merge($modifiers, $this->_modifier); + + foreach ($this->_allowedTags as $name=>$model) { + $this->_extraTags[$name] = new $model(); + } + $this->_sourceFile = $template_file; + $this->_allowedInVar = array_merge($this->_vartype, $this->_op); + $this->_allowedInExpr = array_merge($this->_vartype, $this->_op); + $this->_allowedAssign = array_merge($this->_vartype, $this->_assignOp, + $this->_op); + $this->templateFolders = $folders; + if ($load) { + $this->loadTemplateFile($template_file); + } + } + + /** + * Get blocktrans. + */ + function getBlockTrans() + { + $tplcontent = $this->templateContent; + $tplcontent = preg_replace('!{\*(.*?)\*}!s', '', $tplcontent); + $match = array(); + preg_match_all('!{blocktrans(.*?){/blocktrans}!s', $tplcontent, $match); + $res = array(); + foreach ($match[1] as $m) { + $res[] = '{blocktrans'.$m.'{/blocktrans}'; + } + return $res; + } + + /** + * Get simple trans call. + */ + function getSimpleTrans() + { + $tplcontent = $this->templateContent; + $tplcontent = preg_replace('!{\*(.*?)\*}!s', '', $tplcontent); + $match = array(); + preg_match_all('!{trans(.*?)}!s', $tplcontent, $match); + $res = array(); + foreach ($match[1] as $m) { + $res[] = '{trans'.$m.'}'; + } + return $res; + } + + /** + * Compile the template into a file ready to parse with xgettext. + * + * @return string PHP code of the compiled template. + */ + function compile() + { + $result = ''; + $blocktrans = $this->getBlockTrans(); + // Parse the blocktrans + foreach ($blocktrans as $block) { + $match = array(); + if (preg_match('!{blocktrans(.*?)}(.*?){plural}(.*?){/blocktrans}!s', $block, $match)) { + $sing = $match[2]; + $plural = $match[3]; + $sing = preg_replace_callback('/{((.).*?)}/s', + array($this, '_callbackInTransBlock'), + $sing); + $plural = preg_replace_callback('/{((.).*?)}/s', + array($this, '_callbackInTransBlock'), + $plural); + $result .= '_n(\''.addcslashes($sing, "'").'\', \''.addcslashes($plural, "'").'\', $n);'."\n"; + } elseif (preg_match('!{blocktrans}(.*?){/blocktrans}!s', $block, $match)) { + $sing = preg_replace_callback('/{((.).*?)}/s', + array($this, '_callbackInTransBlock'), + $match[1]); + $result .= '__(\''.addcslashes($sing, "'").'\');'."\n"; + } + } + + $simpletrans = $this->getSimpleTrans(); + foreach ($simpletrans as $content) { + $result .= preg_replace_callback('/{((.).*?)}/s', + array($this, '_callback'), + $content); + } + return ''; + } + + + /** + * Load a template file. + * + * The path to the file to load is relative and the file is found + * in one of the $templateFolders array of folders. + * + * @param string Relative path of the file to load. + */ + function loadTemplateFile($file) + { + // FIXME: Very small security check, could be better. + if (strpos($file, '..') !== false) { + throw new Exception(sprintf(__('Template file contains invalid characters: %s'), $file)); + } + foreach ($this->templateFolders as $folder) { + if (file_exists($folder.'/'.$file)) { + $this->templateContent = file_get_contents($folder.'/'.$file); + return; + } + } + // File not found in all the folders. + throw new Exception(sprintf(__('Template file not found: %s'), $file)); + } + + function _callback($matches) + { + list(,$tag, $firstcar) = $matches; + if ($firstcar != 't') { + trigger_error(sprintf(__('Invalid tag in translation extractor: %s'), $tag), E_USER_ERROR); + return ''; + } + $this->_currentTag = $tag; + if (!preg_match('/^(\/?[a-zA-Z0-9_]+)(?:(?:\s+(.*))|(?:\((.*)\)))?$/', $tag, $m)) { + trigger_error(sprintf(__('Invalid function syntax: %s'), $tag), E_USER_ERROR); + return ''; + } + if (count($m) == 4){ + $m[2] = $m[3]; + } + if (!isset($m[2])) $m[2] = ''; + if ($m[1] == 'trans') { + return $this->_parseFunction($m[1], $m[2]); + } + return ''; + } + + function _callbackInTransBlock($matches) + { + list(,$tag, $firstcar) = $matches; + if (!preg_match('/^\$|[\'"]|[a-zA-Z\/]$/', $firstcar)) { + trigger_error(sprintf(__('Invalid tag syntax: %s'), $tag), E_USER_ERROR); + return ''; + } + $this->_currentTag = $tag; + if ($firstcar == '$') { + $tok = explode('|', $tag); + $this->_transStack[substr($tok[0], 1)] = $this->_parseVariable($tag); + return '%%'.substr($tok[0], 1).'%%'; + } + return ''; + } + + function _parseVariable($expr) + { + $tok = explode('|', $expr); + $res = $this->_parseFinal(array_shift($tok), $this->_allowedInVar); + // We do not take into account the modifiers. + return $res; + } + + function _parseFunction($name, $args) + { + switch ($name) { + case 'trans': + $argfct = $this->_parseFinal($args, $this->_allowedAssign); + $res = '__('.$argfct.');'."\n"; + break; + default: + $res = ''; + break; + } + return $res; + } + + /* + + ------- + if: op, autre, var + foreach: T_AS, T_DOUBLE_ARROW, T_VARIABLE, @locale@ + for: autre, fin_instruction + while: op, autre, var + assign: T_VARIABLE puis assign puis autre, ponctuation, T_STRING + echo: T_VARIABLE/@locale@ puis autre + ponctuation + modificateur: serie de autre séparé par une virgule + + tous : T_VARIABLE, @locale@ + + */ + + function _parseFinal($string, $allowed=array(), + $exceptchar=array(';')) + { + $tokens = token_get_all(''); + $result = ''; + $first = true; + $inDot = false; + $firstok = array_shift($tokens); + $afterAs = false; + $f_key = ''; + $f_val = ''; + $results = array(); + + // il y a un bug, parfois le premier token n'est pas T_OPEN_TAG... + if ($firstok == '<' && $tokens[0] == '?' && is_array($tokens[1]) + && $tokens[1][0] == T_STRING && $tokens[1][1] == 'php') { + array_shift($tokens); + array_shift($tokens); + } + foreach ($tokens as $tok) { + if (is_array($tok)) { + list($type, $str) = $tok; + $first = false; + if($type == T_CLOSE_TAG){ + continue; + } + if ($type == T_AS) { + $afterAs = true; + } + if ($inDot) { + $result .= $str; + } elseif ($type == T_VARIABLE) { + $result .= '$t->_vars[\''.substr($str, 1).'\']'; + } elseif ($type == T_WHITESPACE || in_array($type, $allowed)) { + $result .= $str; + } else { + trigger_error(sprintf(__('Invalid syntax: (%s) %s.'), $this->_currentTag, $str), E_USER_ERROR); + return ''; + } + } else { + if (in_array($tok, $exceptchar)) { + trigger_error(sprintf(__('Invalid character: (%s) %s.'), $this->_currentTag, $tok), E_USER_ERROR); + } elseif ($tok == '.') { + $inDot = true; + $result .= '->'; + } elseif ($tok == '~') { + $result .= '.'; + } elseif ($tok =='[') { + $result.=$tok; + } elseif ($tok ==']') { + $result.=$tok; + } elseif ($getAsArray && $tok == ',') { + $results[]=$result; + $result=''; + } else { + $result .= $tok; + } + $first = false; + } + } + return $result; + } +} + diff --git a/pluf/src/Pluf/User.php b/pluf/src/Pluf/User.php new file mode 100644 index 0000000..8a8d17f --- /dev/null +++ b/pluf/src/Pluf/User.php @@ -0,0 +1,471 @@ +_a['verbose'] = __('user'); + $this->_a['table'] = 'users'; + $this->_a['model'] = 'Pluf_User'; + $this->_a['cols'] = array( + // It is mandatory to have an "id" column. + 'id' => + array( + 'type' => 'Pluf_DB_Field_Sequence', + //It is automatically added. + 'blank' => true, + ), + 'login' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'unique' => true, + 'size' => 50, + 'verbose' => __('login'), + ), + 'first_name' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => true, + 'size' => 100, + 'verbose' => __('first name'), + ), + 'last_name' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => false, + 'size' => 100, + 'verbose' => __('last name'), + ), + 'email' => + array( + 'type' => 'Pluf_DB_Field_Email', + 'blank' => false, + 'verbose' => __('email'), + ), + 'password' => + array( + 'type' => 'Pluf_DB_Field_Password', + 'blank' => false, + 'verbose' => __('password'), + 'size' => 150, + 'help_text' => __('Format: [algo]:[salt]:[hash]') + ), + 'groups' => + array( + 'type' => 'Pluf_DB_Field_Manytomany', + 'blank' => true, + 'model' => Pluf::f('pluf_custom_group','Pluf_Group'), + 'relate_name' => 'users', + ), + 'permissions' => + array( + 'type' => 'Pluf_DB_Field_Manytomany', + 'blank' => true, + 'model' => 'Pluf_Permission', + ), + 'administrator' => + array( + 'type' => 'Pluf_DB_Field_Boolean', + 'default' => false, + 'blank' => true, + 'verbose' => __('administrator'), + ), + 'staff' => + array( + 'type' => 'Pluf_DB_Field_Boolean', + 'default' => false, + 'blank' => true, + 'verbose' => __('staff'), + ), + 'active' => + array( + 'type' => 'Pluf_DB_Field_Boolean', + 'default' => true, + 'blank' => true, + 'verbose' => __('active'), + ), + 'language' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => true, + 'default' => $langs[0], + 'size' => 5, + 'verbose' => __('language'), + 'help_text' => __('Prefered language of the user for the interface. Use the 2 or 5 letter code like "fr", "en", "fr_QC" or "en_US".') + ), + 'timezone' => + array( + 'type' => 'Pluf_DB_Field_Varchar', + 'blank' => true, + 'default' => 'America/Chicago', + 'size' => 45, + 'verbose' => __('time zone'), + 'help_text' => __('Time zone of the user to display the time in local time.') + ), + 'date_joined' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('date joined'), + 'editable' => false, + ), + 'last_login' => + array( + 'type' => 'Pluf_DB_Field_Datetime', + 'blank' => true, + 'verbose' => __('last login'), + 'editable' => false, + ), + ); + $this->_a['idx'] = array( + 'login_idx' => + array( + 'col' => 'login', + 'type' => 'unique', + ), + ); + $this->_a['views'] = array(); + if (Pluf::f('pluf_custom_user',false)) $this->extended_init(); + } + + /** + * Hook for extended class + */ + function extended_init() + { + return; + } + + /** + * String representation of the user. + */ + function __toString() + { + $repr = $this->last_name; + if (strlen($this->first_name) > 0) { + $repr = $this->first_name.' '.$repr; + } + return $repr; + } + + /** + * Predelete to drop the row level permissions. + */ + function preDelete() + { + /** + * [signal] + * + * Pluf_User::preDelete + * + * [sender] + * + * Pluf_User + * + * [description] + * + * This signal allows an application to perform special + * operations at the deletion of a user. + * + * [parameters] + * + * array('user' => $user) + * + */ + $params = array('user' => $this); + Pluf_Signal::send('Pluf_User::preDelete', + 'Pluf_User', $params); + + if (Pluf::f('pluf_use_rowpermission', false)) { + $_rpt = Pluf::factory('Pluf_RowPermission')->getSqlTable(); + $sql = new Pluf_SQL('owner_class=%s AND owner_id=%s', + array($this->_a['model'], $this->_data['id'])); + $this->_con->execute('DELETE FROM '.$_rpt.' WHERE '.$sql->gen()); + } + } + + /** + * Set the password of a user. + * + * You need to manually save the user to store the password in the + * database. The supported algorithms are md5, crc32 and sha1, + * sha1 being the default. + * + * @param string New password + * @return bool Success + */ + function setPassword($password) + { + //$salt = Pluf_Utils::getRandomString(5); + //$this->password = 'sha1:'.$salt.':'.sha1($salt.$password); + //$this->password = sha1($password); + //file_put_contents("/tmp/test", $password); + $this->password = base64_encode(sha1($password, TRUE)); + return true; + } + + /** + * Check if the password of a user matches with the one in the database. + * + * @param string Password + * @return bool True if success + */ + function checkPassword($password) + { + if ($this->password == '') { + return false; + } + if ($this->password == base64_encode(sha1($password, TRUE))) + return true; + else + return false; + /*list($algo, $salt, $hash) = explode(':', $this->password); + if ($hash == $algo($salt.$password)) { + return true; + } else { + return false; + }*/ + } + + /** + * Check if the login creditentials are valid. + * + * @param string Login + * @param string Password + * @return mixed False or matching user + */ + function checkCreditentials($login, $password) + { + $where = 'login = '.$this->_toDb($login, 'login'); + $users = $this->getList(array('filter' => $where)); + if ($users === false or count($users) !== 1) { + return false; + } + if ($users[0]->active and $users[0]->checkPassword($password)) { + return $users[0]; + } + return false; + } + + /** + * Set the last_login and date_joined before creating. + * + */ + function preSave($create=false) + { + if (!($this->id > 0)) { + $this->last_login = gmdate('Y-m-d H:i:s'); + $this->date_joined = gmdate('Y-m-d H:i:s'); + } + } + + /** + * Check if a user is anonymous. + * + * @return bool True if the user is anonymous. + */ + function isAnonymous() + { + return (0 === (int) $this->id); + } + + /** + * Get all the permissions of a user. + * + * @param bool Force the reload of the list of permissions (false) + * @return array List of permissions + */ + function getAllPermissions($force=false) + { + if ($force==false and !is_null($this->_cache_perms)) { + return $this->_cache_perms; + } + $this->_cache_perms = array(); + $perms = (array) $this->get_permissions_list(); + $groups = $this->get_groups_list(); + $ids = array(); + foreach ($groups as $group) { + $ids[] = $group->id; + } + if (count($ids) > 0) { + $gperm = new Pluf_Permission(); + $f_name = strtolower(Pluf::f('pluf_custom_group', 'Pluf_Group')).'_id'; + $perms = array_merge($perms, (array) $gperm->getList(array('filter' => $f_name.' IN ('.join(', ', $ids).')', + 'view' => 'join_group'))); + } + foreach ($perms as $perm) { + if (!in_array($perm->application.'.'.$perm->code_name, $this->_cache_perms)) { + $this->_cache_perms[] = $perm->application.'.'.$perm->code_name; + } + } + if (Pluf::f('pluf_use_rowpermission', false) and $this->id) { + $growp = new Pluf_RowPermission(); + $sql = new Pluf_SQL('owner_id=%s AND owner_class=%s', + array($this->id, 'Pluf_User')); + if (count($ids) > 0) { + $sql2 = new Pluf_SQL('owner_id IN ('.join(', ', $ids).') AND owner_class=%s', + array(Pluf::f('pluf_custom_group','Pluf_Group'))); + $sql->SOr($sql2); + } + $perms = $growp->getList(array('filter' => $sql->gen(), + 'view' => 'join_permission')); + foreach ($perms as $perm) { + $perm_string = $perm->application.'.'.$perm->code_name.'#'.$perm->model_class.'('.$perm->model_id.')'; + if ($perm->negative) { + $perm_string = '!'.$perm_string; + } + if (!in_array($perm_string, $this->_cache_perms)) { + $this->_cache_perms[] = $perm_string; + } + } + } + return $this->_cache_perms; + } + + /** + * Check if a user as a permission. + * + * @param string Permission + * @param Object Object for row level permission (null) + * @return bool True if the user has the permission. + */ + function hasPerm($perm, $obj=null) + { + if (!$this->active) + return false; + if ($this->administrator) + return true; + $perms = $this->getAllPermissions(); + if (!is_null($obj)) { + $perm_row = $perm.'#'.$obj->_a['model'].'('.$obj->id.')'; + if (in_array('!'.$perm_row, $perms)) + return false; + if (in_array($perm_row, $perms)) + return true; + } + if (in_array($perm, $perms)) + return true; + return false; + } + + /** + * Check if a user one or more application permission. + * + * @return bool True if the user has some. + */ + function hasAppPerms($app) + { + if ($this->administrator) + return true; + foreach ($this->getAllPermissions() as $perm) { + if (0 === strpos($perm, $app.'.')) { + return true; + } + } + return false; + } + + /** + * Set a message. + * + * The user must not be anonymous. + * + * @param string Message + * @return bool Success + */ + function setMessage($message) + { + if ($this->isAnonymous()) { + return false; + } + $m = new Pluf_Message(); + $m->user = $this; + $m->message = $message; + return $m->create(); + } + + /** + * Get messages and delete them. + * + * The user must not be anonymous. + * + * @return mixed False if anonymous, else ArrayObject + */ + function getAndDeleteMessages() + { + if ($this->isAnonymous()) { + return false; + } + $messages = new ArrayObject(); + $ms = $this->get_pluf_message_list(); + foreach ($ms as $m) { + $messages[] = $m->message; + $m->delete(); + } + return $messages; + } + + /** + * Get profile. + * + * Retrieve the profile of the current user. If not profile in the + * database a Pluf_Exception_DoesNotExist exception is thrown, + * just catch it and create a profile. + * + * @return Pluf_Model User profile + */ + function getProfile() + { + $pclass = Pluf::f('user_profile_class', false); + if (false == $pclass) { + throw new Pluf_Exception_SettingError(__('"user_profile_class" setting not defined.')); + } + $db = $this->getDbConnection(); + $sql = new Pluf_SQL(sprintf('%s=%%s', $db->qn('user')), + array($this->id)); + $users = Pluf::factory($pclass)->getList(array('filter' => $sql->gen())); + if ($users->count() != 1) { + throw new Pluf_Exception_DoesNotExist(sprintf(__('No profiles available for user: %s'), (string) $this)); + } + return $users[0]; + } +} diff --git a/pluf/src/Pluf/Utils.php b/pluf/src/Pluf/Utils.php new file mode 100644 index 0000000..95d4765 --- /dev/null +++ b/pluf/src/Pluf/Utils.php @@ -0,0 +1,308 @@ + (1000*1000*1000)) { + $mysize = sprintf('%01.2f', $size/(1000*1000*1000)).' '. __('GB'); + } elseif ($size > (1000*1000)) { + $mysize = sprintf('%01.2f', $size/(1000*1000)).' '. __('MB'); + } elseif ($size >= 1000) { + $mysize = sprintf('%01.2f', $size/1000).' '.__('kB'); + } else { + $mysize = sprintf(_n('%d byte', '%d bytes', $size), $size); + } + return $mysize; + } + + /** + * RFC(2)822 Email Parser + * + * By Cal Henderson + * This code is licensed under a Creative Commons + * Attribution-ShareAlike 2.5 License + * http://creativecommons.org/licenses/by-sa/2.5/ + * Revision 5 - http://www.iamcal.com/publish/articles/php/parsing_email/ + * + * Comments were stripped, check the source for the way this + * parser is built. It is a very interesting reading. + * + * @param string Email + * @return bool Is email + */ + static function isValidEmail($email) + { + $email = trim($email); + $n = explode(' ', $email); + if (count($n) > 1) { + return false; + } + $no_ws_ctl = "[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]"; + $alpha = "[\\x41-\\x5a\\x61-\\x7a]"; + $digit = "[\\x30-\\x39]"; + $cr = "\\x0d"; + $lf = "\\x0a"; + $crlf = "($cr$lf)"; + $obs_char = "[\\x00-\\x09\\x0b\\x0c\\x0e-\\x7f]"; + $obs_text = "($lf*$cr*($obs_char$lf*$cr*)*)"; + $text = "([\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f]|$obs_text)"; + $obs_qp = "(\\x5c[\\x00-\\x7f])"; + $quoted_pair = "(\\x5c$text|$obs_qp)"; + $wsp = "[\\x20\\x09]"; + $obs_fws = "($wsp+($crlf$wsp+)*)"; + $fws = "((($wsp*$crlf)?$wsp+)|$obs_fws)"; + $ctext = "($no_ws_ctl|[\\x21-\\x27\\x2A-\\x5b\\x5d-\\x7e])"; + $ccontent = "($ctext|$quoted_pair)"; + $comment = "(\\x28($fws?$ccontent)*$fws?\\x29)"; + $cfws = "(($fws?$comment)*($fws?$comment|$fws))"; + $cfws = "$fws*"; + $atext = "($alpha|$digit|[\\x21\\x23-\\x27\\x2a\\x2b\\x2d\\x2f\\x3d\\x3f\\x5e\\x5f\\x60\\x7b-\\x7e])"; + $atom = "($cfws?$atext+$cfws?)"; + $qtext = "($no_ws_ctl|[\\x21\\x23-\\x5b\\x5d-\\x7e])"; + $qcontent = "($qtext|$quoted_pair)"; + $quoted_string = "($cfws?\\x22($fws?$qcontent)*$fws?\\x22$cfws?)"; + $word = "($atom|$quoted_string)"; + $obs_local_part = "($word(\\x2e$word)*)"; + $obs_domain = "($atom(\\x2e$atom)*)"; + $dot_atom_text = "($atext+(\\x2e$atext+)*)"; + $dot_atom = "($cfws?$dot_atom_text$cfws?)"; + $dtext = "($no_ws_ctl|[\\x21-\\x5a\\x5e-\\x7e])"; + $dcontent = "($dtext|$quoted_pair)"; + $domain_literal = "($cfws?\\x5b($fws?$dcontent)*$fws?\\x5d$cfws?)"; + $local_part = "($dot_atom|$quoted_string|$obs_local_part)"; + $domain = "($dot_atom|$domain_literal|$obs_domain)"; + $addr_spec = "($local_part\\x40$domain)"; + + $done = 0; + while(!$done){ + $new = preg_replace("!$comment!", '', $email); + if (strlen($new) == strlen($email)){ + $done = 1; + } + $email = $new; + } + return preg_match("!^$addr_spec$!", $email) ? true : false; + } + + /** + * Validate an url. + * Only the structure is checked, no check of availability of the + * url is performed. It is a really basic validation. + */ + static function isValidUrl($url) + { + $ip = '(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.' + .'(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}'; + $dom = '([a-z0-9\.\-]+)'; + return (preg_match('!^(http|https|ftp|gopher)\://('.$ip.'|'.$dom.')!i', $url)) ? true : false; + } + + + /** + * Convert a whatever separated list of items and returns an array + * of them. + * + * @param string Items. + * @param string Separator (',') + * @return array Items. + */ + static function itemsToArray($items, $sep=',') + { + $_t = explode($sep, $items); + $res = array(); + foreach ($_t as $item) { + $item = trim($item); + if (strlen($item) > 0) { + $res[] = $item; + } + } + return $res; + } + + /** + * Run an external program capturing both stdout and stderr. + * + * @credits dk at brightbyte dot de + * @source http://www.php.net/manual/en/function.shell-exec.php + * @see proc_open + * + * @param string Command to run (will be passed to proc_open) + * @param &int Return code of the command + * @return mixed false in case of error or output string + */ + public static function runExternal($cmd, &$code) + { + $descriptorspec = array( + // stdin is a pipe that the child will read from + 0 => array('pipe', 'r'), + // stdout is a pipe that the child will write to + 1 => array('pipe', 'w'), + // stderr is a file to write to + 2 => array('pipe', 'w')); + $pipes= array(); + $process = proc_open($cmd, $descriptorspec, $pipes); + $output= ''; + if (!is_resource($process)) return false; + fclose($pipes[0]); //close child's input imidiately + stream_set_blocking($pipes[1], false); + stream_set_blocking($pipes[2], false); + $todo = array($pipes[1], $pipes[2]); + while (true) { + $read = array(); + if(!feof($pipes[1])) $read[] = $pipes[1]; + if(!feof($pipes[2])) $read[] = $pipes[2]; + if (!$read) break; + $write = $ex = array(); + $ready= stream_select($read, $write, $ex, 2); + if ($ready === false) { + break; // should never happen - something died + } + foreach ($read as $r) { + $s = fread($r,1024); + $output .= $s; + } + } + fclose($pipes[1]); + fclose($pipes[2]); + $code = proc_close($process); + return $output; + } + + /** + * URL safe base 64 encoding. + * + * Compatible with python base64's urlsafe methods. + * + * @link http://www.php.net/manual/en/function.base64-encode.php#63543 + */ + public static function urlsafe_b64encode($string) + { + return str_replace(array('+','/','='), + array('-','_',''), + base64_encode($string)); + } + + /** + * URL safe base 64 decoding. + */ + public static function urlsafe_b64decode($string) + { + $data = str_replace(array('-','_'), + array('+','/'), + $string); + $mod4 = strlen($data) % 4; + if ($mod4) { + $data .= substr('====', $mod4); + } + return base64_decode($data); + } + + /** + * Flatten an array. + * + * @param array $array The array to flatten. + * @return array + */ + public static function flattenArray($array) + { + $result = array(); + foreach (new RecursiveIteratorIterator(new RecursiveArrayIterator($array)) as $value) { + $result[] = $value; + } + + return $result; + } + +} diff --git a/pluf/src/Pluf/Views.php b/pluf/src/Pluf/Views.php new file mode 100644 index 0000000..27094df --- /dev/null +++ b/pluf/src/Pluf/Views.php @@ -0,0 +1,367 @@ +REQUEST['_redirect_after'])) { + $success_url = $request->REQUEST['_redirect_after']; + } + $error = ''; + if ($request->method == 'POST') { + foreach (Pluf::f('auth_backends', array('Pluf_Auth_ModelBackend')) + as $backend) { + $user = call_user_func(array($backend, 'authenticate'), + $request->POST); + if ($user !== false) { + break; + } + } + if (false === $user) { + $error = __('The login or the password is not valid. The login and the password are case sensitive.'); + } else { + if (!$request->session->getTestCookie()) { + $error = __('You need to enable the cookies in your browser to access this website.'); + } else { + $request->user = $user; + $request->session->clear(); + $request->session->setData('login_time', gmdate('Y-m-d H:i:s')); + $user->last_login = gmdate('Y-m-d H:i:s'); + $user->update(); + $request->session->deleteTestCookie(); + return new Pluf_HTTP_Response_Redirect($success_url); + } + } + } + // Show the login form + $request->session->createTestCookie(); + $context = new Pluf_Template_Context_Request($request, + array_merge(array( + 'page_title' => __('Sign In'), + '_redirect_after' => $success_url, + 'error' => $error), $extra_context)); + $tmpl = new Pluf_Template($template); + return new Pluf_HTTP_Response($tmpl->render($context)); + } + + /** + * Logout the user. + * + * The success url is either an absolute url starting with + * http(s):// or considered as an action. + * + * @param Request Request object + * @param array Match + * @param string Default redirect URL after login '/' + * @return Response object + */ + function logout($request, $match, $success_url='/') + { + $user_model = Pluf::f('pluf_custom_user','Pluf_User'); + $request->user = new $user_model(); + $request->session->clear(); + $request->session->setData('logout_time', gmdate('Y-m-d H:i:s')); + if (0 !== strpos($success_url, 'http')) { + $murl = new Pluf_HTTP_URL(); + $success_url = Pluf::f('app_base').$murl->generate($success_url); + } + return new Pluf_HTTP_Response_Redirect($success_url); + } + + + /** + * Create an object (Part of the CRUD series). + * + * The minimal extra parameter is the model class name. The list + * of extra parameters is: + * + * 'model' - Class name string, required. + * + * 'extra_context' - Array of key/values to be added to the + * context (array()) + * + * 'extra_form' - Array of key/values to be added to the + * form generation (array()) + * + * 'login_required' - Do we require login (false) + * + * 'template' - Template to use ('"model class"_create_form.html') + * + * 'post_save_redirect' - View to redirect after saving (use + * getAbsoluteUrl() method of the mode) + * + * 'post_save_redirect_keys' - Which keys of the model to pass to + * the view (array('id')) + * + * @param Pluf_HTTP_Request Request object + * @param array Match + * @param array Extra parameters + * @return Pluf_HTTP_Response Response object (can be a redirect) + */ + public function createObject($request, $match, $p) + { + $default = array( + 'extra_context' => array(), + 'extra_form' => array(), + 'login_required' => false, + ); + $p = array_merge($default, $p); + if (isset($p['login_required']) && true == $p['login_required']) { + if ($request->user->isAnonymous()) { + return new Pluf_HTTP_Response_RedirectToLogin($request); + } + } + if (!isset($p['model'])) { + throw new Exception('The model class was not provided in the parameters.'); + } + // Set the default + $model = $p['model']; + $context = (isset($p['extra_context'])) ? $p['extra_context'] : array(); + $template = (isset($p['template'])) ? $p['template'] : strtolower($model).'_create_form.html'; + $post_save_keys = (isset($p['post_save_redirect_keys'])) ? $p['post_save_redirect_keys'] : array('id'); + + + $object = new $model(); + if ($request->method == 'POST') { + $form = Pluf_Shortcuts_GetFormForModel($object, $request->POST, $p['extra_form']); + if ($form->isValid()) { + $object = $form->save(); + if (isset($p['post_save_redirect'])) { + $url = Pluf_HTTP_URL_urlForView($p['post_save_redirect'], + $post_save_keys); + } elseif (in_array('getAbsoluteUrl', + get_class_methods($object))) { + $url = $object->getAbsoluteUrl(); + } else { + throw new Exception('No URL to redirect to from generic create view.'); + } + if (!$request->user->isAnonymous()) { + $request->user->setMessage(sprintf(__('The %s was created successfully.'), $object->_a['verbose'])); + } + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $form = Pluf_Shortcuts_GetFormForModel($object, null, $p['extra_form']); + } + return Pluf_Shortcuts_RenderToResponse($template, + array_merge($context, + array('form' => $form)), + $request); + } + + /** + * Update an object (Part of the CRUD series). + * + * The minimal extra parameter is the model class name. The list + * of extra parameters is: + * + * 'model' - Class name string, required. + * + * 'model_id' - Id of of the current model to update + * + * 'extra_context' - Array of key/values to be added to the + * context (array()) + * + * 'extra_form' - Array of key/values to be added to the + * form generation (array()) + * + * 'login_required' - Do we require login (false) + * + * 'template' - Template to use ('"model class"_update_form.html') + * + * 'post_save_redirect' - View to redirect after saving (use + * getAbsoluteUrl() method of the mode) + * + * 'post_save_redirect_keys' - Which keys of the model to pass to + * the view (array('id')) + * + * @param Pluf_HTTP_Request Request object + * @param array Match + * @param array Extra parameters + * @return Pluf_HTTP_Response Response object (can be a redirect) + */ + public function updateObject($request, $match, $p) + { + if (isset($p['login_required']) && true == $p['login_required']) { + if ($request->user->isAnonymous()) { + return new Pluf_HTTP_Response_RedirectToLogin($request); + } + } + if (!isset($p['model'])) { + throw new Exception('The model class was not provided in the parameters.'); + } + // Set the default + $model = $p['model']; + $model_id = $p['model_id']; + $context = (isset($p['extra_context'])) ? $p['extra_context'] : array(); + $template = (isset($p['template'])) ? $p['template'] : strtolower($model).'_update_form.html'; + $post_save_keys = (isset($p['post_save_redirect_keys'])) ? $p['post_save_redirect_keys'] : array('id'); + + $object = Pluf_Shortcuts_GetObjectOr404($model, $model_id); + if ($request->method == 'POST') { + $form = Pluf_Shortcuts_GetFormForModel($object, $request->POST, $p['extra_form']); + if ($form->isValid()) { + $object = $form->save(); + if (isset($p['post_save_redirect'])) { + $url = Pluf_HTTP_URL_urlForView($p['post_save_redirect'], + $post_save_keys); + } elseif (in_array('getAbsoluteUrl', + get_class_methods($object))) { + $url = $object->getAbsoluteUrl(); + } else { + throw new Exception('No URL to redirect to from generic create view.'); + } + if (!$request->user->isAnonymous()) { + $request->user->setMessage(sprintf(__('The %s was created successfully.'), $object->_a['verbose'])); + } + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $form = Pluf_Shortcuts_GetFormForModel($object, $object->getData(), $p['extra_form']); + } + return Pluf_Shortcuts_RenderToResponse($template, + array_merge($context, + array('form' => $form, + 'object' => $object)), + $request); + } + + + /** + * Delete an object (Part of the CRUD series). + * + * The minimal extra parameter is the model class name. The list + * of extra parameters is: + * + * 'model' - Class name string, required. + * + * 'post_delete_redirect' - View to redirect after saving, required. + * + * 'id' - Index in the match to fin the id of the object to delete (1) + * + * 'login_required' - Do we require login (false) + * + * 'template' - Template to use ('"model class"_confirm_delete.html') + * + * 'post_delete_redirect_keys' - Which keys of the model to pass to + * the view (array()) + * + * 'extra_context' - Array of key/values to be added to the + * context (array()) + * + * @param Pluf_HTTP_Request Request object + * @param array Match + * @param array Extra parameters + * @return Pluf_HTTP_Response Response object (can be a redirect) + */ + public function deleteObject($request, $match, $p) + { + if (isset($p['login_required']) && true == $p['login_required']) { + if ($request->user->isAnonymous()) { + return new Pluf_HTTP_Response_RedirectToLogin($request); + } + } + if (!isset($p['model'])) { + throw new Exception('The model class was not provided in the parameters.'); + } + // Set the default + $id = (isset($p['id'])) ? $match[$p['id']] : $match[1]; + $model = $p['model']; + $context = (isset($p['extra_context'])) ? $p['extra_context'] : array(); + $template = (isset($p['template'])) ? $p['template'] : strtolower($model).'_confirm_delete.html'; + $post_delete_keys = (isset($p['post_delete_redirect_keys'])) ? $p['post_delete_redirect_keys'] : array(); + + $object = Pluf_Shortcuts_GetObjectOr404($model, $id); + if ($request->method == 'POST') { + $object->delete(); + if (isset($p['post_delete_redirect'])) { + $url = Pluf_HTTP_URL_urlForView($p['post_delete_redirect'], + $post_delete_keys); + } else { + throw new Exception('No URL to redirect to from generic delete view.'); + } + if (!$request->user->isAnonymous()) { + $request->user->setMessage(sprintf(__('The %s was deleted successfully.'), $object->_a['verbose'])); + } + return new Pluf_HTTP_Response_Redirect($url); + } + return Pluf_Shortcuts_RenderToResponse($template, + array_merge($context, + array('object' => $object)), + $request); + } + +} \ No newline at end of file diff --git a/pluf/src/Pluf/conf/pluf.test.php b/pluf/src/Pluf/conf/pluf.test.php new file mode 100644 index 0000000..6ad1a09 --- /dev/null +++ b/pluf/src/Pluf/conf/pluf.test.php @@ -0,0 +1,77 @@ + 'Pluf_Template_Tag_Mytag', + ); + +// Must be shared by all the installed_apps and the core framework. +// That way you can have several installations of the core framework. +$cfg['db_table_prefix'] = 'pluf_unit_tests_'; + +// Starting version 4.1 of MySQL the utf-8 support is "correct". +// The reason of the db_version for MySQL is only for that. +$cfg['db_version'] = '5.0'; +$cfg['db_engine'] = 'SQLite'; +$cfg['pluf_ab_mongo_db'] = 'pluf_ab_test'; +$cfg['simple_test_path'] = '/home/loa/Vendors/simpletest'; +$cfg['cache_engine'] = 'Pluf_Cache_Memcached'; +return $cfg; + diff --git a/pluf/src/Pluf/locale/cs/pluf.po b/pluf/src/Pluf/locale/cs/pluf.po new file mode 100644 index 0000000..f40e131 --- /dev/null +++ b/pluf/src/Pluf/locale/cs/pluf.po @@ -0,0 +1,662 @@ +# +# Czech translations of Pluf. +# Copyright (C) 2009 Jakub Vitak and contributors +# This file is distributed under the same license as the Pluf package. +# Jakub Vitak , 2009. +# +msgid "" +msgstr "" +"Project-Id-Version: Pluf git\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2009-09-24 17:21+0200\n" +"PO-Revision-Date: \n" +"Last-Translator: Jakub Vitak \n" +"Language-Team: KoudyNET \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: Czech\n" +"X-Poedit-Country: CZECH REPUBLIC\n" +"X-Poedit-SourceCharset: utf-8\n" +"X-Poedit-Basepath: ../../../\n" + +#: Pluf/Translation/TemplateExtractor.php:267 +#: Pluf/Template/Compiler.php:345 +#, php-format +msgid "Template file contains invalid characters: %s" +msgstr "Template obsahuje neplatné znaky: %s" + +#: Pluf/Translation/TemplateExtractor.php:276 +#: Pluf/Template/Compiler.php:354 +#, php-format +msgid "Template file not found: %s" +msgstr "Template soubor nenalezen: %s" + +#: Pluf/Translation/TemplateExtractor.php:283 +#, php-format +msgid "Invalid tag in translation extractor: %s" +msgstr "Neplatný tag při extrahování překladů: %s" + +#: Pluf/Translation/TemplateExtractor.php:288 +#: Pluf/Template/Compiler.php:375 +#, php-format +msgid "Invalid function syntax: %s" +msgstr "Neplatná syntaxe funkce: %s" + +#: Pluf/Translation/TemplateExtractor.php:305 +#: Pluf/Template/Compiler.php:361 +#, php-format +msgid "Invalid tag syntax: %s" +msgstr "Neplatná syntaxe tagu: %s" + +#: Pluf/Translation/TemplateExtractor.php:390 +#: Pluf/Template/Compiler.php:629 +#, php-format +msgid "Invalid syntax: (%s) %s." +msgstr "Neplatná syntaxe: (%s) %s." + +#: Pluf/Translation/TemplateExtractor.php:395 +#: Pluf/Template/Compiler.php:634 +#, php-format +msgid "Invalid character: (%s) %s." +msgstr "Neplatný znak: (%s) %s." + +#: Pluf/Form.php:228 +#, php-format +msgid "(Hidden field %1$s) %2$s" +msgstr "(Skryté pole %1$s) %2$s" + +#: Pluf/Paginator.php:411 +msgid "Prev" +msgstr "Předchozí" + +#: Pluf/Paginator.php:422 +msgid "Next" +msgstr "Následující" + +#: Pluf/Paginator.php:578 +msgid "Name" +msgstr "Jméno" + +#: Pluf/Paginator.php:622 +msgid "Sort" +msgstr "Setřídit" + +#: Pluf/Paginator.php:625 +msgid "asc" +msgstr "vzestupně" + +#: Pluf/Paginator.php:628 +msgid "desc" +msgstr "sestupně" + +#: Pluf/Paginator.php:651 +msgid "Filter the list:" +msgstr "Filtrovat seznam:" + +#: Pluf/Paginator.php:654 +msgid "Filter" +msgstr "Filtr" + +#: Pluf/Paginator.php:747 +#: Pluf/Template.php:270 +#: Pluf/Template.php:272 +#: Pluf/Template.php:284 +#: Pluf/Template.php:286 +msgid "now" +msgstr "teď" + +#: Pluf/Search/Occ.php:33 +msgid "occurence" +msgstr "událost" + +#: Pluf/Search/Occ.php:49 +#: Pluf/Search/Word.php:33 +#: Pluf/Search/Word.php:50 +msgid "word" +msgstr "slovo" + +#: Pluf/Search/Occ.php:56 +#: Pluf/Search/Stats.php:50 +#: Pluf/RowPermission.php:51 +#: Pluf/Queue.php:67 +msgid "model class" +msgstr "třída modelu" + +#: Pluf/Search/Occ.php:62 +#: Pluf/Search/Stats.php:56 +#: Pluf/Queue.php:73 +msgid "model id" +msgstr "id modelu" + +#: Pluf/Search/Occ.php:68 +msgid "occurences" +msgstr "události" + +#: Pluf/Search/Occ.php:74 +msgid "weighted occurence" +msgstr "" + +#: Pluf/Search/Stats.php:34 +msgid "search stats" +msgstr "vyhledávací statistiky" + +#: Pluf/Search/Stats.php:62 +msgid "number of indexations" +msgstr "počet indexů" + +#: Pluf/Search/Stats.php:69 +#: Pluf/Queue.php:98 +msgid "created at" +msgstr "vytvořeno" + +#: Pluf/Search/Stats.php:75 +#: Pluf/Queue.php:104 +msgid "modified at" +msgstr "modifikováno" + +#: Pluf/Error.php:93 +msgid "DB error:" +msgstr "chyba databáze:" + +#: Pluf/RowPermission.php:44 +msgid "model ID" +msgstr "ID modelu" + +#: Pluf/RowPermission.php:57 +msgid "owner ID" +msgstr "ID vlastníka" + +#: Pluf/RowPermission.php:64 +msgid "owner class" +msgstr "třída vlastníka" + +#: Pluf/RowPermission.php:65 +msgid "For example Pluf_User or Pluf_Group." +msgstr "Například Pluf_User nebo Pluf_Group." + +#: Pluf/RowPermission.php:72 +msgid "do not have the permission" +msgstr "nemám oprávnění" + +#: Pluf/RowPermission.php:79 +#: Pluf/Permission.php:30 +msgid "permission" +msgstr "oprávnění" + +#: Pluf/Model.php:442 +msgid "Error: More than one matching item found." +msgstr "Chyba: Nalezen více než jeden platný výskyt." + +#: Pluf/Model.php:482 +#, php-format +msgid "The view \"%s\" is not defined." +msgstr "Pohled \"%s\" není definován." + +#: Pluf/Model.php:631 +#, php-format +msgid "No matching foreign key found in model: %s for model %s" +msgstr "Nenalezen foreign key v modelu: %s for model %s" + +#: Pluf/Template.php:142 +#, php-format +msgid "Cannot write the compiled template: %s" +msgstr "Není možne uložit zkompilovaný template: %s" + +#: Pluf/Test/Fixture.php:41 +#, php-format +msgid "Fixture file not found: %s." +msgstr "Fixture soubor nenalezen: %s." + +#: Pluf/Test/Fixture.php:56 +#, php-format +msgid "Cannot load existing model <%1$s(%2$s)>." +msgstr "Není možné načíst existující model <%1$s(%2$s)>." + +#: Pluf/Date.php:179 +msgid "year" +msgid_plural "years" +msgstr[0] "rok" +msgstr[1] "roky" + +#: Pluf/Date.php:182 +msgid "month" +msgid_plural "months" +msgstr[0] "měsíc" +msgstr[1] "měsíce" + +#: Pluf/Date.php:185 +msgid "day" +msgid_plural "days" +msgstr[0] "den" +msgstr[1] "dny" + +#: Pluf/Date.php:188 +msgid "hour" +msgid_plural "hours" +msgstr[0] "hodina" +msgstr[1] "hodiny" + +#: Pluf/Date.php:191 +msgid "minute" +msgid_plural "minutes" +msgstr[0] "minuta" +msgstr[1] "minuty" + +#: Pluf/Date.php:194 +msgid "second" +msgid_plural "seconds" +msgstr[0] "sekunda" +msgstr[1] "sekundy" + +#: Pluf/Date.php:206 +#, php-format +msgid "%s ago" +msgstr "před %s" + +#: Pluf/Date.php:208 +#, php-format +msgid "%s left" +msgstr "uběhlo %s" + +#: Pluf/Group.php:30 +msgid "group" +msgstr "skupina" + +#: Pluf/Group.php:46 +#: Pluf/Permission.php:46 +msgid "name" +msgstr "jméno" + +#: Pluf/Group.php:53 +#: Pluf/Permission.php:61 +msgid "description" +msgstr "popis" + +#: Pluf/HTTP/Response/Redirect.php:34 +#: Pluf/HTTP/Response/RedirectToLogin.php:56 +#, php-format +msgid "Please, click here to be redirected." +msgstr "Prosím, kliknět zde pro přesměrování." + +#: Pluf/Form/Field/Url.php:35 +msgid "Enter a valid address." +msgstr "Zadejte platnou adresu." + +#: Pluf/Form/Field/Date.php:46 +msgid "Enter a valid date." +msgstr "Zadejte platné datum." + +#: Pluf/Form/Field/Integer.php:39 +#: Pluf/Encoder.php:138 +msgid "The value must be an integer." +msgstr "Hodnota musí být číslo." + +#: Pluf/Form/Field/Integer.php:49 +#, php-format +msgid "Ensure that this value is not greater than %1$d." +msgstr "Ujistěte se, že tato hodnota není větší než %1$d." + +#: Pluf/Form/Field/Integer.php:52 +#, php-format +msgid "Ensure that this value is not lower than %1$d." +msgstr "Ujistěte se, že tato hodnota není menší než %1$d." + +#: Pluf/Form/Field/Float.php:39 +msgid "Enter a number." +msgstr "Zadejte číslo." + +#: Pluf/Form/Field/Float.php:42 +#, php-format +msgid "Ensure this value is less than or equal to %s." +msgstr "Ujistěte se, že tato hodnota je menší nebo rovna %1$d." + +#: Pluf/Form/Field/Float.php:45 +#, php-format +msgid "Ensure this value is greater than or equal to %s." +msgstr "Ujistěte se, že tato hodnota je větší nebo rovna %1$d." + +#: Pluf/Form/Field/Email.php:38 +msgid "Enter a valid email address." +msgstr "Zadejte správnou e-mailovou adresu." + +#: Pluf/Form/Field/File.php:43 +#: Pluf/Form/Field/File.php:63 +msgid "No files were uploaded. Please try to send the file again." +msgstr "Nebyl nahrán žádný soubor. Prosím, zkuste to znovu." + +#: Pluf/Form/Field/File.php:51 +#: Pluf/Form/Field/File.php:55 +#, php-format +msgid "The uploaded file is too large. Reduce the size of the file to %s and send it again." +msgstr "Nahrávaný soubor je příliš velký. Zmenšete velikost souboru %s a pošlete jej znova." + +#: Pluf/Form/Field/File.php:59 +msgid "The upload did not complete. Please try to send the file again." +msgstr "Nahrávání se nepovedlo. Prosím, zkuste poslat soubor znovu." + +#: Pluf/Form/Field/File.php:70 +msgid "The server has no temporary folder correctly configured to store the uploaded file." +msgstr "Server nemá správně nastavení dočasný adresář pro uložení nahrávaného souboru." + +#: Pluf/Form/Field/File.php:73 +msgid "The uploaded file has been stopped by an extension." +msgstr "Nahravání souboru bylo zastaveno rozšířením (extension)." + +#: Pluf/Form/Field/File.php:76 +msgid "An error occured when upload the file. Please try to send the file again." +msgstr "Nastala chyba při nahrávání souboru. Prosím, zkuste soubor odeslat znovu." + +#: Pluf/Form/Field/File.php:79 +#, php-format +msgid "The uploaded file is to big (%1$s). Reduce the size to less than %2$s and try again." +msgstr "Nahrávaný soubor je příliš velký (%1$s). Zmenšete velikost tak, aby byla menší než %2$s a zkuste to znovu." + +#: Pluf/Form/Field/File.php:140 +msgid "An error occured when creating the upload path. Please try to send the file again." +msgstr "Vznikla chyba při vytváření cesty pro uložení. Prosím, zkuste soubor odeslat znovu." + +#: Pluf/Form/Field/File.php:144 +#, php-format +msgid "A file with the name \"%s\" has already been uploaded." +msgstr "Soubor s jménem \"%s\" již existuje." + +#: Pluf/Form/Field/File.php:147 +msgid "An error occured when uploading the file. Please try to send the file again." +msgstr "Vznikla chyba při nahrávání souboru. Prosím, zkuste soubor odeslat znovu." + +#: Pluf/Form/Field/Varchar.php:38 +#, php-format +msgid "Ensure this value has at most %1$d characters (it has %2$d)." +msgstr "Ujistěte se, že hodnota má maximálně %1$d znaků (má pouze %2$d)." + +#: Pluf/Form/Field/Varchar.php:41 +#, php-format +msgid "Ensure this value has at least %1$d characters (it has %2$d)." +msgstr "Ujistěte se, že hodnota má minimálně %1$d znaků (má pouze %2$d)." + +#: Pluf/Form/Field/Datetime.php:61 +msgid "Enter a valid date/time." +msgstr "Zadejte platné datum/čas." + +#: Pluf/Form/Model.php:85 +msgid "Cannot save the model from an invalid form." +msgstr "Nemohu uložit model z neplatného formuláře." + +#: Pluf/Form/Field.php:120 +#: Pluf/Form/Field.php:123 +msgid "This field is required." +msgstr "Tato položka je povinná" + +#: Pluf/User.php:44 +#: Pluf/Message.php:45 +msgid "user" +msgstr "uživatel" + +#: Pluf/User.php:61 +msgid "login" +msgstr "login" + +#: Pluf/User.php:68 +msgid "first name" +msgstr "jméno" + +#: Pluf/User.php:75 +msgid "last name" +msgstr "příjmení" + +#: Pluf/User.php:81 +msgid "email" +msgstr "email" + +#: Pluf/User.php:87 +msgid "password" +msgstr "heslo" + +#: Pluf/User.php:89 +msgid "Format: [algo]:[salt]:[hash]" +msgstr "Formát: [algo]:[salt]:[hash]" + +#: Pluf/User.php:108 +msgid "administrator" +msgstr "administrátor" + +#: Pluf/User.php:115 +msgid "staff" +msgstr "četa" + +#: Pluf/User.php:122 +msgid "active" +msgstr "aktivní" + +#: Pluf/User.php:130 +msgid "language" +msgstr "jazyk" + +#: Pluf/User.php:131 +msgid "Prefered language of the user for the interface. Use the 2 or 5 letter code like \"fr\", \"en\", \"fr_QC\" or \"en_US\"." +msgstr "Preferovaný jazyk uživatele pro komunikaci. Použijte 2 nebo 5 místný kód jako \"cs\", \"fr\", \"en\", \"fr_QC\" or \"en_US\"" + +#: Pluf/User.php:139 +msgid "time zone" +msgstr "časová zóna" + +#: Pluf/User.php:140 +msgid "Time zone of the user to display the time in local time." +msgstr "Časová zóna uživatele pro zobrazení lokálního času." + +#: Pluf/User.php:146 +msgid "date joined" +msgstr "datum registrace" + +#: Pluf/User.php:153 +msgid "last login" +msgstr "poslední přihlášení" + +#: Pluf/User.php:441 +msgid "\"user_profile_class\" setting not defined." +msgstr "\"user_profile_class\" nebylo definováno." + +#: Pluf/User.php:448 +#, php-format +msgid "No profiles available for user: %s" +msgstr "Nebyl nalezen žádný profil pro uživatele: %s" + +#: Pluf/Text/LaTeX/Equation.php:243 +msgid "Unable to generate the dvi file." +msgstr "Nepovedlo se vygenerovat dvi soubor." + +#: Pluf/Text/LaTeX/Equation.php:260 +msgid "Unable to generate the png file." +msgstr "Nepovedlo se vygenerovat png soubor." + +#: Pluf/Text/LaTeX/Equation.php:270 +msgid "Unable to move the png file." +msgstr "Nepovedlo se přesunout png soubor." + +#: Pluf/Text/LaTeX/Equation.php:308 +#, php-format +msgid "The LaTeX tag \"%s\" is not acceptable." +msgstr "LaTeX značka \"%s\" není povolena." + +#: Pluf/Queue.php:51 +msgid "message queue" +msgstr "fronta zpráv" + +#: Pluf/Queue.php:80 +msgid "action" +msgstr "akce" + +#: Pluf/Queue.php:86 +msgid "lock status" +msgstr "status zámku" + +#: Pluf/Queue.php:89 +msgid "Free" +msgstr "Volno" + +#: Pluf/Queue.php:90 +msgid "In progress" +msgstr "Zpracovává se" + +#: Pluf/Queue.php:91 +msgid "Completed" +msgstr "Hotovo" + +#: Pluf/Calendar.php:318 +msgid "Sunday" +msgstr "Neděle" + +#: Pluf/Calendar.php:319 +msgid "Monday" +msgstr "Pondělí" + +#: Pluf/Calendar.php:320 +msgid "Tuesday" +msgstr "Úterý" + +#: Pluf/Calendar.php:321 +msgid "Wednesday" +msgstr "Středa" + +#: Pluf/Calendar.php:322 +msgid "Thursday" +msgstr "Čtvrtek" + +#: Pluf/Calendar.php:323 +msgid "Friday" +msgstr "Pátek" + +#: Pluf/Calendar.php:324 +msgid "Saturday" +msgstr "Sobota" + +#: Pluf/Utils.php:99 +msgid "GB" +msgstr "GB" + +#: Pluf/Utils.php:101 +msgid "MB" +msgstr "MB" + +#: Pluf/Utils.php:103 +msgid "kB" +msgstr "kB" + +#: Pluf/Utils.php:105 +#, php-format +msgid "%d byte" +msgid_plural "%d bytes" +msgstr[0] "%d byte" +msgstr[1] "%d bytů" + +#: Pluf/Views.php:77 +msgid "The login or the password is not valid. The login and the password are case sensitive." +msgstr "Login nebo heslo nejsou platné. Login a heslo rozlišují velká a malá písmena." + +#: Pluf/Views.php:80 +msgid "You need to enable the cookies in your browser to access this website." +msgstr "Je třeba, abyste si zapli cookies ve vašem prohlížeči, abyste mohli prohlížet tento web." + +#: Pluf/Views.php:96 +msgid "Sign In" +msgstr "Přihlásit" + +#: Pluf/Views.php:194 +#: Pluf/Views.php:270 +#, php-format +msgid "The %s was created successfully." +msgstr "%s vytvořen v pořádku." + +#: Pluf/Views.php:339 +#, php-format +msgid "The %s was deleted successfully." +msgstr "%s smazán v pořádku." + +#: Pluf/Template/Compiler.php:262 +#: Pluf/Template/Compiler.php:427 +#: Pluf/Template/Compiler.php:433 +#: Pluf/Template/Compiler.php:450 +#: Pluf/Template/Compiler.php:493 +#, php-format +msgid "End tag of a block missing: %s" +msgstr "Konec tagu nebo bloku chybí: %s" + +#: Pluf/Template/Compiler.php:398 +#, php-format +msgid "Invalid modifier syntax: (%s) %s" +msgstr "Neplatný modifikátor syntaxe: (%s) %s" + +#: Pluf/Template/Compiler.php:408 +#, php-format +msgid "Unknown modifier: (%s) %s" +msgstr "Neznámý modifikátor: (%s) %s" + +#: Pluf/Template/Compiler.php:462 +msgid "End tag of a block missing: literal" +msgstr "Konec tagu nebo bloku chybí: literal" + +#: Pluf/Template/Compiler.php:466 +msgid "Start tag of a block missing: literal" +msgstr "Začátek tagu nebo bloku chybí: literal" + +#: Pluf/Template/Compiler.php:548 +#, php-format +msgid "The function tag \"%s\" is not allowed." +msgstr "Funkce tag \"%s\" není povolena." + +#: Pluf/Template/Compiler.php:572 +#, php-format +msgid "The function tag \"{%s ...}\" is not supported." +msgstr "Funkce tag \"{%s ...}\" není podporována." + +#: Pluf/Encoder.php:62 +msgid "The value must not be empty." +msgstr "Hodnota nesmí být prázdná." + +#: Pluf/Encoder.php:81 +#, php-format +msgid "The URL %s is not valid." +msgstr "Odkaz %s není platný." + +#: Pluf/Encoder.php:88 +#, php-format +msgid "The value should not be more than %s characters long." +msgstr "" + +#: Pluf/Encoder.php:96 +#, php-format +msgid "The password must be at least %s characters long." +msgstr "Heslo musí být alespoň %s znaků dlouhé." + +#: Pluf/Encoder.php:106 +#, php-format +msgid "The email address \"%s\" is not valid." +msgstr "E-mailová adresa není validní." + +#: Pluf/Encoder.php:146 +#, php-format +msgid "The date and time %s are not valid." +msgstr "Datum a čas %s není validní." + +#: Pluf/Encoder.php:157 +#, php-format +msgid "The date %s is not valid." +msgstr "Datum %s není validní." + +#: Pluf/Permission.php:53 +msgid "code name" +msgstr "kódové jméno" + +#: Pluf/Permission.php:54 +msgid "The code name must be unique for each application. Standard permissions to manage a model in the interface are \"Model_Name-create\", \"Model_Name-update\", \"Model_Name-list\" and \"Model_Name-delete\"." +msgstr "Kódové jméno musí být unikátní pro každou aplikaci. Standartní oprávnění pro správu model v rozhraní je \"Model_Name-create\", \"Model_Name-update\", \"Model_Name-list\" and \"Model_Name-delete\"." + +#: Pluf/Permission.php:68 +msgid "application" +msgstr "aplikace" + +#: Pluf/Permission.php:69 +msgid "The application using this permission, for example \"YourApp\", \"CMS\" or \"SView\"." +msgstr "Aplikace využívající opravnění, například \"YourApp\", \"CMS\" or \"SView\"." + diff --git a/pluf/src/Pluf/locale/de/pluf.po b/pluf/src/Pluf/locale/de/pluf.po new file mode 100644 index 0000000..669919e --- /dev/null +++ b/pluf/src/Pluf/locale/de/pluf.po @@ -0,0 +1,656 @@ +msgid "" +msgstr "" +"Project-Id-Version: Pluf Framework\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2009-02-02 13:56+0100\n" +"PO-Revision-Date: \n" +"Last-Translator: Thomas Keller \n" +"Language-Team: Jürgen Hörmann , Thomas Keller \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: German\n" +"X-Poedit-Country: GERMANY\n" +"X-Poedit-SourceCharset: iso-8859-1\n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" + +#: Pluf/Search/Stats.php:34 +msgid "search stats" +msgstr "Suchstatistik" + +#: Pluf/Search/Stats.php:50 +#: Pluf/Search/Occ.php:56 +#: Pluf/Queue.php:67 +#: Pluf/RowPermission.php:51 +msgid "model class" +msgstr "Modell-Klasse" + +#: Pluf/Search/Stats.php:56 +#: Pluf/Search/Occ.php:62 +#: Pluf/Queue.php:73 +msgid "model id" +msgstr "Modell-Id" + +#: Pluf/Search/Stats.php:62 +msgid "number of indexations" +msgstr "Anzahl der Indexierungen" + +#: Pluf/Search/Stats.php:69 +#: Pluf/Queue.php:98 +msgid "created at" +msgstr "erstellt am" + +#: Pluf/Search/Stats.php:75 +#: Pluf/Queue.php:104 +msgid "modified at" +msgstr "geändert am" + +#: Pluf/Search/Word.php:33 +#: Pluf/Search/Word.php:50 +#: Pluf/Search/Occ.php:49 +msgid "word" +msgstr "Wort" + +#: Pluf/Search/Occ.php:33 +msgid "occurence" +msgstr "Vorkommen" + +#: Pluf/Search/Occ.php:68 +msgid "occurences" +msgstr "Vorkommen" + +#: Pluf/Search/Occ.php:74 +msgid "weighted occurence" +msgstr "gewichtetes Vorkommen" + +#: Pluf/Message.php:45 +#: Pluf/User.php:44 +msgid "user" +msgstr "Benutzer" + +#: Pluf/HTTP/Response/RedirectToLogin.php:56 +#: Pluf/HTTP/Response/Redirect.php:28 +#, php-format +msgid "Please, click here to be redirected." +msgstr "Um weiter geleitet zu werden, klicke bitte hier.." + +#: Pluf/Text/LaTeX/Equation.php:243 +msgid "Unable to generate the dvi file." +msgstr "Konnte die DVI-Datei nicht erstellen." + +#: Pluf/Text/LaTeX/Equation.php:260 +msgid "Unable to generate the png file." +msgstr "Konnte die PNG-Datei nicht erstellen" + +#: Pluf/Text/LaTeX/Equation.php:270 +msgid "Unable to move the png file." +msgstr "Konnte die PNG-Datei nicht verschieben." + +#: Pluf/Text/LaTeX/Equation.php:308 +#, php-format +msgid "The LaTeX tag \"%s\" is not acceptable." +msgstr "Der LaTeX-Tag \"%s\" ist ungültig." + +#: Pluf/Translation/TemplateExtractor.php:267 +#: Pluf/Template/Compiler.php:345 +#, php-format +msgid "Template file contains invalid characters: %s" +msgstr "Die Vorlage enthält ungültige Zeichen: %s" + +#: Pluf/Translation/TemplateExtractor.php:276 +#: Pluf/Template/Compiler.php:354 +#, php-format +msgid "Template file not found: %s" +msgstr "Die Vorlage wurde nicht gefunden: %s" + +#: Pluf/Translation/TemplateExtractor.php:283 +#, php-format +msgid "Invalid tag in translation extractor: %s" +msgstr "Ungültiger Tag im Übersetzungs-Generator: %s" + +#: Pluf/Translation/TemplateExtractor.php:288 +#: Pluf/Template/Compiler.php:375 +#, php-format +msgid "Invalid function syntax: %s" +msgstr "Ungültige Funktionssyntax: %s" + +#: Pluf/Translation/TemplateExtractor.php:305 +#: Pluf/Template/Compiler.php:361 +#, php-format +msgid "Invalid tag syntax: %s" +msgstr "Ungültige Tag-Syntax: %s" + +#: Pluf/Translation/TemplateExtractor.php:390 +#: Pluf/Template/Compiler.php:629 +#, php-format +msgid "Invalid syntax: (%s) %s." +msgstr "Ungültige Syntax: (%s) %s." + +#: Pluf/Translation/TemplateExtractor.php:395 +#: Pluf/Template/Compiler.php:634 +#, php-format +msgid "Invalid character: (%s) %s." +msgstr "Ungültiges Zeichen: (%s) %s." + +#: Pluf/User.php:61 +msgid "login" +msgstr "Anmeldename" + +#: Pluf/User.php:68 +msgid "first name" +msgstr "Vorname" + +#: Pluf/User.php:75 +msgid "last name" +msgstr "Nachname" + +#: Pluf/User.php:81 +msgid "email" +msgstr "E-Mail" + +#: Pluf/User.php:87 +msgid "password" +msgstr "Passwort" + +#: Pluf/User.php:89 +msgid "Format: [algo]:[salt]:[hash]" +msgstr "Format: [algo]:[salt]:[hash]" + +#: Pluf/User.php:108 +msgid "administrator" +msgstr "Administrator" + +#: Pluf/User.php:115 +msgid "staff" +msgstr "Mitarbeiter" + +#: Pluf/User.php:122 +msgid "active" +msgstr "aktiv" + +#: Pluf/User.php:130 +msgid "language" +msgstr "Sprache" + +#: Pluf/User.php:131 +msgid "Prefered language of the user for the interface. Use the 2 or 5 letter code like \"fr\", \"en\", \"fr_QC\" or \"en_US\"." +msgstr "Bevorzugte Sprache des Nutzers für die Oberfläche. Benutze Sprach- bzw. Sprach-Ländercode in der Form \"fr\", \"en\", \"fr_QC\" oder \"en_US\"." + +#: Pluf/User.php:139 +msgid "time zone" +msgstr "Zeitzone" + +#: Pluf/User.php:140 +msgid "Time zone of the user to display the time in local time." +msgstr "Zeitzone des Benutzers, um Zeitangaben in Ortszeit darzustellen." + +#: Pluf/User.php:146 +msgid "date joined" +msgstr "Datum der Anmeldung" + +#: Pluf/User.php:153 +msgid "last login" +msgstr "Letzte Anmeldung" + +#: Pluf/User.php:417 +msgid "\"user_profile_class\" setting not defined." +msgstr "Die Einstellung \"user_profile_class\" ist nicht definiert." + +#: Pluf/User.php:424 +#, php-format +msgid "No profiles available for user: %s" +msgstr "Kein Profil vorhanden für Benutzer: %s" + +#: Pluf/Error.php:93 +msgid "DB error:" +msgstr "Datenbank-Fehler:" + +#: Pluf/Form/Field/Float.php:39 +msgid "Enter a number." +msgstr "Gib eine Zahl ein." + +#: Pluf/Form/Field/Float.php:42 +#, php-format +msgid "Ensure this value is less than or equal to %s." +msgstr "Stelle sicher, dass der Wert kleiner oder gleich %s ist." + +#: Pluf/Form/Field/Float.php:45 +#, php-format +msgid "Ensure this value is greater than or equal to %s." +msgstr "Stelle sicher, dass der Wert größer oder gleich %s ist." + +#: Pluf/Form/Field/Email.php:38 +msgid "Enter a valid email address." +msgstr "Gib eine gültige E-Mail-Adresse ein." + +#: Pluf/Form/Field/Datetime.php:61 +msgid "Enter a valid date/time." +msgstr "Gib ein gültiges Datum bzw. eine gültige Zeit ein." + +#: Pluf/Form/Field/Url.php:35 +msgid "Enter a valid address." +msgstr "Gib eine gültige Adresse ein." + +#: Pluf/Form/Field/Integer.php:40 +#: Pluf/Form/Field/Integer.php:49 +#: Pluf/Encoder.php:138 +msgid "The value must be an integer." +msgstr "Der Wert muss ganzzahlig sein." + +#: Pluf/Form/Field/Integer.php:59 +#, php-format +msgid "Ensure that this value is not greater than %1$d." +msgstr "Stelle sicher, dass der Wert nicht größer als %1$d ist." + +#: Pluf/Form/Field/Integer.php:62 +#, php-format +msgid "Ensure that this value is not lower than %1$d." +msgstr "Stelle sicher, dass der Wert nicht kleiner als %1$d ist." + +#: Pluf/Form/Field/Date.php:46 +msgid "Enter a valid date." +msgstr "Gib ein gültiges Datum ein." + +#: Pluf/Form/Field/Varchar.php:38 +#, php-format +msgid "Ensure this value has at most %1$d characters (it has %2$d)." +msgstr "Stelle sicher, dass dieser Wert maximal %1$d Zeichen enthält (derzeit %2$d Zeichen)." + +#: Pluf/Form/Field/Varchar.php:41 +#, php-format +msgid "Ensure this value has at least %1$d characters (it has %2$d)." +msgstr "Stelle sicher, dass der Wert mindestens %1$d Zeichen enthält (derzeit %2$d Zeichen)." + +#: Pluf/Form/Field/File.php:43 +#: Pluf/Form/Field/File.php:59 +msgid "No files were uploaded. Please try to send the file again." +msgstr "Es wurden keine Dateien hoch geladen. Bitte versuche die Datei erneut hochzuladen." + +#: Pluf/Form/Field/File.php:52 +msgid "The uploaded file is too large. Reduce the size of the file and send it again." +msgstr "Die hoch geladene Datei ist zu groß. Verringere die Dateigröße und lade sie erneut hoch." + +#: Pluf/Form/Field/File.php:55 +msgid "The upload did not complete. Please try to send the file again." +msgstr "Das Hochladen wurde nicht abgeschlossen. Bitte versuche die Datei erneut hochzuladen." + +#: Pluf/Form/Field/File.php:66 +msgid "The server has no temporary folder correctly configured to store the uploaded file." +msgstr "Das temporäre Upload-Verzeichnis ist nicht richtig konfiguriert, um die hochgeladene Datei zu speichern." + +#: Pluf/Form/Field/File.php:69 +msgid "The uploaded file has been stopped by an extension." +msgstr "Das Hochladen wurde durch eine Programmkomponente verhindert." + +#: Pluf/Form/Field/File.php:72 +msgid "An error occured when upload the file. Please try to send the file again." +msgstr "Während dem Hochladen ist ein Fehler aufgetreten. Bitte versuche die Datei erneut hochzuladen." + +#: Pluf/Form/Field/File.php:75 +#, php-format +msgid "The uploaded file is to big (%1$s). Reduce the size to less than %2$s and try again." +msgstr "Die hochgeladene Datei ist zu groß (%1$s). Reduziere die Dateigröße auf unter %2$s und versuche es erneut." + +#: Pluf/Form/Field/File.php:136 +msgid "An error occured when creating the upload path. Please try to send the file again." +msgstr "Beim erzeugen des Upload-Pfades ist ein Fehler aufgetreten. Bitte versuche die Datei erneut hochzuladen." + +#: Pluf/Form/Field/File.php:140 +#, php-format +msgid "A file with the name \"%s\" has already been uploaded." +msgstr "Eine Datei mit dem Namen \"%s\" wurde bereits auf den Server hochgeladen." + +#: Pluf/Form/Field/File.php:143 +msgid "An error occured when uploading the file. Please try to send the file again." +msgstr "Während dem Hochladen ist ein Fehler aufgetreten. Bitte versuche die Datei erneut hochzuladen." + +#: Pluf/Form/Field.php:115 +msgid "This field is required." +msgstr "Dieses Feld muss ausgefüllt sein." + +#: Pluf/Form/Model.php:82 +msgid "Cannot save the model from an invalid form." +msgstr "Das Modell eines ungültigen Formulars kann nicht gespeichert werden." + +#: Pluf/Queue.php:51 +msgid "message queue" +msgstr "Nachrichten-Warteschlange" + +#: Pluf/Queue.php:80 +msgid "action" +msgstr "Aktion" + +#: Pluf/Queue.php:86 +msgid "lock status" +msgstr "Sperrstatus" + +#: Pluf/Queue.php:89 +msgid "Free" +msgstr "Frei" + +#: Pluf/Queue.php:90 +msgid "In progress" +msgstr "In Bearbeitung" + +#: Pluf/Queue.php:91 +msgid "Completed" +msgstr "Abgeschlossen" + +#: Pluf/Group.php:30 +msgid "group" +msgstr "Gruppe" + +#: Pluf/Group.php:46 +#: Pluf/Permission.php:46 +msgid "name" +msgstr "Name" + +#: Pluf/Group.php:53 +#: Pluf/Permission.php:61 +msgid "description" +msgstr "Beschreibung" + +#: Pluf/Permission.php:30 +#: Pluf/RowPermission.php:79 +msgid "permission" +msgstr "Erlaubnis" + +#: Pluf/Permission.php:53 +msgid "code name" +msgstr "Code-Name" + +#: Pluf/Permission.php:54 +msgid "The code name must be unique for each application. Standard permissions to manage a model in the interface are \"Model_Name-create\", \"Model_Name-update\", \"Model_Name-list\" and \"Model_Name-delete\"." +msgstr "Der Code-Name muss für jede Anwendung einmalig sein. Standarderlaubnisse für die Verwaltung eines Modells des Interfaces sind \"Model_Name-create\", \"Model_Name-update\", \"Model_Name-list\" und \"Model_Name-delete\"." + +#: Pluf/Permission.php:68 +msgid "application" +msgstr "Anwendung" + +#: Pluf/Permission.php:69 +msgid "The application using this permission, for example \"YourApp\", \"CMS\" or \"SView\"." +msgstr "Die Anwendung, die dieses Zugriffsrecht verwendet, zum Beispiel \"YourApp\", \"CMS\" oder \"SView\"." + +#: Pluf/Date.php:179 +msgid "year" +msgid_plural "years" +msgstr[0] "Jahr" +msgstr[1] "Jahre" + +#: Pluf/Date.php:182 +msgid "month" +msgid_plural "months" +msgstr[0] "Monat" +msgstr[1] "Monate" + +#: Pluf/Date.php:185 +msgid "day" +msgid_plural "days" +msgstr[0] "Tag" +msgstr[1] "Tage" + +#: Pluf/Date.php:188 +msgid "hour" +msgid_plural "hours" +msgstr[0] "Stunde" +msgstr[1] "Stunden" + +#: Pluf/Date.php:191 +msgid "minute" +msgid_plural "minutes" +msgstr[0] "Minute" +msgstr[1] "Minuten" + +#: Pluf/Date.php:194 +msgid "second" +msgid_plural "seconds" +msgstr[0] "Sekunde" +msgstr[1] "Sekunden" + +#: Pluf/Date.php:206 +#, php-format +msgid "%s ago" +msgstr "vor %s" + +#: Pluf/Date.php:208 +#, php-format +msgid "%s left" +msgstr "%s verbleiben" + +#: Pluf/Calendar.php:318 +msgid "Sunday" +msgstr "Sonntag" + +#: Pluf/Calendar.php:319 +msgid "Monday" +msgstr "Montag" + +#: Pluf/Calendar.php:320 +msgid "Tuesday" +msgstr "Dienstag" + +#: Pluf/Calendar.php:321 +msgid "Wednesday" +msgstr "Mittwoch" + +#: Pluf/Calendar.php:322 +msgid "Thursday" +msgstr "Donnerstag" + +#: Pluf/Calendar.php:323 +msgid "Friday" +msgstr "Freitag" + +#: Pluf/Calendar.php:324 +msgid "Saturday" +msgstr "Samstag" + +#: Pluf/Encoder.php:62 +msgid "The value must not be empty." +msgstr "Der Wert darf nicht leer sein." + +#: Pluf/Encoder.php:81 +#, php-format +msgid "The URL %s is not valid." +msgstr "Die URL %s ist ungültig." + +#: Pluf/Encoder.php:88 +#, php-format +msgid "The value should not be more than %s characters long." +msgstr "Der Wert sollte aus nicht mehr als %s Zeichen bestehen." + +#: Pluf/Encoder.php:96 +#, php-format +msgid "The password must be at least %s characters long." +msgstr "Das Passwort muss mindestens %s Zeichen lang sein." + +#: Pluf/Encoder.php:106 +#, php-format +msgid "The email address \"%s\" is not valid." +msgstr "Die E-Mail-Adresse \"%s\" ist ungültig." + +#: Pluf/Encoder.php:146 +#, php-format +msgid "The date and time %s are not valid." +msgstr "Die Angabe %s für Datum und Zeit ist ungültig." + +#: Pluf/Encoder.php:157 +#, php-format +msgid "The date %s is not valid." +msgstr "Das Datum %s ist nicht gültig." + +#: Pluf/Model.php:429 +#, php-format +msgid "The view \"%s\" is not defined." +msgstr "Die Ansicht \"%s\" ist nicht definiert." + +#: Pluf/Model.php:578 +#, php-format +msgid "No matching foreign key found in model: %s for model %s" +msgstr "Keine passenden Fremdschlüssel im Modell gefunden: %s für Modell %s" + +#: Pluf/Template.php:142 +#, php-format +msgid "Cannot write the compiled template: %s" +msgstr "Kann die übersetzte Vorlage nicht speichern: %s" + +#: Pluf/Template.php:270 +#: Pluf/Template.php:272 +#: Pluf/Template.php:284 +#: Pluf/Template.php:286 +#: Pluf/Paginator.php:713 +msgid "now" +msgstr "jetzt" + +#: Pluf/Paginator.php:396 +msgid "Prev" +msgstr "Vorherige" + +#: Pluf/Paginator.php:407 +msgid "Next" +msgstr "Nächste" + +#: Pluf/Paginator.php:558 +msgid "Name" +msgstr "Name" + +#: Pluf/Paginator.php:595 +msgid "Sort" +msgstr "Sortierung" + +#: Pluf/Paginator.php:598 +msgid "asc" +msgstr "aufsteigend" + +#: Pluf/Paginator.php:601 +msgid "desc" +msgstr "absteigend" + +#: Pluf/Paginator.php:617 +msgid "Filter the list:" +msgstr "Liste filtern:" + +#: Pluf/Paginator.php:620 +msgid "Filter" +msgstr "Filter" + +#: Pluf/Test/Fixture.php:41 +#, php-format +msgid "Fixture file not found: %s." +msgstr "Die Datei mit den Ausgangsdaten der Datenbank ist nicht vorhanden: %s." + +#: Pluf/Test/Fixture.php:56 +#, php-format +msgid "Cannot load existing model <%1$s(%2$s)>." +msgstr "Kann vorhandenes Modell nicht laden <%1$s(%2$s)>." + +#: Pluf/Views.php:63 +msgid "The login or the password is not valid. The login and the password are case sensitive." +msgstr "Der Anmeldename oder das Passwort sind ungültig. Bitte achte auf korrekte Groß- und Kleinschreibung bei Anmeldename und Passwort." + +#: Pluf/Views.php:66 +msgid "You need to enable the cookies in your browser to access this website." +msgstr "Damit Du diese Seite benutzen kannst, musst Du in Deinem Browser Cookies erlauben." + +#: Pluf/Views.php:82 +msgid "Sign In" +msgstr "Anmelden" + +#: Pluf/Views.php:180 +#: Pluf/Views.php:256 +#, php-format +msgid "The %s was created successfully." +msgstr "%s wurde erfolgreich erstellt." + +#: Pluf/Views.php:325 +#, php-format +msgid "The %s was deleted successfully." +msgstr "%s wurde erfolgreich gelöscht." + +#: Pluf/Utils.php:89 +msgid "MB" +msgstr "MB" + +#: Pluf/Utils.php:91 +msgid "kB" +msgstr "kB" + +#: Pluf/Utils.php:93 +msgid "bytes" +msgstr "Bytes" + +#: Pluf/Form.php:228 +#, php-format +msgid "(Hidden field %1$s) %2$s" +msgstr "(Verborgenes Feld %1$s) %2$s" + +#: Pluf/Template/Compiler.php:262 +#: Pluf/Template/Compiler.php:427 +#: Pluf/Template/Compiler.php:433 +#: Pluf/Template/Compiler.php:450 +#: Pluf/Template/Compiler.php:493 +#, php-format +msgid "End tag of a block missing: %s" +msgstr "Der End-Tag eines Block fehlt: %s" + +#: Pluf/Template/Compiler.php:398 +#, php-format +msgid "Invalid modifier syntax: (%s) %s" +msgstr "Ungültige Modifikator-Syntax: (%s) %s" + +#: Pluf/Template/Compiler.php:408 +#, php-format +msgid "Unknown modifier: (%s) %s" +msgstr "Unbekannter Modifikator: (%s) %s" + +#: Pluf/Template/Compiler.php:462 +msgid "End tag of a block missing: literal" +msgstr "Der End-Tag eines Block fehlt: literal" + +#: Pluf/Template/Compiler.php:466 +msgid "Start tag of a block missing: literal" +msgstr "Der Start-Tag eines Block fehlt: literal" + +#: Pluf/Template/Compiler.php:548 +#, php-format +msgid "The function tag \"%s\" is not allowed." +msgstr "Der Funktions-Tag \"%s\" ist nicht erlaubt." + +#: Pluf/Template/Compiler.php:572 +#, php-format +msgid "The function tag \"{%s ...}\" is not supported." +msgstr "Der Funktions-Tag \"{%s ...}\" wird nicht unterstützt." + +#: Pluf/RowPermission.php:44 +msgid "model ID" +msgstr "Modell-ID" + +#: Pluf/RowPermission.php:57 +msgid "owner ID" +msgstr "Besitzer-ID" + +#: Pluf/RowPermission.php:64 +msgid "owner class" +msgstr "Besitzer-Klasse" + +#: Pluf/RowPermission.php:65 +msgid "For example Pluf_User or Pluf_Group." +msgstr "Beispielsweise Pluf_User oder Pluf_Group." + +#: Pluf/RowPermission.php:72 +msgid "do not have the permission" +msgstr "Habe keine Zugriffsrechte" + +#~ msgid "years" +#~ msgstr "Jahre" +#~ msgid "months" +#~ msgstr "Monate" +#~ msgid "days" +#~ msgstr "Tage" +#~ msgid "hours" +#~ msgstr "Stunden" +#~ msgid "minutes" +#~ msgstr "Minuten" +#~ msgid "seconds" +#~ msgstr "Sekunden" + diff --git a/pluf/src/Pluf/locale/fr/pluf.po b/pluf/src/Pluf/locale/fr/pluf.po new file mode 100644 index 0000000..7d0374c --- /dev/null +++ b/pluf/src/Pluf/locale/fr/pluf.po @@ -0,0 +1,668 @@ +# French translations of Pluf. +# Copyright (C) 2008 Loïc d'Anterroches and contributors +# This file is distributed under the same license as the Pluf package. +# Loïc d'Anterroches , 2008. +# +msgid "" +msgstr "" +"Project-Id-Version: Pluf\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2009-01-31 22:35+0100\n" +"PO-Revision-Date: 2009-01-31 22:39+0100\n" +"Last-Translator: Loïc d'Anterroches \n" +"Language-Team: French \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n>1;\n" +"X-Poedit-Language: French\n" +"X-Poedit-Country: France\n" +"X-Poedit-SourceCharset: utf-8\n" +"X-Poedit-Basepath: ../../../\n" + +#: Pluf/Search/Stats.php:34 +msgid "search stats" +msgstr "stats de l'index" + +#: Pluf/Search/Stats.php:50 +#: Pluf/Search/Occ.php:56 +#: Pluf/Queue.php:67 +#: Pluf/RowPermission.php:51 +msgid "model class" +msgstr "class du modèle" + +#: Pluf/Search/Stats.php:56 +#: Pluf/Search/Occ.php:62 +#: Pluf/Queue.php:73 +msgid "model id" +msgstr "model id" + +#: Pluf/Search/Stats.php:62 +msgid "number of indexations" +msgstr "nombre d'indexations" + +#: Pluf/Search/Stats.php:69 +#: Pluf/Queue.php:98 +msgid "created at" +msgstr "créé à" + +#: Pluf/Search/Stats.php:75 +#: Pluf/Queue.php:104 +msgid "modified at" +msgstr "modifié à" + +#: Pluf/Search/Word.php:33 +#: Pluf/Search/Word.php:50 +#: Pluf/Search/Occ.php:49 +msgid "word" +msgstr "mot" + +#: Pluf/Search/Occ.php:33 +msgid "occurence" +msgstr "occurrence" + +#: Pluf/Search/Occ.php:68 +msgid "occurences" +msgstr "occurrences" + +#: Pluf/Search/Occ.php:74 +msgid "ponderated occurence" +msgstr "occurrence pondérée" + +#: Pluf/Message.php:45 +#: Pluf/User.php:44 +msgid "user" +msgstr "utilisateur" + +#: Pluf/HTTP/Response/RedirectToLogin.php:56 +#: Pluf/HTTP/Response/Redirect.php:28 +#, php-format +msgid "Please, click here to be redirected." +msgstr "S'il vous plaît, cliquez ici pour être redirigé." + +#: Pluf/Text/LaTeX/Equation.php:243 +msgid "Unable to generate the dvi file." +msgstr "Impossible de générer le fichier dvi." + +#: Pluf/Text/LaTeX/Equation.php:260 +msgid "Unable to generate the png file." +msgstr "Impossible de générer le fichier png." + +#: Pluf/Text/LaTeX/Equation.php:270 +msgid "Unable to move the png file." +msgstr "Impossible de déplacer le fichier png." + +#: Pluf/Text/LaTeX/Equation.php:308 +#, php-format +msgid "The LaTeX tag \"%s\" is not acceptable." +msgstr "Le marqueur LaTeX \"%s\" n'est pas autorisé." + +#: Pluf/Translation/TemplateExtractor.php:267 +#: Pluf/Template/Compiler.php:345 +#, php-format +msgid "Template file contains invalid characters: %s" +msgstr "Le chemin du gabarit contient des caractères invalides: %s" + +#: Pluf/Translation/TemplateExtractor.php:276 +#: Pluf/Template/Compiler.php:354 +#, php-format +msgid "Template file not found: %s" +msgstr "Fichier gabarit %s introuvable." + +#: Pluf/Translation/TemplateExtractor.php:283 +#, php-format +msgid "Invalid tag in translation extractor: %s" +msgstr "Marqueur invalide dans l'extraction des traductions: %s" + +#: Pluf/Translation/TemplateExtractor.php:288 +#: Pluf/Template/Compiler.php:375 +#, php-format +msgid "Invalid function syntax: %s" +msgstr "Syntaxe de fonction invalide : %s" + +#: Pluf/Translation/TemplateExtractor.php:305 +#: Pluf/Template/Compiler.php:361 +#, php-format +msgid "Invalid tag syntax: %s" +msgstr "Syntaxe du marqueur invalide : %s" + +#: Pluf/Translation/TemplateExtractor.php:390 +#: Pluf/Template/Compiler.php:629 +#, php-format +msgid "Invalid syntax: (%s) %s." +msgstr "Syntaxe invalide : (%s) %s." + +#: Pluf/Translation/TemplateExtractor.php:395 +#: Pluf/Template/Compiler.php:634 +#, php-format +msgid "Invalid character: (%s) %s." +msgstr "Caractère invalide : (%s) %s." + +#: Pluf/User.php:61 +msgid "login" +msgstr "identifiant" + +#: Pluf/User.php:68 +msgid "first name" +msgstr "prénom" + +#: Pluf/User.php:75 +msgid "last name" +msgstr "nom de famille" + +#: Pluf/User.php:81 +msgid "email" +msgstr "email" + +#: Pluf/User.php:87 +msgid "password" +msgstr "mot de passe" + +#: Pluf/User.php:89 +msgid "Format: [algo]:[salt]:[hash]" +msgstr "Format : [algo]:[salt]:[hash]" + +#: Pluf/User.php:108 +msgid "administrator" +msgstr "administrateur" + +#: Pluf/User.php:115 +msgid "staff" +msgstr "staff" + +#: Pluf/User.php:122 +msgid "active" +msgstr "actif" + +#: Pluf/User.php:130 +msgid "language" +msgstr "langage" + +#: Pluf/User.php:131 +msgid "Prefered language of the user for the interface. Use the 2 or 5 letter code like \"fr\", \"en\", \"fr_QC\" or \"en_US\"." +msgstr "Langue de l'interface pour l'utilisateur. Utilisez le code à 2 ou 5 lettres comme \"fr\", \"en\", \"fr_QC\" ou \"en_US\"." + +#: Pluf/User.php:139 +msgid "time zone" +msgstr "Fuseau horaire" + +#: Pluf/User.php:140 +msgid "Time zone of the user to display the time in local time." +msgstr "Zone de l'utilisateur pour afficher l'heure correctement." + +#: Pluf/User.php:146 +msgid "date joined" +msgstr "date d'inscription" + +#: Pluf/User.php:153 +msgid "last login" +msgstr "dernière connexion" + +#: Pluf/User.php:417 +msgid "\"user_profile_class\" setting not defined." +msgstr "La variable de configuration \"user_profile_class\" n'est pas définie." + +#: Pluf/User.php:424 +#, php-format +msgid "No profiles available for user: %s" +msgstr "Aucun profile disponible pour l'utilisateur : %s" + +#: Pluf/Error.php:93 +msgid "DB error:" +msgstr "Erreur de la base de données :" + +#: Pluf/Form/Field/Float.php:39 +msgid "Enter a number." +msgstr "Entrez un nombre." + +#: Pluf/Form/Field/Float.php:42 +#, php-format +msgid "Ensure this value is less than or equal to %s." +msgstr "Assurez-vous que la valeur est inférieure ou égale à %s. " + +#: Pluf/Form/Field/Float.php:45 +#, php-format +msgid "Ensure this value is greater than or equal to %s." +msgstr "Assurez-vous que la valeur est supérieure ou égale à %s." + +#: Pluf/Form/Field/Email.php:38 +msgid "Enter a valid email address." +msgstr "Entrez une adresse email valide." + +#: Pluf/Form/Field/Datetime.php:61 +msgid "Enter a valid date/time." +msgstr "Entrez une date/heure valide." + +#: Pluf/Form/Field/Url.php:35 +msgid "Enter a valid address." +msgstr "Entrez une adresse valide." + +#: Pluf/Form/Field/Integer.php:40 +#: Pluf/Form/Field/Integer.php:49 +#: Pluf/Encoder.php:138 +msgid "The value must be an integer." +msgstr "La valeur doit être un nombre entier." + +#: Pluf/Form/Field/Integer.php:59 +#, php-format +msgid "Ensure that this value is not greater than %1$d." +msgstr "Assurez-vous que la valeur ne soit pas supérieure à %1$d." + +#: Pluf/Form/Field/Integer.php:62 +#, php-format +msgid "Ensure that this value is not lower than %1$d." +msgstr "Assurez-vous que la valeur ne soit pas inférieure à %1$d." + +#: Pluf/Form/Field/Date.php:46 +msgid "Enter a valid date." +msgstr "Entrez une date valide." + +#: Pluf/Form/Field/Varchar.php:38 +#, php-format +msgid "Ensure this value has at most %1$d characters (it has %2$d)." +msgstr "Assurez-vous que la valeur ait au maximum %1$d caractères (elle en contient %2$d)." + +#: Pluf/Form/Field/Varchar.php:41 +#, php-format +msgid "Ensure this value has at least %1$d characters (it has %2$d)." +msgstr "Assurez-vous que la valeur ait au minimum %1$d caractères (elle en contient %2$d)." + +#: Pluf/Form/Field/File.php:43 +#: Pluf/Form/Field/File.php:59 +msgid "No files were uploaded. Please try to send the file again." +msgstr "Aucun fichier n'a été transmis. Essayez d'envoyer le fichier une nouvelle fois." + +#: Pluf/Form/Field/File.php:52 +msgid "The uploaded file is too large. Reduce the size of the file and send it again." +msgstr "Le fichier transmis est trop gros. Réduisez la taille du fichier et transmettez le une nouvelle fois." + +#: Pluf/Form/Field/File.php:55 +msgid "The upload did not complete. Please try to send the file again." +msgstr "L'envoi du fichier ne s'est pas achevé. Essayez de l'envoyer une nouvelle fois." + +#: Pluf/Form/Field/File.php:66 +msgid "The server has no temporary folder correctly configured to store the uploaded file." +msgstr "Le serveur n'a pas de répertoire temporaire correctement configuré pour stocker les fichiers transmis." + +#: Pluf/Form/Field/File.php:69 +msgid "The uploaded file has been stopped by an extension." +msgstr "Le fichier transmis a été bloqué par une extension." + +#: Pluf/Form/Field/File.php:72 +msgid "An error occured when upload the file. Please try to send the file again." +msgstr "Une erreur est survenu pendant la transmission du fichier. Essayez de transmettre le fichier de nouveau." + +#: Pluf/Form/Field/File.php:75 +#, php-format +msgid "The uploaded file is to big (%1$s). Reduce the size to less than %2$s and try again." +msgstr "Le fichier transmis est trop gros (%1$s). Essayez d'obtenir une taille inférieure à %2$s et essayez de nouveau." + +#: Pluf/Form/Field/File.php:136 +msgid "An error occured when creating the upload path. Please try to send the file again." +msgstr "Une erreur est survenu pendant la création du chemin de stockage. Essayez de transmettre le fichier de nouveau." + +#: Pluf/Form/Field/File.php:140 +#, php-format +msgid "A file with the name \"%s\" has already been uploaded." +msgstr "Un fichier avec le nom \"%s\" a déjà été envoyé." + +#: Pluf/Form/Field/File.php:143 +msgid "An error occured when uploading the file. Please try to send the file again." +msgstr "Une erreur est survenu pendant la transmission du fichier. Essayez de transmettre le fichier de nouveau." + +#: Pluf/Form/Field.php:115 +msgid "This field is required." +msgstr "Ce champ est à fournir." + +#: Pluf/Form/Model.php:82 +msgid "Cannot save the model from an invalid form." +msgstr "Ne peut pas sauvegarder le modèle depuis un formulaire non valide." + +#: Pluf/Queue.php:51 +msgid "message queue" +msgstr "queue de messages" + +#: Pluf/Queue.php:80 +msgid "action" +msgstr "action" + +#: Pluf/Queue.php:86 +msgid "lock status" +msgstr "Statut du lock" + +#: Pluf/Queue.php:89 +msgid "Free" +msgstr "Libre" + +#: Pluf/Queue.php:90 +msgid "In progress" +msgstr "En cours" + +#: Pluf/Queue.php:91 +msgid "Completed" +msgstr "Terminé" + +#: Pluf/Group.php:30 +msgid "group" +msgstr "groupe" + +#: Pluf/Group.php:46 +#: Pluf/Permission.php:46 +msgid "name" +msgstr "nom" + +#: Pluf/Group.php:53 +#: Pluf/Permission.php:61 +msgid "description" +msgstr "description" + +#: Pluf/Permission.php:30 +#: Pluf/RowPermission.php:79 +msgid "permission" +msgstr "permission" + +#: Pluf/Permission.php:53 +msgid "code name" +msgstr "nom de code" + +#: Pluf/Permission.php:54 +msgid "The code name must be unique for each application. Standard permissions to manage a model in the interface are \"Model_Name-create\", \"Model_Name-update\", \"Model_Name-list\" and \"Model_Name-delete\"." +msgstr "Le code doit être unique pour chaque application. Les permissions de base sont \"Model_Name-create\", \"Model_Name-update\", \"Model_Name-list\" et \"Model_Name-delete\"." + +#: Pluf/Permission.php:68 +msgid "application" +msgstr "application" + +#: Pluf/Permission.php:69 +msgid "The application using this permission, for example \"YourApp\", \"CMS\" or \"SView\"." +msgstr "L'application utilisant cette permission, par exemple \"VotreApp\", \"CMS\", etc." + +#: Pluf/Date.php:206 +#, php-format +msgid "%s ago" +msgstr "il y a %s" + +#: Pluf/Date.php:208 +#, php-format +msgid "%s left" +msgstr "%s restant" + +#: Pluf/Calendar.php:318 +msgid "Sunday" +msgstr "dimanche" + +#: Pluf/Calendar.php:319 +msgid "Monday" +msgstr "lundi" + +#: Pluf/Calendar.php:320 +msgid "Tuesday" +msgstr "mardi" + +#: Pluf/Calendar.php:321 +msgid "Wednesday" +msgstr "mercredi" + +#: Pluf/Calendar.php:322 +msgid "Thursday" +msgstr "jeudi" + +#: Pluf/Calendar.php:323 +msgid "Friday" +msgstr "vendredi" + +#: Pluf/Calendar.php:324 +msgid "Saturday" +msgstr "samedi" + +#: Pluf/Encoder.php:62 +msgid "The value must not be empty." +msgstr "La valeur ne doit pas être vide." + +#: Pluf/Encoder.php:81 +#, php-format +msgid "The URL %s is not valid." +msgstr "L'URL %s n'est pas valide." + +#: Pluf/Encoder.php:88 +#, php-format +msgid "The value should not be more than %s characters long." +msgstr "La valeur ne doit pas faire plus de %s caractères." + +#: Pluf/Encoder.php:96 +#, php-format +msgid "The password must be at least %s characters long." +msgstr "Le password doit avoir au minimum %s caractères." + +#: Pluf/Encoder.php:106 +#, php-format +msgid "The email address \"%s\" is not valid." +msgstr "L'adresse email \"%s\" n'est pas valid." + +#: Pluf/Encoder.php:146 +#, php-format +msgid "The date and time %s are not valid." +msgstr "Le jour et l'heure %s ne sont pas valides." + +#: Pluf/Encoder.php:157 +#, php-format +msgid "The date %s is not valid." +msgstr "La date %s n'est pas valide." + +#: Pluf/Model.php:429 +#, php-format +msgid "The view \"%s\" is not defined." +msgstr "La vue \"%s\" n'est pas définie." + +#: Pluf/Model.php:578 +#, php-format +msgid "No matching foreign key found in model: %s for model %s" +msgstr "Aucune clef étrangère trouvé dans le modèle %s pour le modèle %s" + +#: Pluf/Template.php:142 +#, php-format +msgid "Cannot write the compiled template: %s" +msgstr "Ne peut pas écrire le gabarit compilé: %s" + +#: Pluf/Template.php:270 +#: Pluf/Template.php:272 +#: Pluf/Template.php:284 +#: Pluf/Template.php:286 +#: Pluf/Paginator.php:713 +msgid "now" +msgstr "maintenant" + +#: Pluf/Paginator.php:396 +msgid "Prev" +msgstr "Préc" + +#: Pluf/Paginator.php:407 +msgid "Next" +msgstr "Suivant" + +#: Pluf/Paginator.php:558 +msgid "Name" +msgstr "Nom" + +#: Pluf/Paginator.php:595 +msgid "Sort" +msgstr "Ordre" + +#: Pluf/Paginator.php:598 +msgid "asc" +msgstr "asc" + +#: Pluf/Paginator.php:601 +msgid "desc" +msgstr "desc" + +#: Pluf/Paginator.php:617 +msgid "Filter the list:" +msgstr "Filtrer la liste :" + +#: Pluf/Paginator.php:620 +msgid "Filter" +msgstr "Filtre" + +#: Pluf/Test/Fixture.php:41 +#, php-format +msgid "Fixture file not found: %s." +msgstr "Fichier de fixtures non trouvé : %s." + +#: Pluf/Test/Fixture.php:56 +#, php-format +msgid "Cannot load existing model <%1$s(%2$s)>." +msgstr "Ne peut pas charger le modèle <%1$s(%2$s)>." + +#: Pluf/Views.php:63 +msgid "The login or the password is not valid. The login and the password are case sensitive." +msgstr "L'identifiant ou le mot de passe n'est pas valide. Les majuscules/minuscules doivent être respectées." + +#: Pluf/Views.php:66 +msgid "You need to enable the cookies in your browser to access this website." +msgstr "Vous devez activer les cookies dans votre navigateur pour accéder à ce site." + +#: Pluf/Views.php:82 +msgid "Sign In" +msgstr "Se connecter" + +#: Pluf/Views.php:180 +#: Pluf/Views.php:256 +#, php-format +msgid "The %s was created successfully." +msgstr "Le %s a été crée avec succès." + +#: Pluf/Views.php:325 +#, php-format +msgid "The %s was deleted successfully." +msgstr "Le %s a été supprimé avec succès." + +#: Pluf/Utils.php:89 +msgid "MB" +msgstr "Mo" + +#: Pluf/Utils.php:91 +msgid "kB" +msgstr "ko" + +#: Pluf/Utils.php:93 +msgid "bytes" +msgstr "octets" + +#: Pluf/Form.php:228 +#, php-format +msgid "(Hidden field %1$s) %2$s" +msgstr "(Champ caché %1$s) %2$s" + +#: Pluf/Template/Compiler.php:262 +#: Pluf/Template/Compiler.php:427 +#: Pluf/Template/Compiler.php:433 +#: Pluf/Template/Compiler.php:450 +#: Pluf/Template/Compiler.php:493 +#, php-format +msgid "End tag of a block missing: %s" +msgstr "Fin du marqueur de bloc manquant: %s" + +#: Pluf/Template/Compiler.php:398 +#, php-format +msgid "Invalid modifier syntax: (%s) %s" +msgstr "Syntaxe de modificateur invalide : %s" + +#: Pluf/Template/Compiler.php:408 +#, php-format +msgid "Unknown modifier: (%s) %s" +msgstr "Modificateur inconnu: (%s) %s" + +#: Pluf/Template/Compiler.php:462 +msgid "End tag of a block missing: literal" +msgstr "Fin du marqueur de bloc manquant: literal" + +#: Pluf/Template/Compiler.php:466 +msgid "Start tag of a block missing: literal" +msgstr "Début du marqueur de bloc manquant: literal" + +#: Pluf/Template/Compiler.php:548 +#, php-format +msgid "The function tag \"%s\" is not allowed." +msgstr "Le tag \"%s\" n'est pas autorisé." + +#: Pluf/Template/Compiler.php:572 +#, php-format +msgid "The function tag \"{%s ...}\" is not supported." +msgstr "Le tag \"{%s ...}\" n'est pas supporté." + +#: Pluf/RowPermission.php:44 +msgid "model ID" +msgstr "ID du modèle" + +#: Pluf/RowPermission.php:57 +msgid "owner ID" +msgstr "ID du propriétaire" + +#: Pluf/RowPermission.php:64 +msgid "owner class" +msgstr "Class du propriètaire" + +#: Pluf/RowPermission.php:65 +msgid "For example Pluf_User or Pluf_Group." +msgstr "Par exemple Pluf_User ou Pluf_Group." + +#: Pluf/RowPermission.php:72 +msgid "do not have the permission" +msgstr "n'a pas la permission" + +#: Pluf/Date.php:179 +msgid "year" +msgid_plural "years" +msgstr[0] "an" +msgstr[1] "ans" + +#: Pluf/Date.php:182 +msgid "month" +msgid_plural "months" +msgstr[0] "mois" +msgstr[1] "mois" + +#: Pluf/Date.php:185 +msgid "day" +msgid_plural "days" +msgstr[0] "jour" +msgstr[1] "jours" + +#: Pluf/Date.php:188 +msgid "hour" +msgid_plural "hours" +msgstr[0] "heure" +msgstr[1] "heures" + +#: Pluf/Date.php:191 +msgid "minute" +msgid_plural "minutes" +msgstr[0] "minute" +msgstr[1] "minutes" + +#: Pluf/Date.php:194 +msgid "second" +msgid_plural "seconds" +msgstr[0] "seconde" +msgstr[1] "secondes" + +#~ msgid "years" +#~ msgstr "années" +#~ msgid "months" +#~ msgstr "mois" +#~ msgid "days" +#~ msgstr "jours" +#~ msgid "hours" +#~ msgstr "heures" +#~ msgid "minutes" +#~ msgstr "minutes" +#~ msgid "seconds" +#~ msgstr "secondes" +#~ msgid "Authentication" +#~ msgstr "Authentification" +#~ msgid "KB" +#~ msgstr "Ko" +#~ msgid "The page %s was not found on the server." +#~ msgstr "La page %s n'a pas été trouvée sur le serveur." + diff --git a/pluf/src/Pluf/locale/pluf.pot b/pluf/src/Pluf/locale/pluf.pot new file mode 100644 index 0000000..e6a60b1 --- /dev/null +++ b/pluf/src/Pluf/locale/pluf.pot @@ -0,0 +1,638 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2009-02-02 13:56+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" + +#: Pluf/Search/Stats.php:34 +msgid "search stats" +msgstr "" + +#: Pluf/Search/Stats.php:50 Pluf/Search/Occ.php:56 Pluf/Queue.php:67 +#: Pluf/RowPermission.php:51 +msgid "model class" +msgstr "" + +#: Pluf/Search/Stats.php:56 Pluf/Search/Occ.php:62 Pluf/Queue.php:73 +msgid "model id" +msgstr "" + +#: Pluf/Search/Stats.php:62 +msgid "number of indexations" +msgstr "" + +#: Pluf/Search/Stats.php:69 Pluf/Queue.php:98 +msgid "created at" +msgstr "" + +#: Pluf/Search/Stats.php:75 Pluf/Queue.php:104 +msgid "modified at" +msgstr "" + +#: Pluf/Search/Word.php:33 Pluf/Search/Word.php:50 Pluf/Search/Occ.php:49 +msgid "word" +msgstr "" + +#: Pluf/Search/Occ.php:33 +msgid "occurence" +msgstr "" + +#: Pluf/Search/Occ.php:68 +msgid "occurences" +msgstr "" + +#: Pluf/Search/Occ.php:74 +msgid "weighted occurence" +msgstr "" + +#: Pluf/Message.php:45 Pluf/User.php:44 +msgid "user" +msgstr "" + +#: Pluf/HTTP/Response/RedirectToLogin.php:56 +#: Pluf/HTTP/Response/Redirect.php:28 +#, php-format +msgid "Please, click here to be redirected." +msgstr "" + +#: Pluf/Text/LaTeX/Equation.php:243 +msgid "Unable to generate the dvi file." +msgstr "" + +#: Pluf/Text/LaTeX/Equation.php:260 +msgid "Unable to generate the png file." +msgstr "" + +#: Pluf/Text/LaTeX/Equation.php:270 +msgid "Unable to move the png file." +msgstr "" + +#: Pluf/Text/LaTeX/Equation.php:308 +#, php-format +msgid "The LaTeX tag \"%s\" is not acceptable." +msgstr "" + +#: Pluf/Translation/TemplateExtractor.php:267 Pluf/Template/Compiler.php:345 +#, php-format +msgid "Template file contains invalid characters: %s" +msgstr "" + +#: Pluf/Translation/TemplateExtractor.php:276 Pluf/Template/Compiler.php:354 +#, php-format +msgid "Template file not found: %s" +msgstr "" + +#: Pluf/Translation/TemplateExtractor.php:283 +#, php-format +msgid "Invalid tag in translation extractor: %s" +msgstr "" + +#: Pluf/Translation/TemplateExtractor.php:288 Pluf/Template/Compiler.php:375 +#, php-format +msgid "Invalid function syntax: %s" +msgstr "" + +#: Pluf/Translation/TemplateExtractor.php:305 Pluf/Template/Compiler.php:361 +#, php-format +msgid "Invalid tag syntax: %s" +msgstr "" + +#: Pluf/Translation/TemplateExtractor.php:390 Pluf/Template/Compiler.php:629 +#, php-format +msgid "Invalid syntax: (%s) %s." +msgstr "" + +#: Pluf/Translation/TemplateExtractor.php:395 Pluf/Template/Compiler.php:634 +#, php-format +msgid "Invalid character: (%s) %s." +msgstr "" + +#: Pluf/User.php:61 +msgid "login" +msgstr "" + +#: Pluf/User.php:68 +msgid "first name" +msgstr "" + +#: Pluf/User.php:75 +msgid "last name" +msgstr "" + +#: Pluf/User.php:81 +msgid "email" +msgstr "" + +#: Pluf/User.php:87 +msgid "password" +msgstr "" + +#: Pluf/User.php:89 +msgid "Format: [algo]:[salt]:[hash]" +msgstr "" + +#: Pluf/User.php:108 +msgid "administrator" +msgstr "" + +#: Pluf/User.php:115 +msgid "staff" +msgstr "" + +#: Pluf/User.php:122 +msgid "active" +msgstr "" + +#: Pluf/User.php:130 +msgid "language" +msgstr "" + +#: Pluf/User.php:131 +msgid "" +"Prefered language of the user for the interface. Use the 2 or 5 letter code " +"like \"fr\", \"en\", \"fr_QC\" or \"en_US\"." +msgstr "" + +#: Pluf/User.php:139 +msgid "time zone" +msgstr "" + +#: Pluf/User.php:140 +msgid "Time zone of the user to display the time in local time." +msgstr "" + +#: Pluf/User.php:146 +msgid "date joined" +msgstr "" + +#: Pluf/User.php:153 +msgid "last login" +msgstr "" + +#: Pluf/User.php:417 +msgid "\"user_profile_class\" setting not defined." +msgstr "" + +#: Pluf/User.php:424 +#, php-format +msgid "No profiles available for user: %s" +msgstr "" + +#: Pluf/Error.php:93 +msgid "DB error:" +msgstr "" + +#: Pluf/Form/Field/Float.php:39 +msgid "Enter a number." +msgstr "" + +#: Pluf/Form/Field/Float.php:42 +#, php-format +msgid "Ensure this value is less than or equal to %s." +msgstr "" + +#: Pluf/Form/Field/Float.php:45 +#, php-format +msgid "Ensure this value is greater than or equal to %s." +msgstr "" + +#: Pluf/Form/Field/Email.php:38 +msgid "Enter a valid email address." +msgstr "" + +#: Pluf/Form/Field/Datetime.php:61 +msgid "Enter a valid date/time." +msgstr "" + +#: Pluf/Form/Field/Url.php:35 +msgid "Enter a valid address." +msgstr "" + +#: Pluf/Form/Field/Integer.php:40 Pluf/Form/Field/Integer.php:49 +#: Pluf/Encoder.php:138 +msgid "The value must be an integer." +msgstr "" + +#: Pluf/Form/Field/Integer.php:59 +#, php-format +msgid "Ensure that this value is not greater than %1$d." +msgstr "" + +#: Pluf/Form/Field/Integer.php:62 +#, php-format +msgid "Ensure that this value is not lower than %1$d." +msgstr "" + +#: Pluf/Form/Field/Date.php:46 +msgid "Enter a valid date." +msgstr "" + +#: Pluf/Form/Field/Varchar.php:38 +#, php-format +msgid "Ensure this value has at most %1$d characters (it has %2$d)." +msgstr "" + +#: Pluf/Form/Field/Varchar.php:41 +#, php-format +msgid "Ensure this value has at least %1$d characters (it has %2$d)." +msgstr "" + +#: Pluf/Form/Field/File.php:43 Pluf/Form/Field/File.php:59 +msgid "No files were uploaded. Please try to send the file again." +msgstr "" + +#: Pluf/Form/Field/File.php:52 +msgid "" +"The uploaded file is too large. Reduce the size of the file and send it " +"again." +msgstr "" + +#: Pluf/Form/Field/File.php:55 +msgid "The upload did not complete. Please try to send the file again." +msgstr "" + +#: Pluf/Form/Field/File.php:66 +msgid "" +"The server has no temporary folder correctly configured to store the " +"uploaded file." +msgstr "" + +#: Pluf/Form/Field/File.php:69 +msgid "The uploaded file has been stopped by an extension." +msgstr "" + +#: Pluf/Form/Field/File.php:72 +msgid "" +"An error occured when upload the file. Please try to send the file again." +msgstr "" + +#: Pluf/Form/Field/File.php:75 +#, php-format +msgid "" +"The uploaded file is to big (%1$s). Reduce the size to less than %2$s and " +"try again." +msgstr "" + +#: Pluf/Form/Field/File.php:136 +msgid "" +"An error occured when creating the upload path. Please try to send the file " +"again." +msgstr "" + +#: Pluf/Form/Field/File.php:140 +#, php-format +msgid "A file with the name \"%s\" has already been uploaded." +msgstr "" + +#: Pluf/Form/Field/File.php:143 +msgid "" +"An error occured when uploading the file. Please try to send the file again." +msgstr "" + +#: Pluf/Form/Field.php:115 +msgid "This field is required." +msgstr "" + +#: Pluf/Form/Model.php:82 +msgid "Cannot save the model from an invalid form." +msgstr "" + +#: Pluf/Queue.php:51 +msgid "message queue" +msgstr "" + +#: Pluf/Queue.php:80 +msgid "action" +msgstr "" + +#: Pluf/Queue.php:86 +msgid "lock status" +msgstr "" + +#: Pluf/Queue.php:89 +msgid "Free" +msgstr "" + +#: Pluf/Queue.php:90 +msgid "In progress" +msgstr "" + +#: Pluf/Queue.php:91 +msgid "Completed" +msgstr "" + +#: Pluf/Group.php:30 +msgid "group" +msgstr "" + +#: Pluf/Group.php:46 Pluf/Permission.php:46 +msgid "name" +msgstr "" + +#: Pluf/Group.php:53 Pluf/Permission.php:61 +msgid "description" +msgstr "" + +#: Pluf/Permission.php:30 Pluf/RowPermission.php:79 +msgid "permission" +msgstr "" + +#: Pluf/Permission.php:53 +msgid "code name" +msgstr "" + +#: Pluf/Permission.php:54 +msgid "" +"The code name must be unique for each application. Standard permissions to " +"manage a model in the interface are \"Model_Name-create\", \"Model_Name-" +"update\", \"Model_Name-list\" and \"Model_Name-delete\"." +msgstr "" + +#: Pluf/Permission.php:68 +msgid "application" +msgstr "" + +#: Pluf/Permission.php:69 +msgid "" +"The application using this permission, for example \"YourApp\", \"CMS\" or " +"\"SView\"." +msgstr "" + +#: Pluf/Date.php:179 +msgid "year" +msgid_plural "years" +msgstr[0] "" +msgstr[1] "" + +#: Pluf/Date.php:182 +msgid "month" +msgid_plural "months" +msgstr[0] "" +msgstr[1] "" + +#: Pluf/Date.php:185 +msgid "day" +msgid_plural "days" +msgstr[0] "" +msgstr[1] "" + +#: Pluf/Date.php:188 +msgid "hour" +msgid_plural "hours" +msgstr[0] "" +msgstr[1] "" + +#: Pluf/Date.php:191 +msgid "minute" +msgid_plural "minutes" +msgstr[0] "" +msgstr[1] "" + +#: Pluf/Date.php:194 +msgid "second" +msgid_plural "seconds" +msgstr[0] "" +msgstr[1] "" + +#: Pluf/Date.php:206 +#, php-format +msgid "%s ago" +msgstr "" + +#: Pluf/Date.php:208 +#, php-format +msgid "%s left" +msgstr "" + +#: Pluf/Calendar.php:318 +msgid "Sunday" +msgstr "" + +#: Pluf/Calendar.php:319 +msgid "Monday" +msgstr "" + +#: Pluf/Calendar.php:320 +msgid "Tuesday" +msgstr "" + +#: Pluf/Calendar.php:321 +msgid "Wednesday" +msgstr "" + +#: Pluf/Calendar.php:322 +msgid "Thursday" +msgstr "" + +#: Pluf/Calendar.php:323 +msgid "Friday" +msgstr "" + +#: Pluf/Calendar.php:324 +msgid "Saturday" +msgstr "" + +#: Pluf/Encoder.php:62 +msgid "The value must not be empty." +msgstr "" + +#: Pluf/Encoder.php:81 +#, php-format +msgid "The URL %s is not valid." +msgstr "" + +#: Pluf/Encoder.php:88 +#, php-format +msgid "The value should not be more than %s characters long." +msgstr "" + +#: Pluf/Encoder.php:96 +#, php-format +msgid "The password must be at least %s characters long." +msgstr "" + +#: Pluf/Encoder.php:106 +#, php-format +msgid "The email address \"%s\" is not valid." +msgstr "" + +#: Pluf/Encoder.php:146 +#, php-format +msgid "The date and time %s are not valid." +msgstr "" + +#: Pluf/Encoder.php:157 +#, php-format +msgid "The date %s is not valid." +msgstr "" + +#: Pluf/Model.php:429 +#, php-format +msgid "The view \"%s\" is not defined." +msgstr "" + +#: Pluf/Model.php:578 +#, php-format +msgid "No matching foreign key found in model: %s for model %s" +msgstr "" + +#: Pluf/Template.php:142 +#, php-format +msgid "Cannot write the compiled template: %s" +msgstr "" + +#: Pluf/Template.php:270 Pluf/Template.php:272 Pluf/Template.php:284 +#: Pluf/Template.php:286 Pluf/Paginator.php:713 +msgid "now" +msgstr "" + +#: Pluf/Paginator.php:396 +msgid "Prev" +msgstr "" + +#: Pluf/Paginator.php:407 +msgid "Next" +msgstr "" + +#: Pluf/Paginator.php:558 +msgid "Name" +msgstr "" + +#: Pluf/Paginator.php:595 +msgid "Sort" +msgstr "" + +#: Pluf/Paginator.php:598 +msgid "asc" +msgstr "" + +#: Pluf/Paginator.php:601 +msgid "desc" +msgstr "" + +#: Pluf/Paginator.php:617 +msgid "Filter the list:" +msgstr "" + +#: Pluf/Paginator.php:620 +msgid "Filter" +msgstr "" + +#: Pluf/Test/Fixture.php:41 +#, php-format +msgid "Fixture file not found: %s." +msgstr "" + +#: Pluf/Test/Fixture.php:56 +#, php-format +msgid "Cannot load existing model <%1$s(%2$s)>." +msgstr "" + +#: Pluf/Views.php:63 +msgid "" +"The login or the password is not valid. The login and the password are case " +"sensitive." +msgstr "" + +#: Pluf/Views.php:66 +msgid "You need to enable the cookies in your browser to access this website." +msgstr "" + +#: Pluf/Views.php:82 +msgid "Sign In" +msgstr "" + +#: Pluf/Views.php:180 Pluf/Views.php:256 +#, php-format +msgid "The %s was created successfully." +msgstr "" + +#: Pluf/Views.php:325 +#, php-format +msgid "The %s was deleted successfully." +msgstr "" + +#: Pluf/Utils.php:89 +msgid "MB" +msgstr "" + +#: Pluf/Utils.php:91 +msgid "kB" +msgstr "" + +#: Pluf/Utils.php:93 +msgid "bytes" +msgstr "" + +#: Pluf/Form.php:228 +#, php-format +msgid "(Hidden field %1$s) %2$s" +msgstr "" + +#: Pluf/Template/Compiler.php:262 Pluf/Template/Compiler.php:427 +#: Pluf/Template/Compiler.php:433 Pluf/Template/Compiler.php:450 +#: Pluf/Template/Compiler.php:493 +#, php-format +msgid "End tag of a block missing: %s" +msgstr "" + +#: Pluf/Template/Compiler.php:398 +#, php-format +msgid "Invalid modifier syntax: (%s) %s" +msgstr "" + +#: Pluf/Template/Compiler.php:408 +#, php-format +msgid "Unknown modifier: (%s) %s" +msgstr "" + +#: Pluf/Template/Compiler.php:462 +msgid "End tag of a block missing: literal" +msgstr "" + +#: Pluf/Template/Compiler.php:466 +msgid "Start tag of a block missing: literal" +msgstr "" + +#: Pluf/Template/Compiler.php:548 +#, php-format +msgid "The function tag \"%s\" is not allowed." +msgstr "" + +#: Pluf/Template/Compiler.php:572 +#, php-format +msgid "The function tag \"{%s ...}\" is not supported." +msgstr "" + +#: Pluf/RowPermission.php:44 +msgid "model ID" +msgstr "" + +#: Pluf/RowPermission.php:57 +msgid "owner ID" +msgstr "" + +#: Pluf/RowPermission.php:64 +msgid "owner class" +msgstr "" + +#: Pluf/RowPermission.php:65 +msgid "For example Pluf_User or Pluf_Group." +msgstr "" + +#: Pluf/RowPermission.php:72 +msgid "do not have the permission" +msgstr "" diff --git a/pluf/src/Pluf/relations.php b/pluf/src/Pluf/relations.php new file mode 100644 index 0000000..c90c4dd --- /dev/null +++ b/pluf/src/Pluf/relations.php @@ -0,0 +1,60 @@ + array( + 'relate_to_many' => array( + $group_model, + 'Pluf_Permission', + ), + ), + $group_model => array( + 'relate_to_many' => array( + 'Pluf_Permission', + ), + ), + 'Pluf_Message' => array( + 'relate_to' => array( + $user_model, + ), + ), + 'Pluf_RowPermission' => array( + 'relate_to' => array( + 'Pluf_Permission', + ), + ), + 'Pluf_Search_Occ' => array( + 'relate_to' => array( + 'Pluf_Search_Word', + ), + ), + ); diff --git a/pluf/src/Pluf/templates/pluf/ab/base.html b/pluf/src/Pluf/templates/pluf/ab/base.html new file mode 100644 index 0000000..a1de9ec --- /dev/null +++ b/pluf/src/Pluf/templates/pluf/ab/base.html @@ -0,0 +1,183 @@ + +{* +Simple base for the A/B dashboard. + +It contains the standard header and footer. +*} + + +{trans 'A/B Testing Dashboard'} + + + +
    +
    {block body}{/block}
    +
    {block details}{/block}
    +
    +
    + + diff --git a/pluf/src/Pluf/templates/pluf/ab/dashboard.html b/pluf/src/Pluf/templates/pluf/ab/dashboard.html new file mode 100644 index 0000000..364b5b3 --- /dev/null +++ b/pluf/src/Pluf/templates/pluf/ab/dashboard.html @@ -0,0 +1,68 @@ +{extends "pluf/ab/base.html"} + +{block body} +

    A/B Testing Dashboard

    +{foreach $active as $test} +

    Test {$test['_id']}

    +
    '. $this->_renderInlineTag($result[$i]).'
    {assign $alts=$test['stats']} +{foreach $alts as $alt} + + + + +{if $can_edit} + +{/if} + + + + + + +{/foreach} +
    Option {$alt['alt']}{$test['alts'][$alt['alt']]|dump}{$alt['nconvr']}{if $alt['better']} ({$alt['comp']} change){/if} +
    + + + +
    +
    +Conv: {$alt['conv']}/{$alt['exp']}{if $alt['conf']} - Conf: {$alt['conf']}{/if} +
    +{/foreach} + +{if count($active) == 0} +

    No running tests at the moment.

    +{/if} + +

    +The confidence is calculated with respect to the second best +alternative to evaluate if the best alternative is significantly +better than the second best. +

    + +
    + +{foreach $stopped as $test} +

    Stopped Test {$test['_id']}

    +{assign $alts=$test['stats']} +{foreach $alts as $alt} + + + + + + + + + + +{/foreach} +
    {if $test['winner'] == $alt['alt']}!{/if} Option {$alt['alt']}{$test['alts'][$alt['alt']]|dump}{$alt['nconvr']}{if $alt['better']} ({$alt['comp']} change){/if}
    +Conv: {$alt['conv']}/{$alt['exp']}{if $alt['conf']} - Conf: {$alt['conf']}{/if} +
    +{/foreach} + + +{/block} + diff --git a/pluf/src/Pluf/templates/pluf/ab/funnel.html b/pluf/src/Pluf/templates/pluf/ab/funnel.html new file mode 100644 index 0000000..2257f74 --- /dev/null +++ b/pluf/src/Pluf/templates/pluf/ab/funnel.html @@ -0,0 +1,91 @@ +{extends "pluf/ab/base.html"} +{block bodyclass} class="funnel"{/block} +{block body} +

    » All funnels

    + +

    Funnel {$funnel} - {$nperiod}

    + + + + + + + +
    + +

    +Today | +Yesterday | +Last 7 days | +All time +

    + + +{assign $i=1} +{foreach $stats as $n => $step} +{if $step} + +{if $i>1 and isset($step['conv'])} +

    {$step['total']} ({$step['conv']})

    +{/if} + +

    Step {$step['id']}: {$step['name']}

    +
    {if $i==1} +{if count($props)} +

    Filter by visitor property

    +
    + + + +
    +{/if} +{elseif isset($step['props']) and isset($step['sprops'])}{assign $stepprops = $step['sprops']} +
    + +{foreach $stepprops as $k=>$t} +

    {$k}
    {assign $nn = $t[1]} +{$t[0]} out of {blocktrans $nn}{$nn} visitor{plural}{$nn} visitors{/blocktrans}{if $t[2]} ({$t[2]}){/if} +{/foreach}

    + +
    +{/if} +
    +

    +{if $i>1 and isset($step['conv1'])} + +{if $step['conv1'] != '100.00%'}
    +{$step['conv1']}{/if} +{else} +  +{/if}
    {assign $t = $step['total']} +{blocktrans $t}{$t} unique visitor.{plural}{$t} unique visitors.{/blocktrans} +

    + +{/if}{assign $i += 1}{/foreach}
    +{if count($stats) and isset($step['conv1'])} +
    + +

    {$step['total']} out of {$step['bigtotal']} visitors reached step {$step['id']} of this funnel. +This is a completion rate of {$step['conv1']}.

    + +{if count($props) and isset($step['sprops1'])} + +
    {assign $stepprops = $step['sprops1']} +

    Visitor Property {$prop}

    +{foreach $stepprops as $k=>$t} +

    {$k}: {assign $nn = $t[1]} +{$t[0]} out of {blocktrans $nn}{$nn} visitor{plural}{$nn} visitors{/blocktrans}{if $t[2]} ({$t[2]}){/if} +{/foreach}

    +
    {/if} +

    +Note that if a user skip a given step, this can make the results a bit +off.{if count($props)} For the overall property funnel statistics, the first step where a given +appears is used as the base value.{/if} +

    +{else} +

    We do not have statistics for this period. See the statistics for all the visitor properties and all time.

    +{/if} +{/block} + diff --git a/pluf/src/Pluf/templates/pluf/ab/funnels.html b/pluf/src/Pluf/templates/pluf/ab/funnels.html new file mode 100644 index 0000000..633c61b --- /dev/null +++ b/pluf/src/Pluf/templates/pluf/ab/funnels.html @@ -0,0 +1,15 @@ +{extends "pluf/ab/base.html"} + +{block body} +

    Funnel Dashboard

    + +{if count($funnels)} +
      {foreach $funnels as $funnel} +
    • {$funnel}
    • +{/foreach}
    +{else} +

    You no funnel analysis running at the moment.

    +{/if} + +{/block} + diff --git a/pluf/src/extracttemplates.php b/pluf/src/extracttemplates.php new file mode 100644 index 0000000..310accf --- /dev/null +++ b/pluf/src/extracttemplates.php @@ -0,0 +1,53 @@ +generate($outputdir); +echo 'Done', "\n"; \ No newline at end of file diff --git a/pluf/src/makepot.sh b/pluf/src/makepot.sh new file mode 100644 index 0000000..90f4e99 --- /dev/null +++ b/pluf/src/makepot.sh @@ -0,0 +1,27 @@ +#!/bin/sh +# +# ***** BEGIN LICENSE BLOCK ***** +# This file is part of Plume Framework, a simple PHP Application Framework. +# Copyright (C) 2001-2007 Loic d'Anterroches and contributors. +# +# Plume Framework is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# Plume Framework is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# ***** END LICENSE BLOCK ***** */ +# +# Create the pot file for Pluf. +# +xgettext -o pluf.pot -p ./Pluf/locale --force-po --from-code=UTF-8 --keyword --keyword=__ --keyword=_n:1,2 -L PHP *.php +sleep 5 +find Pluf/ -iname "*.php" -exec xgettext -o pluf.pot -p ./Pluf/locale --from-code=UTF-8 -j --keyword --keyword=__ --keyword=_n:1,2 -L PHP {} \; diff --git a/pluf/src/migrate.php b/pluf/src/migrate.php new file mode 100644 index 0000000..095ac58 --- /dev/null +++ b/pluf/src/migrate.php @@ -0,0 +1,244 @@ +readPHPArgv(); + +function debug($what) +{ + global $debug; + if ($debug) { + echo($what."\n"); + } +} + +function usage() +{ + echo 'Usage examples:'."\n" + .' Upgrade all: migrate.php --conf=path/to/config.php -a'."\n" + .' Upgrade MyApp: migrate.php --conf=path/to/config.php --app=MyApp'."\n" + .' Backup MyApp: migrate.php --conf=path/to/config.php --app=MyApp -b /path/to/backup/folder [backupname]'."\n" + .' Restore MyApp: migrate.php --conf=path/to/config.php --app=MyApp -r /path/to/backup/folder backupname'."\n" + .' MyApp to ver. 3: migrate.php --conf=path/to/config.php --app=MyApp -v3'."\n" + .''."\n" + .'Options:'."\n" + .' c, --conf: Path to the configuration file.'."\n" + .' a: Upgrade all the installed applications.'."\n" + .' v, --version: Upgrade/Downgrade to the given version.'."\n" + .' --app: Application to upgrade/downgrade.'."\n" + .' u: Dry run, do nothing.'."\n" + .' --search-path: Set the DB search path before the run.'."\n" + .' --include-path: Paths to add to the PHP include path.'."\n" + .' d: Display debug information.'."\n" + .' i: Install the application(s).'."\n" + .' x: Uninstall the application(s).'."\n" + .' b: Backup the application(s).'."\n" + .' r: Restore the application(s).'."\n" + .''."\n" + .'Note: The command line parser of PEAR is not very robust'."\n" + .' if you have an unexpected error about an offset not'."\n" + .' set. Please report a bug. Thanks!'."\n"; + +} + +try { + $ret = $cg->getopt($args, $shortoptions, $longoptions); +} catch (Exception $e) { + echo('Error in getopt command line: '.$e->getMessage()."\n"); + usage(); + die(); +} + +// Note that PEAR is not PHP 5 compatible, so the need to create $p. +$p = new PEAR(); +if ($p->isError($ret)) { + echo('Error in command line: '.$ret->getMessage()."\n"); + usage(); + die(); +} + +// Parse the options. +$what = array( + 'all' => false, + 'app' => '', + 'conf' => '', + 'version' => null, + 'dry_run' => false, + 'un-install' => false, + 'install' => false, + 'backup' => false, + 'restore' => false, + ); + +$opts = $ret[0]; +$args = $ret[1]; +if (sizeof($opts) > 0) { + foreach ($opts as $o) { + switch ($o[0]) { + case 'a': + $what['all'] = true; + break; + case 'b': + $what['backup'] = true; + break; + case 'r': + $what['restore'] = true; + break; + case 'v': + case '--version': + $what['version'] = $o[1]; + break; + case 'c': + case '--conf': + $what['conf'] = $o[1]; + break; + case '--app': + $what['app'] = $o[1]; + break; + case 'd': + $debug = true; + break; + case '--search-path': + $search_path = trim($o[1]); + break; + case '--include-path': + set_include_path(get_include_path().PATH_SEPARATOR.trim($o[1])); + break; + case 'u': + $what['dry_run'] = true; + break; + case 'x': + $what['un-install'] = true; + break; + case 'i': + $what['install'] = true; + break; + } + } +} else { + echo 'Error: Missing what to do.'."\n"; + usage(); + die(); +} + +// control the arguments. +if (('' == $what['conf'] or !file_exists($what['conf'])) + or ($what['all'] == false and $what['app'] == '')) { + echo 'Error: Missing what to do or config file.'."\n"; + usage(); + die(); +} +if ($what['all'] and $what['version'] !== null) { + echo 'Error: -a and -v --version cannot be used together.'."\n"; + echo ' Run the migration to a given version indenpendtly'."\n"; + echo ' for each application.'."\n"; + usage(); + die(); +} + +require 'Pluf.php'; +Pluf::start($what['conf']); +if (PHP_SAPI != 'cli' and Pluf::f('migrate_allow_web', false)) { + echo('Error: This script can only be run from the command line.'."\n"); + exit(); +} + +debug('PHP include path: '.get_include_path()); + +if ($what['un-install']) { + $apps = array(); + if ($what['all']) { + $apps = Pluf::f('installed_apps'); + } else { + $apps = array($what['app']); + } + echo 'Applications to uninstall: '.implode(', ', $apps)."\n"; + echo 'Please confirm that you want to uninstall by typing "yes": '; + $line = trim(fgets(STDIN)); // reads one line from STDIN + if ($line != 'yes') { + echo 'Abort...'."\n"; + die(); + } +} + +if (!is_null($search_path)) { + $db =& Pluf::db(); + $db->setSearchPath($search_path); + debug('Set search path to: '.$search_path); +} +$app = null; // Migrate all the applications. +$app_disp = 'all the apps'; +$v_disp = 'latest'; +if (!is_null($what['version'])) { + $v_disp = $what['version']; +} +if ($what['app']) { + $app = trim($what['app']); + $app_disp = $app; +} +$m = new Pluf_Migration($app); +if ($debug) { + $m->display = true; +} +$m->dry_run = $what['dry_run']; + +if ($what['install']) { + debug('Install '.$app_disp); + $m->install(); +} elseif ($what['un-install']) { + debug('Uninstall '.$app_disp); + $m->unInstall(); +} elseif ($what['backup']) { + debug('Backup '.$app_disp); + if (!isset($args[1])) $args[1] = null; + $m->backup($args[0], $args[1]); +} elseif ($what['restore']) { + debug('Restore '.$app_disp); + $m->restore($args[0], $args[1]); +} else { + debug('Migrate '.$app.' to version '.$v_disp); + $m->migrate($what['version']); +} + + + diff --git a/pluf/src/packager.ignore b/pluf/src/packager.ignore new file mode 100644 index 0000000..3ae4aed --- /dev/null +++ b/pluf/src/packager.ignore @@ -0,0 +1,6 @@ +Pluf.pkg.php +Sparkline.php +Sparkline/ +migrate.php +packager.php +Pluf/Tests/ diff --git a/pluf/src/packager.php b/pluf/src/packager.php new file mode 100644 index 0000000..5cfe73e --- /dev/null +++ b/pluf/src/packager.php @@ -0,0 +1,92 @@ +getPathname(), $p)) { + $skip = true; + break; + } + } + if ($skip) continue; + if ($file->isDir()) { + echo 'Get files in: '.$file->getPathname()."\n"; + } else { + $pathinfo = pathinfo($file->getPathname()); + if ($pathinfo['extension'] == 'php') { + $files[] = $file->getPathname(); + $size += $file->getSize(); + } + } +} +sort($files); +foreach ($files as $file) { + echo '.'; + $return = 0; + $tmp_out = array(); + exec('php -w '.escapeshellarg($file), $tmp_out, $return); + if ($return != 0) { + die('error'); + } + if ($tmp_out[0] == '') { + echo('>> '.$file."\n"); + } + $output = array_merge($output, $tmp_out); +} +echo "\n"; +echo 'Compiled files: '.count($files)."\n"; +file_put_contents($output_file, ''); +echo('Final size: '.(int)(100*filesize($output_file)/$size).'%'."\n"); +?> \ No newline at end of file diff --git a/pluf/src/testrunner.php b/pluf/src/testrunner.php new file mode 100644 index 0000000..c84eed9 --- /dev/null +++ b/pluf/src/testrunner.php @@ -0,0 +1,139 @@ +valid()) { + if ($file->isDir() && !$file->isDot()) { + $res[] = $file->getPathName(); + } + $file->next(); + } + return $res; +} + +function getTestFiles($dir='') +{ + $file = new DirectoryIterator($dir); + $res = array(); + while ($file->valid()) { + if ($file->isFile() && substr($file->getPathName(), -4) == '.php') { + $class = str_replace(DIRECTORY_SEPARATOR, '_', substr($file->getPathName(), 0, -4)); + $res[] = array($file->getPathName(), $class); + } + $file->next(); + } + return $res; +} +if (PHP_SAPI == 'cli') { + // Get the application and then the configuration file + if ($argc < 2) { + usage($argv[0]); + exit(1); + } + $app = $argv[1]; + if ($argc >= 3) { + $config = $argv[2]; + } else { + $config = $app.'/conf/'.strtolower($app).'.test.php'; + } +} else { + echo('Error: This script can only be run from the command line.'."\n"); + exit(1); +} +echo(sprintf('Application: %s ', $app)); +if (!file_exists($config)) { + echo(sprintf("\n".'Error, the config file does not exists: %s'."\n", $config)); + exit(1); +} else { + echo(sprintf('(%s)'."\n", $config)); +} +define('IN_UNIT_TESTS', true); +require 'Pluf.php'; +Pluf::start($config); + +$simple_test = Pluf::f('simple_test_path', false); +if (false == $simple_test) { + e('Error, the path to the simple test framework is not defined.'); + e('Download simple test from:'); + e(' http://simpletest.sourceforge.net/'); + e('Extract the archive on your system and set the "simple_test_path"'); + e('configuration variable in your configuration file.'); + e('For example: $cfg[\'simple_test_path\'] = \'/home/you/simpletest\'; '); + exit(1); +} +$testfolder = $app.'/Tests/'; +if (!file_exists($testfolder)) { + e(sprintf('The test folder does not exists: %s.', $app.'/Tests/')); + exit(1); +} + +define('SIMPLE_TEST', $simple_test.'/'); +require_once(SIMPLE_TEST.'unit_tester.php'); +require_once(SIMPLE_TEST.'reporter.php'); + +$files = getTestFiles($testfolder); +$dirs = getTestDirs($testfolder); +foreach ($dirs as $dir) { + foreach (getTestFiles($dir) as $test) { + $files[] = $test; + } +} +$test = &new GroupTest(sprintf('All tests for application %s.', $app)); +foreach ($files as $t) { + if (!function_exists('apc_store') && 'Pluf_Tests_Cache_Apc' === $t[1]) { + continue; + } + $test->addTestCase(new $t[1]()); +} +$reporter = new TextReporter(); +$mig = new Pluf_Migration(null); +$mig->display = false; +$mig->install(); +// If available, load an initialisation file. +if (file_exists($app.'/Tests/init.json')) { + $created = Pluf_Test_Fixture::loadFile($app.'/Tests/init.json'); +} else { + $created = array(); +} +$test->run($reporter); +$mig->unInstall(); \ No newline at end of file