Merge branch '0.9.x' of gitorious.org:statusnet/mainline into 1.0.x

This commit is contained in:
Brion Vibber 2010-06-11 12:09:55 -07:00
commit 004200f958
32 changed files with 2174 additions and 377 deletions

View File

@ -232,7 +232,8 @@ class ApiDirectMessageAction extends ApiAuthAction
function showXmlDirectMessages()
{
$this->initDocument('xml');
$this->elementStart('direct-messages', array('type' => 'array'));
$this->elementStart('direct-messages', array('type' => 'array',
'xmlns:statusnet' => 'http://status.net/schema/api/1/'));
foreach ($this->messages as $m) {
$dm_array = $this->directMessageArray($m);

View File

@ -100,32 +100,43 @@ class ApiStatusesDestroyAction extends ApiAuthAction
parent::handle($args);
if (!in_array($this->format, array('xml', 'json'))) {
$this->clientError(_('API method not found.'), $code = 404);
return;
$this->clientError(
_('API method not found.'),
404
);
return;
}
if (!in_array($_SERVER['REQUEST_METHOD'], array('POST', 'DELETE'))) {
$this->clientError(_('This method requires a POST or DELETE.'),
400, $this->format);
return;
}
if (!in_array($_SERVER['REQUEST_METHOD'], array('POST', 'DELETE'))) {
$this->clientError(
_('This method requires a POST or DELETE.'),
400,
$this->format
);
return;
}
if (empty($this->notice)) {
$this->clientError(_('No status found with that ID.'),
404, $this->format);
return;
}
if (empty($this->notice)) {
$this->clientError(
_('No status found with that ID.'),
404, $this->format
);
return;
}
if ($this->user->id == $this->notice->profile_id) {
$replies = new Reply;
$replies->get('notice_id', $this->notice_id);
$replies->delete();
$this->notice->delete();
$this->showNotice();
} else {
$this->clientError(_('You may not delete another user\'s status.'),
403, $this->format);
}
if ($this->user->id == $this->notice->profile_id) {
$replies = new Reply;
$replies->get('notice_id', $this->notice_id);
$replies->delete();
$this->notice->delete();
$this->showNotice();
} else {
$this->clientError(
_('You may not delete another user\'s status.'),
403,
$this->format
);
}
}
/**

View File

@ -113,7 +113,7 @@ class ApiUserShowAction extends ApiPrivateAuthAction
if ($this->format == 'xml') {
$this->initDocument('xml');
$this->showTwitterXmlUser($twitter_user);
$this->showTwitterXmlUser($twitter_user, 'user', true);
$this->endDocument('xml');
} elseif ($this->format == 'json') {
$this->initDocument('json');

View File

@ -126,9 +126,19 @@ class DesignadminpanelAction extends AdminPanelAction
return;
}
// check for an image upload
// check for file uploads
$bgimage = $this->saveBackgroundImage();
$customTheme = $this->saveCustomTheme();
$oldtheme = common_config('site', 'theme');
if ($customTheme) {
// This feels pretty hacky :D
$this->args['theme'] = $customTheme;
$themeChanged = true;
} else {
$themeChanged = ($this->trimmed('theme') != $oldtheme);
}
static $settings = array('theme', 'logo');
@ -140,15 +150,13 @@ class DesignadminpanelAction extends AdminPanelAction
$this->validate($values);
$oldtheme = common_config('site', 'theme');
$config = new Config();
$config->query('BEGIN');
// Only update colors if the theme has not changed.
if ($oldtheme == $values['theme']) {
if (!$themeChanged) {
$bgcolor = new WebColor($this->trimmed('design_background'));
$ccolor = new WebColor($this->trimmed('design_content'));
@ -190,6 +198,13 @@ class DesignadminpanelAction extends AdminPanelAction
Config::save('design', 'backgroundimage', $bgimage);
}
if (common_config('custom_css', 'enabled')) {
$css = $this->arg('css');
if ($css != common_config('custom_css', 'css')) {
Config::save('custom_css', 'css', $css);
}
}
$config->query('COMMIT');
}
@ -263,6 +278,33 @@ class DesignadminpanelAction extends AdminPanelAction
}
}
/**
* Save the custom theme if the user uploaded one.
*
* @return mixed custom theme name, if succesful, or null if no theme upload.
* @throws ClientException for invalid theme archives
* @throws ServerException if trouble saving the theme files
*/
function saveCustomTheme()
{
if (common_config('theme_upload', 'enabled') &&
$_FILES['design_upload_theme']['error'] == UPLOAD_ERR_OK) {
$upload = ThemeUploader::fromUpload('design_upload_theme');
$basedir = common_config('local', 'dir');
if (empty($basedir)) {
$basedir = INSTALLDIR . '/local';
}
$name = 'custom'; // @todo allow multiples, custom naming?
$outdir = $basedir . '/theme/' . $name;
$upload->extract($outdir);
return $name;
} else {
return null;
}
}
/**
* Attempt to validate setting values
*
@ -371,7 +413,15 @@ class DesignAdminPanelForm extends AdminForm
function formData()
{
$this->showLogo();
$this->showTheme();
$this->showBackground();
$this->showColors();
$this->showAdvanced();
}
function showLogo()
{
$this->out->elementStart('fieldset', array('id' => 'settings_design_logo'));
$this->out->element('legend', null, _('Change logo'));
@ -384,6 +434,11 @@ class DesignAdminPanelForm extends AdminForm
$this->out->elementEnd('ul');
$this->out->elementEnd('fieldset');
}
function showTheme()
{
$this->out->elementStart('fieldset', array('id' => 'settings_design_theme'));
$this->out->element('legend', null, _('Change theme'));
@ -407,10 +462,23 @@ class DesignAdminPanelForm extends AdminForm
false, $this->value('theme'));
$this->unli();
if (common_config('theme_upload', 'enabled')) {
$this->li();
$this->out->element('label', array('for' => 'design_upload_theme'), _('Custom theme'));
$this->out->element('input', array('id' => 'design_upload_theme',
'name' => 'design_upload_theme',
'type' => 'file'));
$this->out->element('p', 'form_guide', _('You can upload a custom StatusNet theme as a .ZIP archive.'));
$this->unli();
}
$this->out->elementEnd('ul');
$this->out->elementEnd('fieldset');
}
function showBackground()
{
$design = $this->out->design;
$this->out->elementStart('fieldset', array('id' =>
@ -486,6 +554,11 @@ class DesignAdminPanelForm extends AdminForm
$this->out->elementEnd('ul');
$this->out->elementEnd('fieldset');
}
function showColors()
{
$design = $this->out->design;
$this->out->elementStart('fieldset', array('id' => 'settings_design_color'));
$this->out->element('legend', null, _('Change colours'));
@ -493,6 +566,7 @@ class DesignAdminPanelForm extends AdminForm
$this->out->elementStart('ul', 'form_data');
try {
// @fixme avoid loop unrolling in non-performance-critical contexts like this
$bgcolor = new WebColor($design->backgroundcolor);
@ -560,6 +634,7 @@ class DesignAdminPanelForm extends AdminForm
$this->unli();
} catch (WebColorException $e) {
// @fixme normalize them individually!
common_log(LOG_ERR, 'Bad color values in site design: ' .
$e->getMessage());
}
@ -569,6 +644,27 @@ class DesignAdminPanelForm extends AdminForm
$this->out->elementEnd('ul');
}
function showAdvanced()
{
if (common_config('custom_css', 'enabled')) {
$this->out->elementStart('fieldset', array('id' => 'settings_design_advanced'));
$this->out->element('legend', null, _('Advanced'));
$this->out->elementStart('ul', 'form_data');
$this->li();
$this->out->element('label', array('for' => 'css'), _('Custom CSS'));
$this->out->element('textarea', array('name' => 'css',
'id' => 'css',
'cols' => '50',
'rows' => '10'),
strval(common_config('custom_css', 'css')));
$this->unli();
$this->out->elementEnd('fieldset');
$this->out->elementEnd('ul');
}
}
/**
* Action elements
*

View File

@ -154,7 +154,9 @@ class FoafAction extends Action
}
$person = $this->showMicrobloggingAccount($this->profile,
common_root_url(), $this->user->uri, false);
common_root_url(), $this->user->uri,
/*$fetchSubscriptions*/true,
/*$isSubscriber*/false);
// Get people who subscribe to user
@ -209,7 +211,8 @@ class FoafAction extends Action
$this->showMicrobloggingAccount($profile,
($local == 'local') ? common_root_url() : null,
$uri,
true);
/*$fetchSubscriptions*/false,
/*$isSubscriber*/($type == LISTENER || $type == BOTH));
if ($foaf_url) {
$this->element('rdfs:seeAlso', array('rdf:resource' => $foaf_url));
}
@ -234,7 +237,21 @@ class FoafAction extends Action
$this->elementEnd('PersonalProfileDocument');
}
function showMicrobloggingAccount($profile, $service=null, $useruri=null, $isSubscriber=false)
/**
* Output FOAF <account> bit for the given profile.
*
* @param Profile $profile
* @param mixed $service Root URL of this StatusNet instance for a local
* user, otherwise null.
* @param mixed $useruri URI string for the referenced profile..
* @param boolean $fetchSubscriptions Should we load and list all their subscriptions?
* @param boolean $isSubscriber if not fetching subs, we can still mark the user as following the current page.
*
* @return array if $fetchSubscribers is set, return a list of info on those
* subscriptions.
*/
function showMicrobloggingAccount($profile, $service=null, $useruri=null, $fetchSubscriptions=false, $isSubscriber=false)
{
$attr = array();
if ($useruri) {
@ -256,9 +273,7 @@ class FoafAction extends Action
$person = array();
if ($isSubscriber) {
$this->element('sioc:follows', array('rdf:resource'=>$this->user->uri . '#acct'));
} else {
if ($fetchSubscriptions) {
// Get people user is subscribed to
$sub = new Subscription();
$sub->subscriber = $profile->id;
@ -283,6 +298,9 @@ class FoafAction extends Action
}
unset($sub);
} else if ($isSubscriber) {
// Just declare that they follow the user whose FOAF we're showing.
$this->element('sioc:follows', array('rdf:resource' => $this->user->uri . '#acct'));
}
$this->elementEnd('OnlineAccount');

View File

@ -128,12 +128,13 @@ class Memcached_DataObject extends Safe_DataObject
}
static function cacheKey($cls, $k, $v) {
if (is_object($cls) || is_object($k) || is_object($v)) {
if (is_object($cls) || is_object($k) || (is_object($v) && !($v instanceof DB_DataObject_Cast))) {
$e = new Exception();
common_log(LOG_ERR, __METHOD__ . ' object in param: ' .
str_replace("\n", " ", $e->getTraceAsString()));
}
return common_cache_key(strtolower($cls).':'.$k.':'.$v);
$vstr = self::valueString($v);
return common_cache_key(strtolower($cls).':'.$k.':'.$vstr);
}
static function getcached($cls, $k, $v) {
@ -229,10 +230,10 @@ class Memcached_DataObject extends Safe_DataObject
if (empty($this->$key)) {
continue;
}
$ckeys[] = $this->cacheKey($this->tableName(), $key, $this->$key);
$ckeys[] = $this->cacheKey($this->tableName(), $key, self::valueString($this->$key));
} else if ($type == 'K' || $type == 'N') {
$pkey[] = $key;
$pval[] = $this->$key;
$pval[] = self::valueString($this->$key);
} else {
throw new Exception("Unknown key type $key => $type for " . $this->tableName());
}
@ -604,5 +605,30 @@ class Memcached_DataObject extends Safe_DataObject
return $c->set($cacheKey, $value);
}
static function valueString($v)
{
$vstr = null;
if (is_object($v) && $v instanceof DB_DataObject_Cast) {
switch ($v->type) {
case 'date':
$vstr = $v->year . '-' . $v->month . '-' . $v->day;
break;
case 'blob':
case 'string':
case 'sql':
case 'datetime':
case 'time':
throw new ServerException("Unhandled DB_DataObject_Cast type passed as cacheKey value: '$v->type'");
break;
default:
throw new ServerException("Unknown DB_DataObject_Cast type passed as cacheKey value: '$v->type'");
break;
}
} else {
$vstr = strval($v);
}
return $vstr;
}
}

View File

@ -1254,6 +1254,8 @@ class Notice extends Memcached_DataObject
if (!empty($cur)) {
$noticeInfoAttr['favorite'] = ($cur->hasFave($this)) ? "true" : "false";
$profile = $cur->getProfile();
$noticeInfoAttr['repeated'] = ($profile->hasRepeated($this->id)) ? "true" : "false";
}
if (!empty($this->repeat_of)) {

View File

@ -18,6 +18,7 @@ VALUES
('Facebook','Facebook','http://apps.facebook.com/identica/', now()),
('feed2omb','feed2omb','http://projects.ciarang.com/p/feed2omb/', now()),
('get2gnow', 'get2gnow', 'http://uberchicgeekchick.com/?projects=get2gnow', now()),
('gNewBook', 'gNewBook', 'http://www.gnewbook.org/', now()),
('gravity', 'Gravity', 'http://mobileways.de/gravity', now()),
('Gwibber','Gwibber','http://launchpad.net/gwibber', now()),
('HelloTxt','HelloTxt','http://hellotxt.com/', now()),

View File

@ -235,6 +235,16 @@ class Action extends HTMLOutputter // lawsuit
Event::handle('EndShowDesign', array($this));
}
Event::handle('EndShowStyles', array($this));
if (common_config('custom_css', 'enabled')) {
$css = common_config('custom_css', 'css');
if (Event::handle('StartShowCustomCss', array($this, &$css))) {
if (trim($css) != '') {
$this->style($css);
}
Event::handle('EndShowCustomCss', array($this));
}
}
}
}

View File

@ -284,9 +284,10 @@ class AdminPanelAction extends Action
$this->clientError(_("Unable to delete design setting."));
return null;
}
return $result;
}
return $result;
return null;
}
function canAdmin($name)

View File

@ -297,6 +297,10 @@ class ApiAction extends Action
}
}
// StatusNet-specific
$twitter_user['statusnet:profile_url'] = $profile->profileurl;
return $twitter_user;
}
@ -398,6 +402,10 @@ class ApiAction extends Action
$twitter_status['user'] = $twitter_user;
}
// StatusNet-specific
$twitter_status['statusnet:html'] = $notice->rendered;
return $twitter_status;
}
@ -565,9 +573,13 @@ class ApiAction extends Action
}
}
function showTwitterXmlStatus($twitter_status, $tag='status')
function showTwitterXmlStatus($twitter_status, $tag='status', $namespaces=false)
{
$this->elementStart($tag);
$attrs = array();
if ($namespaces) {
$attrs['xmlns:statusnet'] = 'http://status.net/schema/api/1/';
}
$this->elementStart($tag, $attrs);
foreach($twitter_status as $element => $value) {
switch ($element) {
case 'user':
@ -601,9 +613,13 @@ class ApiAction extends Action
$this->elementEnd('group');
}
function showTwitterXmlUser($twitter_user, $role='user')
function showTwitterXmlUser($twitter_user, $role='user', $namespaces=false)
{
$this->elementStart($role);
$attrs = array();
if ($namespaces) {
$attrs['xmlns:statusnet'] = 'http://status.net/schema/api/1/';
}
$this->elementStart($role, $attrs);
foreach($twitter_user as $element => $value) {
if ($element == 'status') {
$this->showTwitterXmlStatus($twitter_user['status']);
@ -685,7 +701,7 @@ class ApiAction extends Action
{
$this->initDocument('xml');
$twitter_status = $this->twitterStatusArray($notice);
$this->showTwitterXmlStatus($twitter_status);
$this->showTwitterXmlStatus($twitter_status, 'status', true);
$this->endDocument('xml');
}
@ -701,7 +717,8 @@ class ApiAction extends Action
{
$this->initDocument('xml');
$this->elementStart('statuses', array('type' => 'array'));
$this->elementStart('statuses', array('type' => 'array',
'xmlns:statusnet' => 'http://status.net/schema/api/1/'));
if (is_array($notice)) {
foreach ($notice as $n) {
@ -868,9 +885,13 @@ class ApiAction extends Action
$this->elementEnd('entry');
}
function showXmlDirectMessage($dm)
function showXmlDirectMessage($dm, $namespaces=false)
{
$this->elementStart('direct_message');
$attrs = array();
if ($namespaces) {
$attrs['xmlns:statusnet'] = 'http://status.net/schema/api/1/';
}
$this->elementStart('direct_message', $attrs);
foreach($dm as $element => $value) {
switch ($element) {
case 'sender':
@ -947,7 +968,7 @@ class ApiAction extends Action
{
$this->initDocument('xml');
$dmsg = $this->directMessageArray($message);
$this->showXmlDirectMessage($dmsg);
$this->showXmlDirectMessage($dmsg, true);
$this->endDocument('xml');
}
@ -1064,7 +1085,8 @@ class ApiAction extends Action
{
$this->initDocument('xml');
$this->elementStart('users', array('type' => 'array'));
$this->elementStart('users', array('type' => 'array',
'xmlns:statusnet' => 'http://status.net/schema/api/1/'));
if (is_array($user)) {
foreach ($user as $u) {

View File

@ -141,10 +141,17 @@ $default =
'dir' => null,
'path'=> null,
'ssl' => null),
'theme_upload' =>
array('enabled' => extension_loaded('zip')),
'javascript' =>
array('server' => null,
'path'=> null,
'ssl' => null),
'local' => // To override path/server for themes in 'local' dir (not currently applied to local plugins)
array('server' => null,
'dir' => null,
'path' => null,
'ssl' => null),
'throttle' =>
array('enabled' => false, // whether to throttle edits; false by default
'count' => 20, // number of allowed messages in timespan
@ -260,6 +267,9 @@ $default =
'linkcolor' => null,
'backgroundimage' => null,
'disposition' => null),
'custom_css' =>
array('enabled' => true,
'css' => ''),
'notice' =>
array('contentlimit' => null),
'message' =>

View File

@ -82,9 +82,12 @@ abstract class Installer
{
$pass = true;
if (file_exists(INSTALLDIR.'/config.php')) {
$this->warning('Config file "config.php" already exists.');
$pass = false;
$config = INSTALLDIR.'/config.php';
if (file_exists($config)) {
if (!is_writable($config) || filesize($config) > 0) {
$this->warning('Config file "config.php" already exists.');
$pass = false;
}
}
if (version_compare(PHP_VERSION, '5.2.3', '<')) {

View File

@ -540,7 +540,7 @@ class Router
$m->connect('api/favorites/:id.:format',
array('action' => 'ApiTimelineFavorites',
'id' => '[a-zA-Z0-9]+',
'format' => '(xmljson|rss|atom)'));
'format' => '(xml|json|rss|atom)'));
$m->connect('api/favorites/create/:id.:format',
array('action' => 'ApiFavoriteCreate',
@ -597,7 +597,7 @@ class Router
$m->connect('api/statusnet/groups/timeline/:id.:format',
array('action' => 'ApiTimelineGroup',
'id' => '[a-zA-Z0-9]+',
'format' => '(xmljson|rss|atom)'));
'format' => '(xml|json|rss|atom)'));
$m->connect('api/statusnet/groups/show.:format',
array('action' => 'ApiGroupShow',
@ -664,7 +664,7 @@ class Router
// Tags
$m->connect('api/statusnet/tags/timeline/:tag.:format',
array('action' => 'ApiTimelineTag',
'format' => '(xmljson|rss|atom)'));
'format' => '(xml|json|rss|atom)'));
// media related
$m->connect(

View File

@ -39,6 +39,9 @@ if (!defined('STATUSNET') && !defined('LACONICA')) {
* in them. They're found in either local/theme (for locally-installed themes)
* or theme/ subdir of installation dir.
*
* Note that the 'local' directory can be overridden as $config['local']['path']
* and $config['local']['dir'] etc.
*
* This used to be a couple of functions, but for various reasons it's nice
* to have a class instead.
*
@ -76,7 +79,7 @@ class Theme
if (file_exists($fulldir) && is_dir($fulldir)) {
$this->dir = $fulldir;
$this->path = common_path('local/theme/'.$name.'/');
$this->path = $this->relativeThemePath('local', 'local', 'theme/' . $name);
return;
}
@ -89,44 +92,65 @@ class Theme
if (file_exists($fulldir) && is_dir($fulldir)) {
$this->dir = $fulldir;
$path = common_config('theme', 'path');
if (empty($path)) {
$path = common_config('site', 'path') . '/theme/';
}
if ($path[strlen($path)-1] != '/') {
$path .= '/';
}
if ($path[0] != '/') {
$path = '/'.$path;
}
$server = common_config('theme', 'server');
if (empty($server)) {
$server = common_config('site', 'server');
}
$ssl = common_config('theme', 'ssl');
if (is_null($ssl)) { // null -> guess
if (common_config('site', 'ssl') == 'always' &&
!common_config('theme', 'server')) {
$ssl = true;
} else {
$ssl = false;
}
}
$protocol = ($ssl) ? 'https' : 'http';
$this->path = $protocol . '://'.$server.$path.$name;
$this->path = $this->relativeThemePath('theme', 'theme', $name);
}
}
/**
* Build a full URL to the given theme's base directory, possibly
* using an offsite theme server path.
*
* @param string $group configuration section name to pull paths from
* @param string $fallbackSubdir default subdirectory under INSTALLDIR
* @param string $name theme name
*
* @return string URL
*
* @todo consolidate code with that for other customizable paths
*/
protected function relativeThemePath($group, $fallbackSubdir, $name)
{
$path = common_config($group, 'path');
if (empty($path)) {
$path = common_config('site', 'path') . '/';
if ($fallbackSubdir) {
$path .= $fallbackSubdir . '/';
}
}
if ($path[strlen($path)-1] != '/') {
$path .= '/';
}
if ($path[0] != '/') {
$path = '/'.$path;
}
$server = common_config($group, 'server');
if (empty($server)) {
$server = common_config('site', 'server');
}
$ssl = common_config($group, 'ssl');
if (is_null($ssl)) { // null -> guess
if (common_config('site', 'ssl') == 'always' &&
!common_config($group, 'server')) {
$ssl = true;
} else {
$ssl = false;
}
}
$protocol = ($ssl) ? 'https' : 'http';
$path = $protocol . '://'.$server.$path.$name;
return $path;
}
/**
* Gets the full local filename of a file in this theme.
*
@ -236,7 +260,13 @@ class Theme
protected static function localRoot()
{
return INSTALLDIR.'/local/theme';
$basedir = common_config('local', 'dir');
if (empty($basedir)) {
$basedir = INSTALLDIR . '/local';
}
return $basedir . '/theme';
}
/**

311
lib/themeuploader.php Normal file
View File

@ -0,0 +1,311 @@
<?php
/**
* StatusNet, the distributed open-source microblogging tool
*
* Utilities for theme files and paths
*
* PHP version 5
*
* LICENCE: This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Paths
* @package StatusNet
* @author Brion Vibber <brion@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET') && !defined('LACONICA')) {
exit(1);
}
/**
* Encapsulation of the validation-and-save process when dealing with
* a user-uploaded StatusNet theme archive...
*
* @todo extract theme metadata from css/display.css
* @todo allow saving multiple themes
*/
class ThemeUploader
{
protected $sourceFile;
protected $isUpload;
private $prevErrorReporting;
public function __construct($filename)
{
if (!class_exists('ZipArchive')) {
throw new Exception(_("This server cannot handle theme uploads without ZIP support."));
}
$this->sourceFile = $filename;
}
public static function fromUpload($name)
{
if (!isset($_FILES[$name]['error'])) {
throw new ServerException(_("Theme upload missing or failed."));
}
if ($_FILES[$name]['error'] != UPLOAD_ERR_OK) {
throw new ServerException(_("Theme upload missing or failed."));
}
return new ThemeUploader($_FILES[$name]['tmp_name']);
}
/**
* @param string $destDir
* @throws Exception on bogus files
*/
public function extract($destDir)
{
$zip = $this->openArchive();
// First pass: validate but don't save anything to disk.
// Any errors will trip an exception.
$this->traverseArchive($zip);
// Second pass: now that we know we're good, actually extract!
$tmpDir = $destDir . '.tmp' . getmypid();
$this->traverseArchive($zip, $tmpDir);
$zip->close();
if (file_exists($destDir)) {
$killDir = $tmpDir . '.old';
$this->quiet();
$ok = rename($destDir, $killDir);
$this->loud();
if (!$ok) {
common_log(LOG_ERR, "Could not move old custom theme from $destDir to $killDir");
throw new ServerException(_("Failed saving theme."));
}
} else {
$killDir = false;
}
$this->quiet();
$ok = rename($tmpDir, $destDir);
$this->loud();
if (!$ok) {
common_log(LOG_ERR, "Could not move saved theme from $tmpDir to $destDir");
throw new ServerException(_("Failed saving theme."));
}
if ($killDir) {
$this->recursiveRmdir($killDir);
}
}
/**
*
*/
protected function traverseArchive($zip, $outdir=false)
{
$sizeLimit = 2 * 1024 * 1024; // 2 megabyte space limit?
$blockSize = 4096; // estimated; any entry probably takes this much space
$totalSize = 0;
$hasMain = false;
$commonBaseDir = false;
for ($i = 0; $i < $zip->numFiles; $i++) {
$data = $zip->statIndex($i);
$name = str_replace('\\', '/', $data['name']);
if (substr($name, -1) == '/') {
// A raw directory... skip!
continue;
}
// Check the directory structure...
$path = pathinfo($name);
$dirs = explode('/', $path['dirname']);
$baseDir = array_shift($dirs);
if ($commonBaseDir === false) {
$commonBaseDir = $baseDir;
} else {
if ($commonBaseDir != $baseDir) {
throw new ClientException(_("Invalid theme: bad directory structure."));
}
}
foreach ($dirs as $dir) {
$this->validateFileOrFolder($dir);
}
// Is this a safe or skippable file?
if ($this->skippable($path['filename'], $path['extension'])) {
// Documentation and such... booooring
continue;
} else {
$this->validateFile($path['filename'], $path['extension']);
}
$fullPath = $dirs;
$fullPath[] = $path['basename'];
$localFile = implode('/', $fullPath);
if ($localFile == 'css/display.css') {
$hasMain = true;
}
$size = $data['size'];
$estSize = $blockSize * max(1, intval(ceil($size / $blockSize)));
$totalSize += $estSize;
if ($totalSize > $sizeLimit) {
$msg = sprintf(_("Uploaded theme is too large; " .
"must be less than %d bytes uncompressed."),
$sizeLimit);
throw new ClientException($msg);
}
if ($outdir) {
$this->extractFile($zip, $data['name'], "$outdir/$localFile");
}
}
if (!$hasMain) {
throw new ClientException(_("Invalid theme archive: " .
"missing file css/display.css"));
}
}
protected function skippable($filename, $ext)
{
$skip = array('txt', 'rtf', 'doc', 'docx', 'odt');
if (strtolower($filename) == 'readme') {
return true;
}
if (in_array(strtolower($ext), $skip)) {
return true;
}
return false;
}
protected function validateFile($filename, $ext)
{
$this->validateFileOrFolder($filename);
$this->validateExtension($ext);
// @fixme validate content
}
protected function validateFileOrFolder($name)
{
if (!preg_match('/^[a-z0-9_-]+$/i', $name)) {
$msg = _("Theme contains invalid file or folder name. " .
"Stick with ASCII letters, digits, underscore, and minus sign.");
throw new ClientException($msg);
}
return true;
}
protected function validateExtension($ext)
{
$allowed = array('css', 'png', 'gif', 'jpg', 'jpeg');
if (!in_array(strtolower($ext), $allowed)) {
$msg = sprintf(_("Theme contains file of type '.%s', " .
"which is not allowed."),
$ext);
throw new ClientException($msg);
}
return true;
}
/**
* @return ZipArchive
*/
protected function openArchive()
{
$zip = new ZipArchive;
$ok = $zip->open($this->sourceFile);
if ($ok !== true) {
common_log(LOG_ERR, "Error opening theme zip archive: " .
"{$this->sourceFile} code: {$ok}");
throw new Exception(_("Error opening theme archive."));
}
return $zip;
}
/**
* @param ZipArchive $zip
* @param string $from original path inside ZIP archive
* @param string $to final destination path in filesystem
*/
protected function extractFile($zip, $from, $to)
{
$dir = dirname($to);
if (!file_exists($dir)) {
$this->quiet();
$ok = mkdir($dir, 0755, true);
$this->loud();
if (!$ok) {
common_log(LOG_ERR, "Failed to mkdir $dir while uploading theme");
throw new ServerException(_("Failed saving theme."));
}
} else if (!is_dir($dir)) {
common_log(LOG_ERR, "Output directory $dir not a directory while uploading theme");
throw new ServerException(_("Failed saving theme."));
}
// ZipArchive::extractTo would be easier, but won't let us alter
// the directory structure.
$in = $zip->getStream($from);
if (!$in) {
common_log(LOG_ERR, "Couldn't open archived file $from while uploading theme");
throw new ServerException(_("Failed saving theme."));
}
$this->quiet();
$out = fopen($to, "wb");
$this->loud();
if (!$out) {
common_log(LOG_ERR, "Couldn't open output file $to while uploading theme");
throw new ServerException(_("Failed saving theme."));
}
while (!feof($in)) {
$buffer = fread($in, 65536);
fwrite($out, $buffer);
}
fclose($in);
fclose($out);
}
private function quiet()
{
$this->prevErrorReporting = error_reporting();
error_reporting($this->prevErrorReporting & ~E_WARNING);
}
private function loud()
{
error_reporting($this->prevErrorReporting);
}
private function recursiveRmdir($dir)
{
$list = dir($dir);
while (($file = $list->read()) !== false) {
if ($file == '.' || $file == '..') {
continue;
}
$full = "$dir/$file";
if (is_dir($full)) {
$this->recursiveRmdir($full);
} else {
unlink($full);
}
}
$list->close();
rmdir($dir);
}
}

View File

@ -16,12 +16,12 @@ msgid ""
msgstr ""
"Project-Id-Version: StatusNet\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-05-25 11:36+0000\n"
"PO-Revision-Date: 2010-06-03 23:01:09+0000\n"
"POT-Creation-Date: 2010-06-10 22:48+0000\n"
"PO-Revision-Date: 2010-06-10 22:49:22+0000\n"
"Language-Team: German\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: MediaWiki 1.17alpha (r67302); Translate extension (2010-05-24)\n"
"X-Generator: MediaWiki 1.17alpha (r67833); Translate extension (2010-06-10)\n"
"X-Translation-Project: translatewiki.net at http://translatewiki.net\n"
"X-Language-Code: de\n"
"X-Message-Group: out-statusnet\n"
@ -92,13 +92,13 @@ msgid "Save"
msgstr "Speichern"
#. TRANS: Server error when page not found (404)
#: actions/all.php:65 actions/public.php:98 actions/replies.php:93
#: actions/all.php:68 actions/public.php:98 actions/replies.php:93
#: actions/showfavorites.php:138 actions/tag.php:52
msgid "No such page."
msgstr "Seite nicht vorhanden"
#: actions/all.php:76 actions/allrss.php:68
#: actions/apiaccountupdatedeliverydevice.php:113
#: actions/all.php:79 actions/allrss.php:68
#: actions/apiaccountupdatedeliverydevice.php:114
#: actions/apiaccountupdateprofile.php:105
#: actions/apiaccountupdateprofilebackgroundimage.php:116
#: actions/apiaccountupdateprofileimage.php:105 actions/apiblockcreate.php:97
@ -122,7 +122,7 @@ msgid "No such user."
msgstr "Unbekannter Benutzer."
#. TRANS: Page title. %1$s is user nickname, %2$d is page number
#: actions/all.php:87
#: actions/all.php:90
#, php-format
msgid "%1$s and friends, page %2$d"
msgstr "%1$s und Freunde, Seite% 2$d"
@ -130,7 +130,7 @@ msgstr "%1$s und Freunde, Seite% 2$d"
#. TRANS: Page title. %1$s is user nickname
#. TRANS: H1 text. %1$s is user nickname
#. TRANS: Message is used as link title. %s is a user nickname.
#: actions/all.php:90 actions/all.php:182 actions/allrss.php:116
#: actions/all.php:93 actions/all.php:185 actions/allrss.php:116
#: actions/apitimelinefriends.php:210 actions/apitimelinehome.php:116
#: lib/personalgroupnav.php:100
#, php-format
@ -138,25 +138,25 @@ msgid "%s and friends"
msgstr "%s und Freunde"
#. TRANS: %1$s is user nickname
#: actions/all.php:104
#: actions/all.php:107
#, php-format
msgid "Feed for friends of %s (RSS 1.0)"
msgstr "Feed der Freunde von %s (RSS 1.0)"
#. TRANS: %1$s is user nickname
#: actions/all.php:113
#: actions/all.php:116
#, php-format
msgid "Feed for friends of %s (RSS 2.0)"
msgstr "Feed der Freunde von %s (RSS 2.0)"
#. TRANS: %1$s is user nickname
#: actions/all.php:122
#: actions/all.php:125
#, php-format
msgid "Feed for friends of %s (Atom)"
msgstr "Feed der Freunde von %s (Atom)"
#. TRANS: %1$s is user nickname
#: actions/all.php:135
#: actions/all.php:138
#, php-format
msgid ""
"This is the timeline for %s and friends but no one has posted anything yet."
@ -164,7 +164,7 @@ msgstr ""
"Dies ist die Zeitleiste für %s und Freunde aber bisher hat niemand etwas "
"gepostet."
#: actions/all.php:140
#: actions/all.php:143
#, php-format
msgid ""
"Try subscribing to more people, [join a group](%%action.groups%%) or post "
@ -174,7 +174,7 @@ msgstr ""
"poste selber etwas."
#. TRANS: %1$s is user nickname, %2$s is user nickname, %2$s is user nickname prefixed with "@"
#: actions/all.php:143
#: actions/all.php:146
#, php-format
msgid ""
"You can try to [nudge %1$s](../%2$s) from his profile or [post something to "
@ -184,7 +184,7 @@ msgstr ""
"posten](%%%%action.newnotice%%%%?status_textarea=%s) um seine Aufmerksamkeit "
"zu erregen."
#: actions/all.php:146 actions/replies.php:210 actions/showstream.php:211
#: actions/all.php:149 actions/replies.php:210 actions/showstream.php:211
#, php-format
msgid ""
"Why not [register an account](%%%%action.register%%%%) and then nudge %s or "
@ -195,7 +195,7 @@ msgstr ""
"erregen?"
#. TRANS: H1 text
#: actions/all.php:179
#: actions/all.php:182
msgid "You and friends"
msgstr "Du und Freunde"
@ -207,8 +207,8 @@ msgstr "Du und Freunde"
msgid "Updates from %1$s and friends on %2$s!"
msgstr "Aktualisierungen von %1$s und Freunden auf %2$s!"
#: actions/apiaccountratelimitstatus.php:70
#: actions/apiaccountupdatedeliverydevice.php:93
#: actions/apiaccountratelimitstatus.php:72
#: actions/apiaccountupdatedeliverydevice.php:94
#: actions/apiaccountupdateprofile.php:97
#: actions/apiaccountupdateprofilebackgroundimage.php:94
#: actions/apiaccountupdateprofilecolors.php:118
@ -232,7 +232,7 @@ msgstr "Aktualisierungen von %1$s und Freunden auf %2$s!"
msgid "API method not found."
msgstr "API-Methode nicht gefunden."
#: actions/apiaccountupdatedeliverydevice.php:85
#: actions/apiaccountupdatedeliverydevice.php:86
#: actions/apiaccountupdateprofile.php:89
#: actions/apiaccountupdateprofilebackgroundimage.php:86
#: actions/apiaccountupdateprofilecolors.php:110
@ -246,7 +246,7 @@ msgstr "API-Methode nicht gefunden."
msgid "This method requires a POST."
msgstr "Diese Methode benötigt ein POST."
#: actions/apiaccountupdatedeliverydevice.php:105
#: actions/apiaccountupdatedeliverydevice.php:106
msgid ""
"You must specify a parameter named 'device' with a value of one of: sms, im, "
"none."
@ -254,7 +254,7 @@ msgstr ""
"Du musst einen Parameter mit Namen 'device' übergeben. Mögliche Werte sind: "
"sms, im, none."
#: actions/apiaccountupdatedeliverydevice.php:132
#: actions/apiaccountupdatedeliverydevice.php:133
msgid "Could not update user."
msgstr "Konnte Benutzerdaten nicht aktualisieren."
@ -641,7 +641,7 @@ msgstr "Zugang zu deinem Konto erlauben oder ablehnen"
msgid "This method requires a POST or DELETE."
msgstr "Diese Methode benötigt ein POST oder DELETE."
#: actions/apistatusesdestroy.php:131
#: actions/apistatusesdestroy.php:126
msgid "You may not delete another user's status."
msgstr "Du kannst den Status eines anderen Benutzers nicht löschen."
@ -6161,6 +6161,9 @@ msgid ""
"If you believe this account is being used abusively, you can block them from "
"your subscribers list and report as spam to site administrators at %s"
msgstr ""
"Wenn du dir sicher bist, das dieses Benutzerkonto missbräuchlich benutzt "
"wurde, kannst du das Benutzerkonto von deiner Liste der Abonnenten sperren "
"und es den Seitenadministratoren unter %s als Spam melden."
#. TRANS: Main body of new-subscriber notification e-mail
#: lib/mail.php:254

View File

@ -15,12 +15,12 @@ msgid ""
msgstr ""
"Project-Id-Version: StatusNet\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-05-25 11:36+0000\n"
"PO-Revision-Date: 2010-06-03 23:01:38+0000\n"
"POT-Creation-Date: 2010-06-10 22:48+0000\n"
"PO-Revision-Date: 2010-06-10 22:49:53+0000\n"
"Language-Team: French\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: MediaWiki 1.17alpha (r67302); Translate extension (2010-05-24)\n"
"X-Generator: MediaWiki 1.17alpha (r67833); Translate extension (2010-06-10)\n"
"X-Translation-Project: translatewiki.net at http://translatewiki.net\n"
"X-Language-Code: fr\n"
"X-Message-Group: out-statusnet\n"
@ -90,13 +90,13 @@ msgid "Save"
msgstr "Enregistrer"
#. TRANS: Server error when page not found (404)
#: actions/all.php:65 actions/public.php:98 actions/replies.php:93
#: actions/all.php:68 actions/public.php:98 actions/replies.php:93
#: actions/showfavorites.php:138 actions/tag.php:52
msgid "No such page."
msgstr "Page non trouvée."
#: actions/all.php:76 actions/allrss.php:68
#: actions/apiaccountupdatedeliverydevice.php:113
#: actions/all.php:79 actions/allrss.php:68
#: actions/apiaccountupdatedeliverydevice.php:114
#: actions/apiaccountupdateprofile.php:105
#: actions/apiaccountupdateprofilebackgroundimage.php:116
#: actions/apiaccountupdateprofileimage.php:105 actions/apiblockcreate.php:97
@ -120,7 +120,7 @@ msgid "No such user."
msgstr "Utilisateur non trouvé."
#. TRANS: Page title. %1$s is user nickname, %2$d is page number
#: actions/all.php:87
#: actions/all.php:90
#, php-format
msgid "%1$s and friends, page %2$d"
msgstr "%1$s et ses amis, page %2$d"
@ -128,7 +128,7 @@ msgstr "%1$s et ses amis, page %2$d"
#. TRANS: Page title. %1$s is user nickname
#. TRANS: H1 text. %1$s is user nickname
#. TRANS: Message is used as link title. %s is a user nickname.
#: actions/all.php:90 actions/all.php:182 actions/allrss.php:116
#: actions/all.php:93 actions/all.php:185 actions/allrss.php:116
#: actions/apitimelinefriends.php:210 actions/apitimelinehome.php:116
#: lib/personalgroupnav.php:100
#, php-format
@ -136,25 +136,25 @@ msgid "%s and friends"
msgstr "%s et ses amis"
#. TRANS: %1$s is user nickname
#: actions/all.php:104
#: actions/all.php:107
#, php-format
msgid "Feed for friends of %s (RSS 1.0)"
msgstr "Flux pour les amis de %s (RSS 1.0)"
#. TRANS: %1$s is user nickname
#: actions/all.php:113
#: actions/all.php:116
#, php-format
msgid "Feed for friends of %s (RSS 2.0)"
msgstr "Flux pour les amis de %s (RSS 2.0)"
#. TRANS: %1$s is user nickname
#: actions/all.php:122
#: actions/all.php:125
#, php-format
msgid "Feed for friends of %s (Atom)"
msgstr "Flux pour les amis de %s (Atom)"
#. TRANS: %1$s is user nickname
#: actions/all.php:135
#: actions/all.php:138
#, php-format
msgid ""
"This is the timeline for %s and friends but no one has posted anything yet."
@ -162,7 +162,7 @@ msgstr ""
"Ceci est le flux pour %s et ses amis mais personne na rien posté pour le "
"moment."
#: actions/all.php:140
#: actions/all.php:143
#, php-format
msgid ""
"Try subscribing to more people, [join a group](%%action.groups%%) or post "
@ -172,7 +172,7 @@ msgstr ""
"(%%action.groups%%) ou de poster quelque chose vous-même."
#. TRANS: %1$s is user nickname, %2$s is user nickname, %2$s is user nickname prefixed with "@"
#: actions/all.php:143
#: actions/all.php:146
#, php-format
msgid ""
"You can try to [nudge %1$s](../%2$s) from his profile or [post something to "
@ -182,7 +182,7 @@ msgstr ""
"profil ou [poster quelque chose à son intention](%%%%action.newnotice%%%%?"
"status_textarea=%3$s)."
#: actions/all.php:146 actions/replies.php:210 actions/showstream.php:211
#: actions/all.php:149 actions/replies.php:210 actions/showstream.php:211
#, php-format
msgid ""
"Why not [register an account](%%%%action.register%%%%) and then nudge %s or "
@ -192,7 +192,7 @@ msgstr ""
"un clin dœil à %s ou poster un avis à son intention."
#. TRANS: H1 text
#: actions/all.php:179
#: actions/all.php:182
msgid "You and friends"
msgstr "Vous et vos amis"
@ -204,8 +204,8 @@ msgstr "Vous et vos amis"
msgid "Updates from %1$s and friends on %2$s!"
msgstr "Statuts de %1$s et ses amis dans %2$s!"
#: actions/apiaccountratelimitstatus.php:70
#: actions/apiaccountupdatedeliverydevice.php:93
#: actions/apiaccountratelimitstatus.php:72
#: actions/apiaccountupdatedeliverydevice.php:94
#: actions/apiaccountupdateprofile.php:97
#: actions/apiaccountupdateprofilebackgroundimage.php:94
#: actions/apiaccountupdateprofilecolors.php:118
@ -229,7 +229,7 @@ msgstr "Statuts de %1$s et ses amis dans %2$s!"
msgid "API method not found."
msgstr "Méthode API non trouvée !"
#: actions/apiaccountupdatedeliverydevice.php:85
#: actions/apiaccountupdatedeliverydevice.php:86
#: actions/apiaccountupdateprofile.php:89
#: actions/apiaccountupdateprofilebackgroundimage.php:86
#: actions/apiaccountupdateprofilecolors.php:110
@ -243,7 +243,7 @@ msgstr "Méthode API non trouvée !"
msgid "This method requires a POST."
msgstr "Ce processus requiert un POST."
#: actions/apiaccountupdatedeliverydevice.php:105
#: actions/apiaccountupdatedeliverydevice.php:106
msgid ""
"You must specify a parameter named 'device' with a value of one of: sms, im, "
"none."
@ -251,7 +251,7 @@ msgstr ""
"Vous devez spécifier un paramètre « device » avec une des valeurs suivantes : "
"sms, im, none."
#: actions/apiaccountupdatedeliverydevice.php:132
#: actions/apiaccountupdatedeliverydevice.php:133
msgid "Could not update user."
msgstr "Impossible de mettre à jour lutilisateur."
@ -643,7 +643,7 @@ msgstr "Autoriser ou refuser laccès à votre compte."
msgid "This method requires a POST or DELETE."
msgstr "Ce processus requiert un POST ou un DELETE."
#: actions/apistatusesdestroy.php:131
#: actions/apistatusesdestroy.php:126
msgid "You may not delete another user's status."
msgstr "Vous ne pouvez pas supprimer le statut dun autre utilisateur."
@ -6188,6 +6188,9 @@ msgid ""
"If you believe this account is being used abusively, you can block them from "
"your subscribers list and report as spam to site administrators at %s"
msgstr ""
"Si vous pensez que ce compte est utilisé à des fins abusives, vous pouvez le "
"bloquer de votre liste d'abonnés et le signaler comme spam aux "
"administrateurs du site, sur %s."
#. TRANS: Main body of new-subscriber notification e-mail
#: lib/mail.php:254

View File

@ -9,12 +9,12 @@ msgid ""
msgstr ""
"Project-Id-Version: StatusNet\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-05-25 11:36+0000\n"
"PO-Revision-Date: 2010-06-03 23:01:55+0000\n"
"POT-Creation-Date: 2010-06-10 22:48+0000\n"
"PO-Revision-Date: 2010-06-10 22:50:14+0000\n"
"Language-Team: Dutch\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: MediaWiki 1.17alpha (r67302); Translate extension (2010-05-24)\n"
"X-Generator: MediaWiki 1.17alpha (r67833); Translate extension (2010-06-10)\n"
"X-Translation-Project: translatewiki.net at http://translatewiki.net\n"
"X-Language-Code: hsb\n"
"X-Message-Group: out-statusnet\n"
@ -40,7 +40,7 @@ msgstr "Registrowanje"
#. TRANS: Checkbox instructions for admin setting "Private"
#: actions/accessadminpanel.php:165
msgid "Prohibit anonymous users (not logged in) from viewing site?"
msgstr ""
msgstr "Anonymnym wužiwarjam (njepřizjewjenym) wobhladowanje sydła zakazć?"
#. TRANS: Checkbox label for prohibiting anonymous users from viewing site.
#: actions/accessadminpanel.php:167
@ -85,13 +85,13 @@ msgid "Save"
msgstr "Składować"
#. TRANS: Server error when page not found (404)
#: actions/all.php:65 actions/public.php:98 actions/replies.php:93
#: actions/all.php:68 actions/public.php:98 actions/replies.php:93
#: actions/showfavorites.php:138 actions/tag.php:52
msgid "No such page."
msgstr "Strona njeeksistuje."
#: actions/all.php:76 actions/allrss.php:68
#: actions/apiaccountupdatedeliverydevice.php:113
#: actions/all.php:79 actions/allrss.php:68
#: actions/apiaccountupdatedeliverydevice.php:114
#: actions/apiaccountupdateprofile.php:105
#: actions/apiaccountupdateprofilebackgroundimage.php:116
#: actions/apiaccountupdateprofileimage.php:105 actions/apiblockcreate.php:97
@ -115,7 +115,7 @@ msgid "No such user."
msgstr "Wužiwar njeeksistuje"
#. TRANS: Page title. %1$s is user nickname, %2$d is page number
#: actions/all.php:87
#: actions/all.php:90
#, php-format
msgid "%1$s and friends, page %2$d"
msgstr "%1$s a přećeljo, strona %2$d"
@ -123,7 +123,7 @@ msgstr "%1$s a přećeljo, strona %2$d"
#. TRANS: Page title. %1$s is user nickname
#. TRANS: H1 text. %1$s is user nickname
#. TRANS: Message is used as link title. %s is a user nickname.
#: actions/all.php:90 actions/all.php:182 actions/allrss.php:116
#: actions/all.php:93 actions/all.php:185 actions/allrss.php:116
#: actions/apitimelinefriends.php:210 actions/apitimelinehome.php:116
#: lib/personalgroupnav.php:100
#, php-format
@ -131,31 +131,31 @@ msgid "%s and friends"
msgstr "%s a přećeljo"
#. TRANS: %1$s is user nickname
#: actions/all.php:104
#: actions/all.php:107
#, php-format
msgid "Feed for friends of %s (RSS 1.0)"
msgstr "Kanal za přećelow wužiwarja %s (RSS 1.0)"
#. TRANS: %1$s is user nickname
#: actions/all.php:113
#: actions/all.php:116
#, php-format
msgid "Feed for friends of %s (RSS 2.0)"
msgstr "Kanal za přećelow wužiwarja %s (RSS 2.0)"
#. TRANS: %1$s is user nickname
#: actions/all.php:122
#: actions/all.php:125
#, php-format
msgid "Feed for friends of %s (Atom)"
msgstr "Kanal za přećelow wužiwarja %s (Atom)"
#. TRANS: %1$s is user nickname
#: actions/all.php:135
#: actions/all.php:138
#, php-format
msgid ""
"This is the timeline for %s and friends but no one has posted anything yet."
msgstr ""
#: actions/all.php:140
#: actions/all.php:143
#, php-format
msgid ""
"Try subscribing to more people, [join a group](%%action.groups%%) or post "
@ -163,14 +163,14 @@ msgid ""
msgstr ""
#. TRANS: %1$s is user nickname, %2$s is user nickname, %2$s is user nickname prefixed with "@"
#: actions/all.php:143
#: actions/all.php:146
#, php-format
msgid ""
"You can try to [nudge %1$s](../%2$s) from his profile or [post something to "
"his or her attention](%%%%action.newnotice%%%%?status_textarea=%3$s)."
msgstr ""
#: actions/all.php:146 actions/replies.php:210 actions/showstream.php:211
#: actions/all.php:149 actions/replies.php:210 actions/showstream.php:211
#, php-format
msgid ""
"Why not [register an account](%%%%action.register%%%%) and then nudge %s or "
@ -178,7 +178,7 @@ msgid ""
msgstr ""
#. TRANS: H1 text
#: actions/all.php:179
#: actions/all.php:182
msgid "You and friends"
msgstr "Ty a přećeljo"
@ -190,8 +190,8 @@ msgstr "Ty a přećeljo"
msgid "Updates from %1$s and friends on %2$s!"
msgstr "Aktualizacije wot %1$s a přećelow na %2$s!"
#: actions/apiaccountratelimitstatus.php:70
#: actions/apiaccountupdatedeliverydevice.php:93
#: actions/apiaccountratelimitstatus.php:72
#: actions/apiaccountupdatedeliverydevice.php:94
#: actions/apiaccountupdateprofile.php:97
#: actions/apiaccountupdateprofilebackgroundimage.php:94
#: actions/apiaccountupdateprofilecolors.php:118
@ -215,7 +215,7 @@ msgstr "Aktualizacije wot %1$s a přećelow na %2$s!"
msgid "API method not found."
msgstr "API-metoda njenamakana."
#: actions/apiaccountupdatedeliverydevice.php:85
#: actions/apiaccountupdatedeliverydevice.php:86
#: actions/apiaccountupdateprofile.php:89
#: actions/apiaccountupdateprofilebackgroundimage.php:86
#: actions/apiaccountupdateprofilecolors.php:110
@ -229,13 +229,13 @@ msgstr "API-metoda njenamakana."
msgid "This method requires a POST."
msgstr "Tuta metoda wužaduje sej POST."
#: actions/apiaccountupdatedeliverydevice.php:105
#: actions/apiaccountupdatedeliverydevice.php:106
msgid ""
"You must specify a parameter named 'device' with a value of one of: sms, im, "
"none."
msgstr ""
#: actions/apiaccountupdatedeliverydevice.php:132
#: actions/apiaccountupdatedeliverydevice.php:133
msgid "Could not update user."
msgstr "Wužiwar njeje so dał aktualizować."
@ -328,6 +328,8 @@ msgstr "Přijimowar njenamakany."
#: actions/apidirectmessagenew.php:142
msgid "Can't send direct messages to users who aren't your friend."
msgstr ""
"Njeje móžno, direktne powěsće wužiwarjam pósłać, kotřiž twoji přećeljo "
"njejsu."
#: actions/apifavoritecreate.php:109 actions/apifavoritedestroy.php:110
#: actions/apistatusesdestroy.php:114
@ -340,7 +342,7 @@ msgstr "Tutón status je hižo faworit."
#: actions/apifavoritecreate.php:131 actions/favor.php:84 lib/command.php:285
msgid "Could not create favorite."
msgstr ""
msgstr "Faworit njeda so wutworić."
#: actions/apifavoritedestroy.php:123
msgid "That status is not a favorite."
@ -348,7 +350,7 @@ msgstr "Tón status faworit njeje."
#: actions/apifavoritedestroy.php:135 actions/disfavor.php:87
msgid "Could not delete favorite."
msgstr ""
msgstr "Faworit njeda so zhašeć."
#: actions/apifriendshipscreate.php:109
msgid "Could not follow user: User not found."
@ -369,7 +371,7 @@ msgstr "Njemóžeš slědowanje swójskich aktiwitow blokować."
#: actions/apifriendshipsexists.php:94
msgid "Two user ids or screen_names must be supplied."
msgstr ""
msgstr "Dwaj wužiwarskej ID abo wužiwarskej mjenje dyrbitej so podać."
#: actions/apifriendshipsshow.php:134
msgid "Could not determine source user."
@ -556,7 +558,7 @@ msgstr ""
#: actions/oauthconnectionssettings.php:147 actions/recoverpassword.php:44
#: actions/smssettings.php:277 lib/designsettings.php:304
msgid "Unexpected form submission."
msgstr ""
msgstr "Njewočakowane wotpósłanje formulara."
#: actions/apioauthauthorize.php:259
msgid "An application would like to connect to your account"
@ -609,7 +611,7 @@ msgstr "Přistup ke kontowym informacijam dowolić abo wotpokazać."
msgid "This method requires a POST or DELETE."
msgstr "Tuta metoda wužaduje sej POST abo DELETE."
#: actions/apistatusesdestroy.php:131
#: actions/apistatusesdestroy.php:126
msgid "You may not delete another user's status."
msgstr "Njemóžeš status druheho wužiwarja zničić."
@ -1510,7 +1512,7 @@ msgstr "Žana adresa za dochadźace e-mejle."
#: actions/emailsettings.php:504 actions/emailsettings.php:528
#: actions/smssettings.php:578 actions/smssettings.php:602
msgid "Couldn't update user record."
msgstr ""
msgstr "Datowa sadźba wužiwarja njeda so aktualizować."
#. TRANS: Message given after successfully removing an incoming e-mail address.
#: actions/emailsettings.php:508 actions/smssettings.php:581
@ -1585,7 +1587,7 @@ msgstr ""
#: actions/featured.php:99
#, php-format
msgid "A selection of some great users on %s"
msgstr ""
msgstr "Wuběr wulkotnych wužiwarjow na %s"
#: actions/file.php:34
msgid "No notice ID."
@ -1649,7 +1651,7 @@ msgstr "Njepłaćiwa róla."
#: actions/grantrole.php:66 actions/revokerole.php:66
msgid "This role is reserved and cannot be set."
msgstr ""
msgstr "Tuta róla je wuměnjena a njeda so stajić."
#: actions/grantrole.php:75
msgid "You cannot grant user roles on this site."
@ -1712,7 +1714,7 @@ msgstr "Tutoho wužiwarja za tutu skupinu blokować"
#: actions/groupblock.php:206
msgid "Database error blocking user from group."
msgstr ""
msgstr "Zmylk datoweje banki blokuje wužiwarja za skupinu."
#: actions/groupbyid.php:74 actions/userbyid.php:70
msgid "No ID."
@ -1763,7 +1765,7 @@ msgstr "Logo zaktualizowane."
#: actions/grouplogo.php:401
msgid "Failed updating logo."
msgstr ""
msgstr "Aktualizowanje loga je so njeporadźiło."
#: actions/groupmembers.php:100 lib/groupnav.php:92
#, php-format
@ -1860,6 +1862,8 @@ msgid ""
"If you can't find the group you're looking for, you can [create it](%%action."
"newgroup%%) yourself."
msgstr ""
"Jeli njemóžeš skupinu namakać, kotruž pytaš, móžeš [ju wutworić] (%%action."
"newgroup%%)."
#: actions/groupsearch.php:85
#, php-format
@ -2152,7 +2156,7 @@ msgstr ""
#: actions/joingroup.php:60
msgid "You must be logged in to join a group."
msgstr ""
msgstr "Dyrbiš přizjewjeny być, zo by do skupiny zastupił."
#: actions/joingroup.php:88 actions/leavegroup.php:88
msgid "No nickname or ID."
@ -2217,6 +2221,8 @@ msgid ""
"For security reasons, please re-enter your user name and password before "
"changing your settings."
msgstr ""
"Prošu zapodaj z přičinow wěstoty swoje wužiwarske mjeno znowa, prjedy hač "
"změniš swoje nastajenja."
#: actions/login.php:292
msgid "Login with your username and password."
@ -2227,6 +2233,7 @@ msgstr "Přizjewjenje z twojim wužiwarskim mjenom a hesłom."
msgid ""
"Don't have a username yet? [Register](%%action.register%%) a new account."
msgstr ""
"Hišće nimaš wužiwarske mjeno? [Zregistruj (%%action.register%%) nowe konto."
#: actions/makeadmin.php:92
msgid "Only an admin can make another user an admin."
@ -2819,7 +2826,7 @@ msgstr "Městno"
#: actions/profilesettings.php:134 actions/register.php:480
msgid "Where you are, like \"City, State (or Region), Country\""
msgstr ""
msgstr "Hdźež sy, na př. \"město, zwjazkowy kraj (abo region) , kraj\""
#: actions/profilesettings.php:138
msgid "Share my current location when posting notices"
@ -2899,7 +2906,7 @@ msgstr "Nastajenja składowane."
#: actions/public.php:83
#, php-format
msgid "Beyond the page limit (%s)."
msgstr ""
msgstr "Limit stronow (%s) překročeny."
#: actions/public.php:92
msgid "Could not retrieve public stream."
@ -3644,12 +3651,12 @@ msgstr ""
#: actions/showmessage.php:108
#, php-format
msgid "Message to %1$s on %2$s"
msgstr ""
msgstr "Powěsć do %1$s na %2$s"
#: actions/showmessage.php:113
#, php-format
msgid "Message from %1$s on %2$s"
msgstr ""
msgstr "Powěsć wot %1$s na %2$s"
#: actions/shownotice.php:90
msgid "Notice deleted."
@ -3773,7 +3780,7 @@ msgstr "Sydłowe mjeno"
#: actions/siteadminpanel.php:225
msgid "The name of your site, like \"Yourcompany Microblog\""
msgstr ""
msgstr "Mjeno twojeho sydła, kaž \"TwojePředewzaće Microblog\""
#: actions/siteadminpanel.php:229
msgid "Brought by"
@ -3805,7 +3812,7 @@ msgstr "Standardne časowe pasmo"
#: actions/siteadminpanel.php:257
msgid "Default timezone for the site; usually UTC."
msgstr ""
msgstr "Standardne časowe pasmo za sydło; zwjetša UTC."
#: actions/siteadminpanel.php:262
msgid "Default language"
@ -3968,7 +3975,7 @@ msgstr ""
#. TRANS: Message given canceling SMS phone number confirmation for the wrong phone number.
#: actions/smssettings.php:413
msgid "That is the wrong confirmation number."
msgstr ""
msgstr "To je wopačne wobkrućenske čisło."
#. TRANS: Message given after successfully canceling SMS phone number confirmation.
#: actions/smssettings.php:427
@ -4074,7 +4081,7 @@ msgstr "Njejsy tón profil abonował."
#: actions/subedit.php:83 classes/Subscription.php:132
msgid "Could not save subscription."
msgstr ""
msgstr "Abonement njeda so składować."
#: actions/subscribe.php:77
msgid "This action only accepts POST requests."
@ -4287,7 +4294,7 @@ msgstr ""
#: actions/useradminpanel.php:165
#, php-format
msgid "Invalid default subscripton: '%1$s' is not user."
msgstr ""
msgstr "Njepłaćiwy standardny abonement: '%1$s' wužiwar njeje."
#. TRANS: Link description in user account settings menu.
#: actions/useradminpanel.php:218 lib/accountsettingsaction.php:111
@ -4369,7 +4376,7 @@ msgstr "Tutón abonement wotpokazać"
#: actions/userauthorization.php:232
msgid "No authorization request!"
msgstr ""
msgstr "Žane awtorizaciske naprašowanje!"
#: actions/userauthorization.php:254
msgid "Subscription authorized"
@ -4416,7 +4423,7 @@ msgstr ""
#: actions/userauthorization.php:345
#, php-format
msgid "Avatar URL %s is not valid."
msgstr ""
msgstr "URL awatara '%s' njeje płaćiwy"
#: actions/userauthorization.php:350
#, php-format
@ -4569,7 +4576,7 @@ msgstr ""
#: classes/Message.php:61
msgid "Could not insert message."
msgstr ""
msgstr "Powěsć njeda so zasunyć."
#: classes/Message.php:71
msgid "Could not update message with new URI."
@ -4650,11 +4657,11 @@ msgstr "Abonoment njeje so dał zničić."
#: classes/User.php:363
#, php-format
msgid "Welcome to %1$s, @%2$s!"
msgstr ""
msgstr "Witaj do %1$s, @%2$s!"
#: classes/User_group.php:480
msgid "Could not create group."
msgstr ""
msgstr "Skupina njeda so wutowrić."
#: classes/User_group.php:489
msgid "Could not set group URI."
@ -4662,7 +4669,7 @@ msgstr "URI skupiny njeda so nastajić."
#: classes/User_group.php:510
msgid "Could not set group membership."
msgstr ""
msgstr "Skupinske čłonstwo njeda so stajić."
#: classes/User_group.php:524
msgid "Could not save local group info."
@ -4671,17 +4678,17 @@ msgstr "Informacije wo lokalnej skupinje njedachu so składować."
#. TRANS: Link title attribute in user account settings menu.
#: lib/accountsettingsaction.php:109
msgid "Change your profile settings"
msgstr ""
msgstr "Twoje profilowe nastajenja změnić"
#. TRANS: Link title attribute in user account settings menu.
#: lib/accountsettingsaction.php:116
msgid "Upload an avatar"
msgstr ""
msgstr "Awatar nahrać"
#. TRANS: Link title attribute in user account settings menu.
#: lib/accountsettingsaction.php:123
msgid "Change your password"
msgstr ""
msgstr "Twoje hesło změnić"
#. TRANS: Link title attribute in user account settings menu.
#: lib/accountsettingsaction.php:130
@ -4985,7 +4992,7 @@ msgstr ""
#. TRANS: Client error message thrown when a user tries to change admin settings but has no access rights.
#: lib/adminpanelaction.php:98
msgid "You cannot make changes to this site."
msgstr ""
msgstr "Njemóžeš tute sydło změnić."
#. TRANS: Client error message throw when a certain panel's settings cannot be changed.
#: lib/adminpanelaction.php:110
@ -4995,12 +5002,12 @@ msgstr "Změny na tutym woknje njejsu dowolene."
#. TRANS: Client error message.
#: lib/adminpanelaction.php:229
msgid "showForm() not implemented."
msgstr ""
msgstr "showForm() njeimplementowany."
#. TRANS: Client error message
#: lib/adminpanelaction.php:259
msgid "saveSettings() not implemented."
msgstr ""
msgstr "saveSettings() njeimplementowany."
#. TRANS: Client error message thrown if design settings could not be deleted in
#. TRANS: the admin panel Design.
@ -5011,7 +5018,7 @@ msgstr ""
#. TRANS: Menu item title/tooltip
#: lib/adminpanelaction.php:349
msgid "Basic site configuration"
msgstr ""
msgstr "Zakładna sydłowa konfiguracija"
#. TRANS: Menu item for site administration
#: lib/adminpanelaction.php:351
@ -5104,12 +5111,12 @@ msgstr "URL žórła"
#. TRANS: Form input field instructions.
#: lib/applicationeditform.php:233
msgid "Organization responsible for this application"
msgstr ""
msgstr "Organizacija, kotraž je za tutu aplikaciju zamołwita"
#. TRANS: Form input field instructions.
#: lib/applicationeditform.php:242
msgid "URL for the homepage of the organization"
msgstr ""
msgstr "URL za startowu stronu organizacije"
#. TRANS: Form input field instructions.
#: lib/applicationeditform.php:251
@ -5134,12 +5141,12 @@ msgstr ""
#. TRANS: Radio button label for access type.
#: lib/applicationeditform.php:320
msgid "Read-only"
msgstr ""
msgstr "Jenož čitajomny"
#. TRANS: Radio button label for access type.
#: lib/applicationeditform.php:339
msgid "Read-write"
msgstr ""
msgstr "Popisujomny"
#. TRANS: Form guide.
#: lib/applicationeditform.php:341
@ -5154,12 +5161,12 @@ msgstr "Přetorhnyć"
#. TRANS: Application access type
#: lib/applicationlist.php:136
msgid "read-write"
msgstr ""
msgstr "popisujomny"
#. TRANS: Application access type
#: lib/applicationlist.php:138
msgid "read-only"
msgstr ""
msgstr "jenož čitajomny"
#. TRANS: Used in application list. %1$s is a modified date, %2$s is access type (read-write or read-only)
#: lib/applicationlist.php:144
@ -5229,18 +5236,18 @@ msgstr "Wužiwar nima poslednju powěsć"
#: lib/command.php:127
#, php-format
msgid "Could not find a user with nickname %s"
msgstr ""
msgstr "Wužiwar z přimjenom %s njeda so namakać"
#. TRANS: Message given getting a non-existing user.
#. TRANS: %s is the nickname of the user that could not be found.
#: lib/command.php:147
#, php-format
msgid "Could not find a local user with nickname %s"
msgstr ""
msgstr "Lokalny wužiwar z přimjenom %s njeda so namakać"
#: lib/command.php:180
msgid "Sorry, this command is not yet implemented."
msgstr ""
msgstr "Tutón přikaz hišće njeje implementowany."
#: lib/command.php:225
msgid "It does not make a lot of sense to nudge yourself!"
@ -5370,7 +5377,7 @@ msgstr ""
#: lib/command.php:620
msgid "Specify the name of the user to subscribe to"
msgstr ""
msgstr "Podaj mjeno wužiwarja, kotrehož chceš abonować"
#: lib/command.php:628
msgid "Can't subscribe to OMB profiles by command."
@ -5379,16 +5386,16 @@ msgstr "OMB-profile njedadźa so přez přikaz abonować."
#: lib/command.php:634
#, php-format
msgid "Subscribed to %s"
msgstr ""
msgstr "%s abonowany"
#: lib/command.php:655 lib/command.php:754
msgid "Specify the name of the user to unsubscribe from"
msgstr ""
msgstr "Podaj mjeno wužiwarja, kotrehož chceš wotskazać"
#: lib/command.php:664
#, php-format
msgid "Unsubscribed from %s"
msgstr ""
msgstr "%s wotskazany"
#: lib/command.php:682 lib/command.php:705
msgid "Command not yet implemented."
@ -5412,7 +5419,7 @@ msgstr ""
#: lib/command.php:723
msgid "Login command is disabled"
msgstr ""
msgstr "Přizjewjenski přikaz je znjemóžnjeny"
#: lib/command.php:734
#, php-format
@ -5426,7 +5433,7 @@ msgstr "%s wotskazany"
#: lib/command.php:778
msgid "You are not subscribed to anyone."
msgstr ""
msgstr "Njejsy nikoho abonował."
#: lib/command.php:780
msgid "You are subscribed to this person:"
@ -5438,7 +5445,7 @@ msgstr[3] "Sy tute wosoby abonował:"
#: lib/command.php:800
msgid "No one is subscribed to you."
msgstr ""
msgstr "Nichtó njeje će abonował."
#: lib/command.php:802
msgid "This person is subscribed to you:"
@ -5508,15 +5515,15 @@ msgstr "Žana konfiguraciska dataja namakana. "
#: lib/common.php:136
msgid "I looked for configuration files in the following places: "
msgstr ""
msgstr "Sym na slědowacych městnach za konfiguraciskimi datajemi pytał: "
#: lib/common.php:138
msgid "You may wish to run the installer to fix this."
msgstr ""
msgstr "Móže być, zo chceš instalaciski program startować, zo by to porjedźił."
#: lib/common.php:139
msgid "Go to the installer."
msgstr ""
msgstr "K instalaciji"
#: lib/connectsettingsaction.php:110
msgid "IM"
@ -5536,7 +5543,7 @@ msgstr "Zwiski"
#: lib/connectsettingsaction.php:121
msgid "Authorized connected applications"
msgstr ""
msgstr "Awtorizowane zwjazane aplikacije"
#: lib/dberroraction.php:60
msgid "Database error"
@ -5611,7 +5618,7 @@ msgstr ""
#: lib/galleryaction.php:143
msgid "Go"
msgstr ""
msgstr "Start"
#: lib/grantroleform.php:91
#, php-format
@ -5635,6 +5642,8 @@ msgstr "Skupinu abo temu w %d znamješkach wopisać"
msgid ""
"Location for the group, if any, like \"City, State (or Region), Country\""
msgstr ""
"Městno za skupinu, jeli eksistuje, na př. \"město, zwjazkowy kraj (abo "
"region), kraj\""
#: lib/groupeditform.php:187
#, php-format
@ -5657,7 +5666,7 @@ msgstr ""
#: lib/groupnav.php:108
#, php-format
msgid "Edit %s group properties"
msgstr ""
msgstr "Kajkosće skupiny %s wobdźěłać"
#: lib/groupnav.php:113
msgid "Logo"
@ -5690,6 +5699,8 @@ msgstr ""
#: lib/htmloutputter.php:104
msgid "This page is not available in a media type you accept"
msgstr ""
"Tuta strona we wot tebje akceptowanym medijowym typje k dispoziciji "
"njesteji."
#: lib/imagefile.php:72
msgid "Unsupported image file format."
@ -5740,7 +5751,7 @@ msgstr "Njeznate žórło postoweho kašćika %d."
#: lib/joinform.php:114
msgid "Join"
msgstr ""
msgstr "Zastupić"
#: lib/leaveform.php:114
msgid "Leave"
@ -5934,6 +5945,9 @@ msgid ""
"\n"
"\t%s"
msgstr ""
"Dospołnu rozmołwu móžes tu čitać:\n"
"\n"
"%s"
#: lib/mail.php:657
#, php-format
@ -5970,7 +5984,7 @@ msgstr ""
#: lib/mailbox.php:89
msgid "Only the user can read their own mailboxes."
msgstr ""
msgstr "Jenož wužiwar móže swoje póstowe kašćiki čitać."
#: lib/mailbox.php:139
msgid ""
@ -5984,7 +5998,7 @@ msgstr "wot"
#: lib/mailhandler.php:37
msgid "Could not parse message."
msgstr ""
msgstr "Powěsć njeda so analyzować."
#: lib/mailhandler.php:42
msgid "Not a registered user."
@ -6006,6 +6020,8 @@ msgstr "Njepodpěrany powěsćowy typ: %s"
#: lib/mediafile.php:98 lib/mediafile.php:123
msgid "There was a database error while saving your file. Please try again."
msgstr ""
"Při składowanju twojeje dataje je zmylk w datowej bance wustupił. Prošu "
"spytaj hišće raz."
#: lib/mediafile.php:142
msgid "The uploaded file exceeds the upload_max_filesize directive in php.ini."
@ -6027,11 +6043,11 @@ msgstr "Temporerny rjadowka faluje."
#: lib/mediafile.php:162
msgid "Failed to write file to disk."
msgstr ""
msgstr "Dataju njeda so na tačel pisać."
#: lib/mediafile.php:165
msgid "File upload stopped by extension."
msgstr ""
msgstr "Datajowe nahraće přez rozšěrjenje zastajene."
#: lib/mediafile.php:179 lib/mediafile.php:216
msgid "File exceeds user's quota."
@ -6039,16 +6055,16 @@ msgstr ""
#: lib/mediafile.php:196 lib/mediafile.php:233
msgid "File could not be moved to destination directory."
msgstr ""
msgstr "Dataja njeda so do ciloweho zapisa přesunyć."
#: lib/mediafile.php:201 lib/mediafile.php:237
msgid "Could not determine file's MIME type."
msgstr ""
msgstr "MIME-typ dataje njeda so zwěsćić."
#: lib/mediafile.php:270
#, php-format
msgid " Try using another %s format."
msgstr ""
msgstr "Spytaj druhi format %s."
#: lib/mediafile.php:275
#, php-format
@ -6174,7 +6190,7 @@ msgstr "Zmylk při zasunjenju awatara"
#: lib/oauthstore.php:306
msgid "Error updating remote profile"
msgstr ""
msgstr "Zmylk při aktualizowanju zdaleneho profila"
#: lib/oauthstore.php:311
msgid "Error inserting remote profile"
@ -6186,7 +6202,7 @@ msgstr "Dwójna zdźělenka"
#: lib/oauthstore.php:490
msgid "Couldn't insert new subscription."
msgstr ""
msgstr "Nowy abonement njeda so zasunyć."
#: lib/personalgroupnav.php:99
msgid "Personal"
@ -6305,7 +6321,7 @@ msgstr "Rólu \"%s\" tutoho wužiwarja wotwołać"
#: lib/router.php:709
msgid "No single user defined for single-user mode."
msgstr ""
msgstr "Žadyn jednotliwy wužiwar za modus jednotliweho wužiwarja definowany."
#: lib/sandboxform.php:67
msgid "Sandbox"
@ -6366,7 +6382,7 @@ msgstr ""
#: lib/subgroupnav.php:83
#, php-format
msgid "People %s subscribes to"
msgstr ""
msgstr "Ludźo, kotrychž %s abonuje"
#: lib/subgroupnav.php:91
#, php-format
@ -6376,7 +6392,7 @@ msgstr "Ludźo, kotřiž su %s abonowali"
#: lib/subgroupnav.php:99
#, php-format
msgid "Groups %s is a member of"
msgstr ""
msgstr "Skupiny, w kotrychž %s je čłon"
#: lib/subgroupnav.php:105
msgid "Invite"
@ -6444,7 +6460,7 @@ msgstr "Wužiwarske akcije"
#: lib/userprofile.php:237
msgid "User deletion in progress..."
msgstr ""
msgstr "Wužiwar so haša..."
#: lib/userprofile.php:263
msgid "Edit profile settings"
@ -6464,7 +6480,7 @@ msgstr "Powěsć"
#: lib/userprofile.php:326
msgid "Moderate"
msgstr ""
msgstr "Moderěrować"
#: lib/userprofile.php:364
msgid "User role"
@ -6478,7 +6494,7 @@ msgstr "Administrator"
#: lib/userprofile.php:367
msgctxt "role"
msgid "Moderator"
msgstr ""
msgstr "Moderator"
#. TRANS: Used in notices to indicate when the notice was made compared to now.
#: lib/util.php:1100

View File

@ -8,12 +8,12 @@ msgid ""
msgstr ""
"Project-Id-Version: StatusNet\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-05-25 11:36+0000\n"
"PO-Revision-Date: 2010-06-03 23:01:59+0000\n"
"POT-Creation-Date: 2010-06-10 22:48+0000\n"
"PO-Revision-Date: 2010-06-10 22:50:20+0000\n"
"Language-Team: Interlingua\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: MediaWiki 1.17alpha (r67302); Translate extension (2010-05-24)\n"
"X-Generator: MediaWiki 1.17alpha (r67833); Translate extension (2010-06-10)\n"
"X-Translation-Project: translatewiki.net at http://translatewiki.net\n"
"X-Language-Code: ia\n"
"X-Message-Group: out-statusnet\n"
@ -83,13 +83,13 @@ msgid "Save"
msgstr "Salveguardar"
#. TRANS: Server error when page not found (404)
#: actions/all.php:65 actions/public.php:98 actions/replies.php:93
#: actions/all.php:68 actions/public.php:98 actions/replies.php:93
#: actions/showfavorites.php:138 actions/tag.php:52
msgid "No such page."
msgstr "Pagina non existe."
#: actions/all.php:76 actions/allrss.php:68
#: actions/apiaccountupdatedeliverydevice.php:113
#: actions/all.php:79 actions/allrss.php:68
#: actions/apiaccountupdatedeliverydevice.php:114
#: actions/apiaccountupdateprofile.php:105
#: actions/apiaccountupdateprofilebackgroundimage.php:116
#: actions/apiaccountupdateprofileimage.php:105 actions/apiblockcreate.php:97
@ -113,7 +113,7 @@ msgid "No such user."
msgstr "Usator non existe."
#. TRANS: Page title. %1$s is user nickname, %2$d is page number
#: actions/all.php:87
#: actions/all.php:90
#, php-format
msgid "%1$s and friends, page %2$d"
msgstr "%1$s e amicos, pagina %2$d"
@ -121,7 +121,7 @@ msgstr "%1$s e amicos, pagina %2$d"
#. TRANS: Page title. %1$s is user nickname
#. TRANS: H1 text. %1$s is user nickname
#. TRANS: Message is used as link title. %s is a user nickname.
#: actions/all.php:90 actions/all.php:182 actions/allrss.php:116
#: actions/all.php:93 actions/all.php:185 actions/allrss.php:116
#: actions/apitimelinefriends.php:210 actions/apitimelinehome.php:116
#: lib/personalgroupnav.php:100
#, php-format
@ -129,25 +129,25 @@ msgid "%s and friends"
msgstr "%s e amicos"
#. TRANS: %1$s is user nickname
#: actions/all.php:104
#: actions/all.php:107
#, php-format
msgid "Feed for friends of %s (RSS 1.0)"
msgstr "Syndication pro le amicos de %s (RSS 1.0)"
#. TRANS: %1$s is user nickname
#: actions/all.php:113
#: actions/all.php:116
#, php-format
msgid "Feed for friends of %s (RSS 2.0)"
msgstr "Syndication pro le amicos de %s (RSS 2.0)"
#. TRANS: %1$s is user nickname
#: actions/all.php:122
#: actions/all.php:125
#, php-format
msgid "Feed for friends of %s (Atom)"
msgstr "Syndication pro le amicos de %s (Atom)"
#. TRANS: %1$s is user nickname
#: actions/all.php:135
#: actions/all.php:138
#, php-format
msgid ""
"This is the timeline for %s and friends but no one has posted anything yet."
@ -155,7 +155,7 @@ msgstr ""
"Isto es le chronologia pro %s e su amicos, ma necuno ha ancora publicate "
"alique."
#: actions/all.php:140
#: actions/all.php:143
#, php-format
msgid ""
"Try subscribing to more people, [join a group](%%action.groups%%) or post "
@ -165,7 +165,7 @@ msgstr ""
"action.groups%%) o publica alique tu mesme."
#. TRANS: %1$s is user nickname, %2$s is user nickname, %2$s is user nickname prefixed with "@"
#: actions/all.php:143
#: actions/all.php:146
#, php-format
msgid ""
"You can try to [nudge %1$s](../%2$s) from his profile or [post something to "
@ -174,7 +174,7 @@ msgstr ""
"Tu pote tentar [dar un pulsata a %1$s](../%2$s) in su profilo o [publicar un "
"message a su attention](%%%%action.newnotice%%%%?status_textarea=%3$s)."
#: actions/all.php:146 actions/replies.php:210 actions/showstream.php:211
#: actions/all.php:149 actions/replies.php:210 actions/showstream.php:211
#, php-format
msgid ""
"Why not [register an account](%%%%action.register%%%%) and then nudge %s or "
@ -184,7 +184,7 @@ msgstr ""
"pulsata a %s o publicar un message a su attention."
#. TRANS: H1 text
#: actions/all.php:179
#: actions/all.php:182
msgid "You and friends"
msgstr "Tu e amicos"
@ -196,8 +196,8 @@ msgstr "Tu e amicos"
msgid "Updates from %1$s and friends on %2$s!"
msgstr "Actualisationes de %1$s e su amicos in %2$s!"
#: actions/apiaccountratelimitstatus.php:70
#: actions/apiaccountupdatedeliverydevice.php:93
#: actions/apiaccountratelimitstatus.php:72
#: actions/apiaccountupdatedeliverydevice.php:94
#: actions/apiaccountupdateprofile.php:97
#: actions/apiaccountupdateprofilebackgroundimage.php:94
#: actions/apiaccountupdateprofilecolors.php:118
@ -221,7 +221,7 @@ msgstr "Actualisationes de %1$s e su amicos in %2$s!"
msgid "API method not found."
msgstr "Methodo API non trovate."
#: actions/apiaccountupdatedeliverydevice.php:85
#: actions/apiaccountupdatedeliverydevice.php:86
#: actions/apiaccountupdateprofile.php:89
#: actions/apiaccountupdateprofilebackgroundimage.php:86
#: actions/apiaccountupdateprofilecolors.php:110
@ -235,7 +235,7 @@ msgstr "Methodo API non trovate."
msgid "This method requires a POST."
msgstr "Iste methodo require un POST."
#: actions/apiaccountupdatedeliverydevice.php:105
#: actions/apiaccountupdatedeliverydevice.php:106
msgid ""
"You must specify a parameter named 'device' with a value of one of: sms, im, "
"none."
@ -243,7 +243,7 @@ msgstr ""
"Tu debe specificar un parametro nominate 'device' con un del valores: sms, "
"im, none."
#: actions/apiaccountupdatedeliverydevice.php:132
#: actions/apiaccountupdatedeliverydevice.php:133
msgid "Could not update user."
msgstr "Non poteva actualisar le usator."
@ -627,7 +627,7 @@ msgstr "Permitter o refusar accesso al informationes de tu conto."
msgid "This method requires a POST or DELETE."
msgstr "Iste methodo require un commando POST o DELETE."
#: actions/apistatusesdestroy.php:131
#: actions/apistatusesdestroy.php:126
msgid "You may not delete another user's status."
msgstr "Tu non pote deler le stato de un altere usator."
@ -6119,6 +6119,9 @@ msgid ""
"If you believe this account is being used abusively, you can block them from "
"your subscribers list and report as spam to site administrators at %s"
msgstr ""
"Si tu crede que iste conto es usate abusivemente, tu pote blocar lo de tu "
"lista de subscriptores e reportar lo como spam al administratores del sito a "
"%s"
#. TRANS: Main body of new-subscriber notification e-mail
#: lib/mail.php:254

View File

@ -10,12 +10,12 @@ msgid ""
msgstr ""
"Project-Id-Version: StatusNet\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-05-25 11:36+0000\n"
"PO-Revision-Date: 2010-06-03 23:02:37+0000\n"
"POT-Creation-Date: 2010-06-10 22:48+0000\n"
"PO-Revision-Date: 2010-06-10 22:51:15+0000\n"
"Language-Team: Portuguese\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: MediaWiki 1.17alpha (r67302); Translate extension (2010-05-24)\n"
"X-Generator: MediaWiki 1.17alpha (r67833); Translate extension (2010-06-10)\n"
"X-Translation-Project: translatewiki.net at http://translatewiki.net\n"
"X-Language-Code: pt\n"
"X-Message-Group: out-statusnet\n"
@ -85,13 +85,13 @@ msgid "Save"
msgstr "Gravar"
#. TRANS: Server error when page not found (404)
#: actions/all.php:65 actions/public.php:98 actions/replies.php:93
#: actions/all.php:68 actions/public.php:98 actions/replies.php:93
#: actions/showfavorites.php:138 actions/tag.php:52
msgid "No such page."
msgstr "Página não foi encontrada."
#: actions/all.php:76 actions/allrss.php:68
#: actions/apiaccountupdatedeliverydevice.php:113
#: actions/all.php:79 actions/allrss.php:68
#: actions/apiaccountupdatedeliverydevice.php:114
#: actions/apiaccountupdateprofile.php:105
#: actions/apiaccountupdateprofilebackgroundimage.php:116
#: actions/apiaccountupdateprofileimage.php:105 actions/apiblockcreate.php:97
@ -115,7 +115,7 @@ msgid "No such user."
msgstr "Utilizador não foi encontrado."
#. TRANS: Page title. %1$s is user nickname, %2$d is page number
#: actions/all.php:87
#: actions/all.php:90
#, php-format
msgid "%1$s and friends, page %2$d"
msgstr "%1$s e amigos, página %2$d"
@ -123,7 +123,7 @@ msgstr "%1$s e amigos, página %2$d"
#. TRANS: Page title. %1$s is user nickname
#. TRANS: H1 text. %1$s is user nickname
#. TRANS: Message is used as link title. %s is a user nickname.
#: actions/all.php:90 actions/all.php:182 actions/allrss.php:116
#: actions/all.php:93 actions/all.php:185 actions/allrss.php:116
#: actions/apitimelinefriends.php:210 actions/apitimelinehome.php:116
#: lib/personalgroupnav.php:100
#, php-format
@ -131,32 +131,32 @@ msgid "%s and friends"
msgstr "%s e amigos"
#. TRANS: %1$s is user nickname
#: actions/all.php:104
#: actions/all.php:107
#, php-format
msgid "Feed for friends of %s (RSS 1.0)"
msgstr "Fonte para os amigos de %s (RSS 1.0)"
#. TRANS: %1$s is user nickname
#: actions/all.php:113
#: actions/all.php:116
#, php-format
msgid "Feed for friends of %s (RSS 2.0)"
msgstr "Fonte para os amigos de %s (RSS 2.0)"
#. TRANS: %1$s is user nickname
#: actions/all.php:122
#: actions/all.php:125
#, php-format
msgid "Feed for friends of %s (Atom)"
msgstr "Fonte para os amigos de %s (Atom)"
#. TRANS: %1$s is user nickname
#: actions/all.php:135
#: actions/all.php:138
#, php-format
msgid ""
"This is the timeline for %s and friends but no one has posted anything yet."
msgstr ""
"Estas são as notas de %s e dos amigos, mas ainda não publicaram nenhuma."
#: actions/all.php:140
#: actions/all.php:143
#, php-format
msgid ""
"Try subscribing to more people, [join a group](%%action.groups%%) or post "
@ -166,7 +166,7 @@ msgstr ""
"publicar qualquer coisa."
#. TRANS: %1$s is user nickname, %2$s is user nickname, %2$s is user nickname prefixed with "@"
#: actions/all.php:143
#: actions/all.php:146
#, php-format
msgid ""
"You can try to [nudge %1$s](../%2$s) from his profile or [post something to "
@ -175,7 +175,7 @@ msgstr ""
"Pode tentar [dar um toque em %1$s](../%2$s) a partir do perfil ou [publicar "
"qualquer coisa à sua atenção](%%%%action.newnotice%%%%?status_textarea=%3$s)."
#: actions/all.php:146 actions/replies.php:210 actions/showstream.php:211
#: actions/all.php:149 actions/replies.php:210 actions/showstream.php:211
#, php-format
msgid ""
"Why not [register an account](%%%%action.register%%%%) and then nudge %s or "
@ -185,7 +185,7 @@ msgstr ""
"publicar uma nota à sua atenção."
#. TRANS: H1 text
#: actions/all.php:179
#: actions/all.php:182
msgid "You and friends"
msgstr "Você e seus amigos"
@ -197,8 +197,8 @@ msgstr "Você e seus amigos"
msgid "Updates from %1$s and friends on %2$s!"
msgstr "Actualizações de %1$s e amigos no %2$s!"
#: actions/apiaccountratelimitstatus.php:70
#: actions/apiaccountupdatedeliverydevice.php:93
#: actions/apiaccountratelimitstatus.php:72
#: actions/apiaccountupdatedeliverydevice.php:94
#: actions/apiaccountupdateprofile.php:97
#: actions/apiaccountupdateprofilebackgroundimage.php:94
#: actions/apiaccountupdateprofilecolors.php:118
@ -222,7 +222,7 @@ msgstr "Actualizações de %1$s e amigos no %2$s!"
msgid "API method not found."
msgstr "Método da API não encontrado."
#: actions/apiaccountupdatedeliverydevice.php:85
#: actions/apiaccountupdatedeliverydevice.php:86
#: actions/apiaccountupdateprofile.php:89
#: actions/apiaccountupdateprofilebackgroundimage.php:86
#: actions/apiaccountupdateprofilecolors.php:110
@ -236,14 +236,14 @@ msgstr "Método da API não encontrado."
msgid "This method requires a POST."
msgstr "Este método requer um POST."
#: actions/apiaccountupdatedeliverydevice.php:105
#: actions/apiaccountupdatedeliverydevice.php:106
msgid ""
"You must specify a parameter named 'device' with a value of one of: sms, im, "
"none."
msgstr ""
"Tem de especificar um parâmetro 'aparelho' com um dos valores: sms, im, none."
#: actions/apiaccountupdatedeliverydevice.php:132
#: actions/apiaccountupdatedeliverydevice.php:133
msgid "Could not update user."
msgstr "Não foi possível actualizar o utilizador."
@ -624,7 +624,7 @@ msgstr "Permitir ou negar acesso à informação da sua conta."
msgid "This method requires a POST or DELETE."
msgstr "Este método requer um POST ou DELETE."
#: actions/apistatusesdestroy.php:131
#: actions/apistatusesdestroy.php:126
msgid "You may not delete another user's status."
msgstr "Não pode apagar o estado de outro utilizador."
@ -2952,11 +2952,11 @@ msgstr ""
#: actions/profilesettings.php:151
msgid "Language"
msgstr "Idioma"
msgstr "Língua"
#: actions/profilesettings.php:152
msgid "Preferred language"
msgstr "Idioma preferido"
msgstr "Língua preferida"
#: actions/profilesettings.php:161
msgid "Timezone"
@ -2982,7 +2982,7 @@ msgstr "Fuso horário não foi seleccionado."
#: actions/profilesettings.php:241
msgid "Language is too long (max 50 chars)."
msgstr "Idioma é demasiado extenso (máx. 50 caracteres)."
msgstr "Língua é demasiado extensa (máx. 50 caracteres)."
#: actions/profilesettings.php:253 actions/tagother.php:178
#, php-format
@ -4013,12 +4013,12 @@ msgstr "Fuso horário por omissão, para o site; normalmente, UTC."
#: actions/siteadminpanel.php:262
msgid "Default language"
msgstr "Idioma do site, por omissão"
msgstr "Língua, por omissão"
#: actions/siteadminpanel.php:263
msgid "Site language when autodetection from browser settings is not available"
msgstr ""
"Idioma do site quando a sua detecção na configuração do browser não é "
"Língua do site quando a sua detecção na configuração do browser não é "
"possível"
#: actions/siteadminpanel.php:271
@ -6114,6 +6114,9 @@ msgid ""
"If you believe this account is being used abusively, you can block them from "
"your subscribers list and report as spam to site administrators at %s"
msgstr ""
"Se acredita que esta conta está sendo usada abusivamente pode bloqueá-la da "
"sua lista de subscritores e reportá-la como spam aos administradores do site "
"em %s"
#. TRANS: Main body of new-subscriber notification e-mail
#: lib/mail.php:254

View File

@ -12,12 +12,12 @@ msgid ""
msgstr ""
"Project-Id-Version: StatusNet\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-05-25 11:36+0000\n"
"PO-Revision-Date: 2010-06-03 23:02:43+0000\n"
"POT-Creation-Date: 2010-06-10 22:48+0000\n"
"PO-Revision-Date: 2010-06-10 22:51:24+0000\n"
"Language-Team: Russian\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: MediaWiki 1.17alpha (r67302); Translate extension (2010-05-24)\n"
"X-Generator: MediaWiki 1.17alpha (r67833); Translate extension (2010-06-10)\n"
"X-Translation-Project: translatewiki.net at http://translatewiki.net\n"
"X-Language-Code: ru\n"
"X-Message-Group: out-statusnet\n"
@ -89,13 +89,13 @@ msgid "Save"
msgstr "Сохранить"
#. TRANS: Server error when page not found (404)
#: actions/all.php:65 actions/public.php:98 actions/replies.php:93
#: actions/all.php:68 actions/public.php:98 actions/replies.php:93
#: actions/showfavorites.php:138 actions/tag.php:52
msgid "No such page."
msgstr "Нет такой страницы."
#: actions/all.php:76 actions/allrss.php:68
#: actions/apiaccountupdatedeliverydevice.php:113
#: actions/all.php:79 actions/allrss.php:68
#: actions/apiaccountupdatedeliverydevice.php:114
#: actions/apiaccountupdateprofile.php:105
#: actions/apiaccountupdateprofilebackgroundimage.php:116
#: actions/apiaccountupdateprofileimage.php:105 actions/apiblockcreate.php:97
@ -119,7 +119,7 @@ msgid "No such user."
msgstr "Нет такого пользователя."
#. TRANS: Page title. %1$s is user nickname, %2$d is page number
#: actions/all.php:87
#: actions/all.php:90
#, php-format
msgid "%1$s and friends, page %2$d"
msgstr "%1$s и друзья, страница %2$d"
@ -127,7 +127,7 @@ msgstr "%1$s и друзья, страница %2$d"
#. TRANS: Page title. %1$s is user nickname
#. TRANS: H1 text. %1$s is user nickname
#. TRANS: Message is used as link title. %s is a user nickname.
#: actions/all.php:90 actions/all.php:182 actions/allrss.php:116
#: actions/all.php:93 actions/all.php:185 actions/allrss.php:116
#: actions/apitimelinefriends.php:210 actions/apitimelinehome.php:116
#: lib/personalgroupnav.php:100
#, php-format
@ -135,31 +135,31 @@ msgid "%s and friends"
msgstr "%s и друзья"
#. TRANS: %1$s is user nickname
#: actions/all.php:104
#: actions/all.php:107
#, php-format
msgid "Feed for friends of %s (RSS 1.0)"
msgstr "Лента друзей %s (RSS 1.0)"
#. TRANS: %1$s is user nickname
#: actions/all.php:113
#: actions/all.php:116
#, php-format
msgid "Feed for friends of %s (RSS 2.0)"
msgstr "Лента друзей %s (RSS 2.0)"
#. TRANS: %1$s is user nickname
#: actions/all.php:122
#: actions/all.php:125
#, php-format
msgid "Feed for friends of %s (Atom)"
msgstr "Лента друзей %s (Atom)"
#. TRANS: %1$s is user nickname
#: actions/all.php:135
#: actions/all.php:138
#, php-format
msgid ""
"This is the timeline for %s and friends but no one has posted anything yet."
msgstr "Это лента %s и друзей, однако пока никто ничего не отправил."
#: actions/all.php:140
#: actions/all.php:143
#, php-format
msgid ""
"Try subscribing to more people, [join a group](%%action.groups%%) or post "
@ -169,7 +169,7 @@ msgstr ""
"action.groups%%) или отправьте что-нибудь сами."
#. TRANS: %1$s is user nickname, %2$s is user nickname, %2$s is user nickname prefixed with "@"
#: actions/all.php:143
#: actions/all.php:146
#, php-format
msgid ""
"You can try to [nudge %1$s](../%2$s) from his profile or [post something to "
@ -179,7 +179,7 @@ msgstr ""
"что-нибудь для привлечения его или её внимания](%%%%action.newnotice%%%%?"
"status_textarea=%3$s)."
#: actions/all.php:146 actions/replies.php:210 actions/showstream.php:211
#: actions/all.php:149 actions/replies.php:210 actions/showstream.php:211
#, php-format
msgid ""
"Why not [register an account](%%%%action.register%%%%) and then nudge %s or "
@ -189,7 +189,7 @@ msgstr ""
"s или отправить запись для привлечения его или её внимания?"
#. TRANS: H1 text
#: actions/all.php:179
#: actions/all.php:182
msgid "You and friends"
msgstr "Вы и друзья"
@ -201,8 +201,8 @@ msgstr "Вы и друзья"
msgid "Updates from %1$s and friends on %2$s!"
msgstr "Обновлено от %1$s и его друзей на %2$s!"
#: actions/apiaccountratelimitstatus.php:70
#: actions/apiaccountupdatedeliverydevice.php:93
#: actions/apiaccountratelimitstatus.php:72
#: actions/apiaccountupdatedeliverydevice.php:94
#: actions/apiaccountupdateprofile.php:97
#: actions/apiaccountupdateprofilebackgroundimage.php:94
#: actions/apiaccountupdateprofilecolors.php:118
@ -226,7 +226,7 @@ msgstr "Обновлено от %1$s и его друзей на %2$s!"
msgid "API method not found."
msgstr "Метод API не найден."
#: actions/apiaccountupdatedeliverydevice.php:85
#: actions/apiaccountupdatedeliverydevice.php:86
#: actions/apiaccountupdateprofile.php:89
#: actions/apiaccountupdateprofilebackgroundimage.php:86
#: actions/apiaccountupdateprofilecolors.php:110
@ -240,7 +240,7 @@ msgstr "Метод API не найден."
msgid "This method requires a POST."
msgstr "Этот метод требует POST."
#: actions/apiaccountupdatedeliverydevice.php:105
#: actions/apiaccountupdatedeliverydevice.php:106
msgid ""
"You must specify a parameter named 'device' with a value of one of: sms, im, "
"none."
@ -248,7 +248,7 @@ msgstr ""
"Вы должны указать параметр с именем «device» и одним из значений: sms, im, "
"none."
#: actions/apiaccountupdatedeliverydevice.php:132
#: actions/apiaccountupdatedeliverydevice.php:133
msgid "Could not update user."
msgstr "Не удаётся обновить пользователя."
@ -636,7 +636,7 @@ msgstr "Разрешить или запретить доступ к инфор
msgid "This method requires a POST or DELETE."
msgstr "Этот метод требует POST или DELETE."
#: actions/apistatusesdestroy.php:131
#: actions/apistatusesdestroy.php:126
msgid "You may not delete another user's status."
msgstr "Вы не можете удалять статус других пользователей."
@ -6136,6 +6136,9 @@ msgid ""
"If you believe this account is being used abusively, you can block them from "
"your subscribers list and report as spam to site administrators at %s"
msgstr ""
"Если вы считаете, эта учётная запись используется со злоупотреблениями, вы "
"можете заблокировать её включение в свой список подписчиков и сообщить о "
"спаме администраторам сайта по %s"
#. TRANS: Main body of new-subscriber notification e-mail
#: lib/mail.php:254

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-06-03 23:00+0000\n"
"POT-Creation-Date: 2010-06-10 22:48+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -81,13 +81,13 @@ msgid "Save"
msgstr ""
#. TRANS: Server error when page not found (404)
#: actions/all.php:65 actions/public.php:98 actions/replies.php:93
#: actions/all.php:68 actions/public.php:98 actions/replies.php:93
#: actions/showfavorites.php:138 actions/tag.php:52
msgid "No such page."
msgstr ""
#: actions/all.php:76 actions/allrss.php:68
#: actions/apiaccountupdatedeliverydevice.php:113
#: actions/all.php:79 actions/allrss.php:68
#: actions/apiaccountupdatedeliverydevice.php:114
#: actions/apiaccountupdateprofile.php:105
#: actions/apiaccountupdateprofilebackgroundimage.php:116
#: actions/apiaccountupdateprofileimage.php:105 actions/apiblockcreate.php:97
@ -111,7 +111,7 @@ msgid "No such user."
msgstr ""
#. TRANS: Page title. %1$s is user nickname, %2$d is page number
#: actions/all.php:87
#: actions/all.php:90
#, php-format
msgid "%1$s and friends, page %2$d"
msgstr ""
@ -119,7 +119,7 @@ msgstr ""
#. TRANS: Page title. %1$s is user nickname
#. TRANS: H1 text. %1$s is user nickname
#. TRANS: Message is used as link title. %s is a user nickname.
#: actions/all.php:90 actions/all.php:182 actions/allrss.php:116
#: actions/all.php:93 actions/all.php:185 actions/allrss.php:116
#: actions/apitimelinefriends.php:210 actions/apitimelinehome.php:116
#: lib/personalgroupnav.php:100
#, php-format
@ -127,31 +127,31 @@ msgid "%s and friends"
msgstr ""
#. TRANS: %1$s is user nickname
#: actions/all.php:104
#: actions/all.php:107
#, php-format
msgid "Feed for friends of %s (RSS 1.0)"
msgstr ""
#. TRANS: %1$s is user nickname
#: actions/all.php:113
#: actions/all.php:116
#, php-format
msgid "Feed for friends of %s (RSS 2.0)"
msgstr ""
#. TRANS: %1$s is user nickname
#: actions/all.php:122
#: actions/all.php:125
#, php-format
msgid "Feed for friends of %s (Atom)"
msgstr ""
#. TRANS: %1$s is user nickname
#: actions/all.php:135
#: actions/all.php:138
#, php-format
msgid ""
"This is the timeline for %s and friends but no one has posted anything yet."
msgstr ""
#: actions/all.php:140
#: actions/all.php:143
#, php-format
msgid ""
"Try subscribing to more people, [join a group](%%action.groups%%) or post "
@ -159,14 +159,14 @@ msgid ""
msgstr ""
#. TRANS: %1$s is user nickname, %2$s is user nickname, %2$s is user nickname prefixed with "@"
#: actions/all.php:143
#: actions/all.php:146
#, php-format
msgid ""
"You can try to [nudge %1$s](../%2$s) from his profile or [post something to "
"his or her attention](%%%%action.newnotice%%%%?status_textarea=%3$s)."
msgstr ""
#: actions/all.php:146 actions/replies.php:210 actions/showstream.php:211
#: actions/all.php:149 actions/replies.php:210 actions/showstream.php:211
#, php-format
msgid ""
"Why not [register an account](%%%%action.register%%%%) and then nudge %s or "
@ -174,7 +174,7 @@ msgid ""
msgstr ""
#. TRANS: H1 text
#: actions/all.php:179
#: actions/all.php:182
msgid "You and friends"
msgstr ""
@ -186,8 +186,8 @@ msgstr ""
msgid "Updates from %1$s and friends on %2$s!"
msgstr ""
#: actions/apiaccountratelimitstatus.php:70
#: actions/apiaccountupdatedeliverydevice.php:93
#: actions/apiaccountratelimitstatus.php:72
#: actions/apiaccountupdatedeliverydevice.php:94
#: actions/apiaccountupdateprofile.php:97
#: actions/apiaccountupdateprofilebackgroundimage.php:94
#: actions/apiaccountupdateprofilecolors.php:118
@ -211,7 +211,7 @@ msgstr ""
msgid "API method not found."
msgstr ""
#: actions/apiaccountupdatedeliverydevice.php:85
#: actions/apiaccountupdatedeliverydevice.php:86
#: actions/apiaccountupdateprofile.php:89
#: actions/apiaccountupdateprofilebackgroundimage.php:86
#: actions/apiaccountupdateprofilecolors.php:110
@ -225,13 +225,13 @@ msgstr ""
msgid "This method requires a POST."
msgstr ""
#: actions/apiaccountupdatedeliverydevice.php:105
#: actions/apiaccountupdatedeliverydevice.php:106
msgid ""
"You must specify a parameter named 'device' with a value of one of: sms, im, "
"none."
msgstr ""
#: actions/apiaccountupdatedeliverydevice.php:132
#: actions/apiaccountupdatedeliverydevice.php:133
msgid "Could not update user."
msgstr ""
@ -605,7 +605,7 @@ msgstr ""
msgid "This method requires a POST or DELETE."
msgstr ""
#: actions/apistatusesdestroy.php:131
#: actions/apistatusesdestroy.php:126
msgid "You may not delete another user's status."
msgstr ""

View File

@ -11,12 +11,12 @@ msgid ""
msgstr ""
"Project-Id-Version: StatusNet\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-05-27 22:55+0000\n"
"PO-Revision-Date: 2010-06-03 23:02:57+0000\n"
"POT-Creation-Date: 2010-06-10 22:48+0000\n"
"PO-Revision-Date: 2010-06-10 22:51:44+0000\n"
"Language-Team: Ukrainian\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: MediaWiki 1.17alpha (r67302); Translate extension (2010-05-24)\n"
"X-Generator: MediaWiki 1.17alpha (r67833); Translate extension (2010-06-10)\n"
"X-Translation-Project: translatewiki.net at http://translatewiki.net\n"
"X-Language-Code: uk\n"
"X-Message-Group: out-statusnet\n"
@ -89,13 +89,13 @@ msgid "Save"
msgstr "Зберегти"
#. TRANS: Server error when page not found (404)
#: actions/all.php:65 actions/public.php:98 actions/replies.php:93
#: actions/all.php:68 actions/public.php:98 actions/replies.php:93
#: actions/showfavorites.php:138 actions/tag.php:52
msgid "No such page."
msgstr "Немає такої сторінки."
#: actions/all.php:76 actions/allrss.php:68
#: actions/apiaccountupdatedeliverydevice.php:113
#: actions/all.php:79 actions/allrss.php:68
#: actions/apiaccountupdatedeliverydevice.php:114
#: actions/apiaccountupdateprofile.php:105
#: actions/apiaccountupdateprofilebackgroundimage.php:116
#: actions/apiaccountupdateprofileimage.php:105 actions/apiblockcreate.php:97
@ -119,7 +119,7 @@ msgid "No such user."
msgstr "Такого користувача немає."
#. TRANS: Page title. %1$s is user nickname, %2$d is page number
#: actions/all.php:87
#: actions/all.php:90
#, php-format
msgid "%1$s and friends, page %2$d"
msgstr "%1$s та друзі, сторінка %2$d"
@ -127,7 +127,7 @@ msgstr "%1$s та друзі, сторінка %2$d"
#. TRANS: Page title. %1$s is user nickname
#. TRANS: H1 text. %1$s is user nickname
#. TRANS: Message is used as link title. %s is a user nickname.
#: actions/all.php:90 actions/all.php:182 actions/allrss.php:116
#: actions/all.php:93 actions/all.php:185 actions/allrss.php:116
#: actions/apitimelinefriends.php:210 actions/apitimelinehome.php:116
#: lib/personalgroupnav.php:100
#, php-format
@ -135,31 +135,31 @@ msgid "%s and friends"
msgstr "%s з друзями"
#. TRANS: %1$s is user nickname
#: actions/all.php:104
#: actions/all.php:107
#, php-format
msgid "Feed for friends of %s (RSS 1.0)"
msgstr "Стрічка дописів для друзів %s (RSS 1.0)"
#. TRANS: %1$s is user nickname
#: actions/all.php:113
#: actions/all.php:116
#, php-format
msgid "Feed for friends of %s (RSS 2.0)"
msgstr "Стрічка дописів для друзів %s (RSS 2.0)"
#. TRANS: %1$s is user nickname
#: actions/all.php:122
#: actions/all.php:125
#, php-format
msgid "Feed for friends of %s (Atom)"
msgstr "Стрічка дописів для друзів %s (Atom)"
#. TRANS: %1$s is user nickname
#: actions/all.php:135
#: actions/all.php:138
#, php-format
msgid ""
"This is the timeline for %s and friends but no one has posted anything yet."
msgstr "Це стрічка дописів %s і друзів, але вона поки що порожня."
#: actions/all.php:140
#: actions/all.php:143
#, php-format
msgid ""
"Try subscribing to more people, [join a group](%%action.groups%%) or post "
@ -169,7 +169,7 @@ msgstr ""
"або напишіть щось самі."
#. TRANS: %1$s is user nickname, %2$s is user nickname, %2$s is user nickname prefixed with "@"
#: actions/all.php:143
#: actions/all.php:146
#, php-format
msgid ""
"You can try to [nudge %1$s](../%2$s) from his profile or [post something to "
@ -178,7 +178,7 @@ msgstr ""
"Ви можете [«розштовхати» %1$s](../%2$s) зі сторінки його профілю або [щось "
"йому написати](%%%%action.newnotice%%%%?status_textarea=%3$s)."
#: actions/all.php:146 actions/replies.php:210 actions/showstream.php:211
#: actions/all.php:149 actions/replies.php:210 actions/showstream.php:211
#, php-format
msgid ""
"Why not [register an account](%%%%action.register%%%%) and then nudge %s or "
@ -188,7 +188,7 @@ msgstr ""
"«розштовхати» %s або щось йому написати."
#. TRANS: H1 text
#: actions/all.php:179
#: actions/all.php:182
msgid "You and friends"
msgstr "Ви з друзями"
@ -200,8 +200,8 @@ msgstr "Ви з друзями"
msgid "Updates from %1$s and friends on %2$s!"
msgstr "Оновлення від %1$s та друзів на %2$s!"
#: actions/apiaccountratelimitstatus.php:70
#: actions/apiaccountupdatedeliverydevice.php:93
#: actions/apiaccountratelimitstatus.php:72
#: actions/apiaccountupdatedeliverydevice.php:94
#: actions/apiaccountupdateprofile.php:97
#: actions/apiaccountupdateprofilebackgroundimage.php:94
#: actions/apiaccountupdateprofilecolors.php:118
@ -225,7 +225,7 @@ msgstr "Оновлення від %1$s та друзів на %2$s!"
msgid "API method not found."
msgstr "API метод не знайдено."
#: actions/apiaccountupdatedeliverydevice.php:85
#: actions/apiaccountupdatedeliverydevice.php:86
#: actions/apiaccountupdateprofile.php:89
#: actions/apiaccountupdateprofilebackgroundimage.php:86
#: actions/apiaccountupdateprofilecolors.php:110
@ -239,14 +239,14 @@ msgstr "API метод не знайдено."
msgid "This method requires a POST."
msgstr "Цей метод потребує POST."
#: actions/apiaccountupdatedeliverydevice.php:105
#: actions/apiaccountupdatedeliverydevice.php:106
msgid ""
"You must specify a parameter named 'device' with a value of one of: sms, im, "
"none."
msgstr ""
"Ви мусите встановити параметр «device» з одним зі значень: sms, im, none."
#: actions/apiaccountupdatedeliverydevice.php:132
#: actions/apiaccountupdatedeliverydevice.php:133
msgid "Could not update user."
msgstr "Не вдалося оновити користувача."
@ -453,7 +453,7 @@ msgstr "Помилкове додаткове ім’я: «%s»."
#: actions/newgroup.php:172
#, php-format
msgid "Alias \"%s\" already in use. Try another one."
msgstr "Додаткове ім’я \"%s\" вже використовується. Спробуйте інше."
msgstr "Додаткове ім’я «%s» вже використовується. Спробуйте інше."
#: actions/apigroupcreate.php:289 actions/editgroup.php:238
#: actions/newgroup.php:178
@ -632,7 +632,7 @@ msgstr "Дозволити або заборонити доступ до Ваш
msgid "This method requires a POST or DELETE."
msgstr "Цей метод потребує або НАПИСАТИ, або ВИДАЛИТИ."
#: actions/apistatusesdestroy.php:131
#: actions/apistatusesdestroy.php:126
msgid "You may not delete another user's status."
msgstr "Ви не можете видалити статус іншого користувача."
@ -970,7 +970,7 @@ msgstr "Підтвердити адресу"
#: actions/confirmaddress.php:161
#, php-format
msgid "The address \"%s\" has been confirmed for your account."
msgstr "Адресу \"%s\" було підтверджено для Вашого акаунту."
msgstr "Адресу «%s» було підтверджено для Вашого акаунту."
#: actions/conversation.php:99
msgid "Conversation"
@ -1315,7 +1315,7 @@ msgstr "опис надто довгий (%d знаків максимум)."
#: actions/editgroup.php:228 actions/newgroup.php:168
#, php-format
msgid "Invalid alias: \"%s\""
msgstr "Помилкове додаткове ім’я: \"%s\""
msgstr "Помилкове додаткове ім’я: «%s»"
#: actions/editgroup.php:258
msgid "Could not update group."
@ -1385,7 +1385,7 @@ msgstr "Скасувати"
#. TRANS: Instructions for e-mail address input form.
#: actions/emailsettings.php:135
msgid "Email address, like \"UserName@example.org\""
msgstr "Електронна адреса, на зразок \"UserName@example.org\""
msgstr "Електронна адреса, на зразок «UserName@example.org»"
#. TRANS: Button label for adding an e-mail address in e-mail settings form.
#. TRANS: Button label for adding an IM address in IM settings form.
@ -1444,7 +1444,7 @@ msgstr "Надсилати мені листа, коли хтось має пр
#. TRANS: Checkbox label in e-mail preferences form.
#: actions/emailsettings.php:199
msgid "Send me email when someone sends me an \"@-reply\"."
msgstr "Надсилати мені листа, коли на мій допис з’являється \"@-відповідь\"."
msgstr "Надсилати мені листа, коли на мій допис з’являється «@-відповідь»."
#. TRANS: Checkbox label in e-mail preferences form.
#: actions/emailsettings.php:205
@ -1882,9 +1882,9 @@ msgid ""
msgstr ""
"Групи на сайті %%%%site.name%%%% дозволять Вам відшукати людей зі спільними "
"інтересами. Лише приєднайтеся до групи і надсилайте повідомлення до усіх її "
"учасників використовуючи просту команду \"!groupname\" у тексті "
"повідомлення. Не бачите групу, яка Вас цікавить? Спробуйте її [знайти](%%%%"
"action.groupsearch%%%%) або [створіть власну!](%%%%action.newgroup%%%%)"
"учасників використовуючи просту команду «!groupname» у тексті повідомлення. "
"Не бачите групу, яка Вас цікавить? Спробуйте її [знайти](%%%%action."
"groupsearch%%%%) або [створіть власну!](%%%%action.newgroup%%%%)"
#: actions/groups.php:107 actions/usergroups.php:126 lib/groupeditform.php:122
msgid "Create a new group"
@ -1991,7 +1991,7 @@ msgid ""
"Jabber or GTalk address, like \"UserName@example.org\". First, make sure to "
"add %s to your buddy list in your IM client or on GTalk."
msgstr ""
"Jabber або GTalk адреса, на зразок \"UserName@example.org\". Але спершу "
"Jabber або GTalk адреса, на зразок «UserName@example.org». Але спершу "
"переконайтеся, що додали %s до списку контактів в своєму IM-клієнті або в "
"GTalk."
@ -2468,12 +2468,12 @@ msgstr ""
#: actions/noticesearchrss.php:96
#, php-format
msgid "Updates with \"%s\""
msgstr "Оновлення з \"%s\""
msgstr "Оновлення з «%s»"
#: actions/noticesearchrss.php:98
#, php-format
msgid "Updates matching search term \"%1$s\" on %2$s!"
msgstr "Всі оновлення за збігом з \"%s\" на %2$s!"
msgstr "Всі оновлення за збігом з «%s» на %2$s!"
#: actions/nudge.php:85
msgid ""
@ -2997,7 +2997,7 @@ msgstr "Мова задовга (50 знаків максимум)."
#: actions/profilesettings.php:253 actions/tagother.php:178
#, php-format
msgid "Invalid tag: \"%s\""
msgstr "Недійсний теґ: \"%s\""
msgstr "Недійсний теґ: «%s»"
#: actions/profilesettings.php:306
msgid "Couldn't update user for autosubscribe."
@ -3079,7 +3079,7 @@ msgid ""
"friends, family, and colleagues! ([Read more](%%doc.help%%))"
msgstr ""
"Це %%site.name%% — сервіс [мікроблоґів](http://uk.wikipedia.org/wiki/"
"Мікроблоггінг), який працює на вільному програмному забезпеченні [StatusNet]"
"Мікроблогінг), який працює на вільному програмному забезпеченні [StatusNet]"
"(http://status.net/). [Приєднуйтесь](%%action.register%%) зараз і зможете "
"розділити своє життя з друзями, родиною і колегами! ([Дізнатися більше](%%"
"doc.help%%))"
@ -3092,7 +3092,7 @@ msgid ""
"tool."
msgstr ""
"Це %%site.name%% — сервіс [мікроблоґів](http://uk.wikipedia.org/wiki/"
"Мікроблоггінг), який працює на вільному програмному забезпеченні [StatusNet]"
"Мікроблогінг), який працює на вільному програмному забезпеченні [StatusNet]"
"(http://status.net/)."
#: actions/publictagcloud.php:57
@ -3803,7 +3803,7 @@ msgid ""
"of this group and many more! ([Read more](%%%%doc.help%%%%))"
msgstr ""
"**%s** це група на %%%%site.name%%%% — сервісі [мікроблоґів](http://uk."
"wikipedia.org/wiki/Мікроблоггінг), який працює на вільному програмному "
"wikipedia.org/wiki/Мікроблогінг), який працює на вільному програмному "
"забезпеченні [StatusNet](http://status.net/). Члени цієї групи роблять "
"короткі дописи про своє життя та інтереси. [Приєднуйтесь](%%%%action.register"
"%%%%) зараз і долучіться до спілкування! ([Дізнатися більше](%%%%doc.help%%%"
@ -3817,10 +3817,10 @@ msgid ""
"[StatusNet](http://status.net/) tool. Its members share short messages about "
"their life and interests. "
msgstr ""
"**%s** це група користувачів на %%site.name%% — сервісі [мікроблоґів](http://"
"uk.wikipedia.org/wiki/Мікроблоггінг), який працює на вільному програмному "
"забезпеченні [StatusNet](http://status.net/). Члени цієї групи роблять "
"короткі дописи про своє життя та інтереси. "
"**%s** це група користувачів на %%%%site.name%%%% — сервісі [мікроблоґів]"
"(http://uk.wikipedia.org/wiki/Мікроблогінг), який працює на вільному "
"програмному забезпеченні [StatusNet](http://status.net/). Члени цієї групи "
"роблять короткі дописи про своє життя та інтереси. "
#: actions/showgroup.php:497
msgid "Admins"
@ -3914,7 +3914,7 @@ msgid ""
"follow **%s**'s notices and many more! ([Read more](%%%%doc.help%%%%))"
msgstr ""
"**%s** користується %%%%site.name%%%% — сервісом [мікроблоґів](http://uk."
"wikipedia.org/wiki/Мікроблоґ), який працює на вільному програмному "
"wikipedia.org/wiki/Мікроблогінг), який працює на вільному програмному "
"забезпеченні [StatusNet](http://status.net/). [Приєднуйтесь](%%%%action."
"register%%%%) зараз і слідкуйте за дописами **%s**, також на Вас чекає "
"багато іншого! ([Дізнатися більше](%%%%doc.help%%%%))"
@ -3927,7 +3927,7 @@ msgid ""
"[StatusNet](http://status.net/) tool. "
msgstr ""
"**%s** є власником акаунту на сайті %%%%site.name%%%% — сервісі [мікроблоґів]"
"(http://uk.wikipedia.org/wiki/Мікроблоггінг), який працює на вільному "
"(http://uk.wikipedia.org/wiki/Мікроблогінг), який працює на вільному "
"програмному забезпеченні [StatusNet](http://status.net/). "
#: actions/showstream.php:305
@ -4064,11 +4064,12 @@ msgstr "Максимальна довжина повідомлення сайт
#: actions/sitenoticeadminpanel.php:176
msgid "Site notice text"
msgstr "Текст повідомлення сайту"
msgstr "Текст повідомлення"
#: actions/sitenoticeadminpanel.php:178
msgid "Site-wide notice text (255 chars max; HTML okay)"
msgstr "Текст повідомлення сайту (255 символів максимум; HTML дозволено)"
msgstr ""
"Текст повідомлення сайту (255 символів максимум; деякий HTML дозволено)"
#: actions/sitenoticeadminpanel.php:198
msgid "Save site notice"
@ -4519,7 +4520,7 @@ msgstr "Помилковий текст привітання. Максималь
#: actions/useradminpanel.php:165
#, php-format
msgid "Invalid default subscripton: '%1$s' is not user."
msgstr "Помилкова підписка за замовчуванням: '%1$s' не є користувачем."
msgstr "Помилкова підписка за замовчуванням: «%1$s» не є користувачем."
#. TRANS: Link description in user account settings menu.
#: actions/useradminpanel.php:218 lib/accountsettingsaction.php:111
@ -4643,32 +4644,32 @@ msgstr "URI слухача «%s» тут не знайдено"
#: actions/userauthorization.php:308
#, php-format
msgid "Listenee URI %s is too long."
msgstr "URI слухача %s задовге."
msgstr "URI слухача «%s» задовге."
#: actions/userauthorization.php:314
#, php-format
msgid "Listenee URI %s is a local user."
msgstr "URI слухача %s це локальний користувач"
msgstr "URI слухача «%s» це локальний користувач"
#: actions/userauthorization.php:329
#, php-format
msgid "Profile URL %s is for a local user."
msgstr "URL-адреса профілю %s для локального користувача."
msgstr "URL-адреса профілю «%s» для локального користувача."
#: actions/userauthorization.php:345
#, php-format
msgid "Avatar URL %s is not valid."
msgstr "URL-адреса автари %s помилкова."
msgstr "URL-адреса аватари «%s» помилкова."
#: actions/userauthorization.php:350
#, php-format
msgid "Cant read avatar URL %s."
msgstr "Не можна прочитати URL аватари %s."
msgstr "Не можна прочитати URL аватари «%s»."
#: actions/userauthorization.php:355
#, php-format
msgid "Wrong image type for avatar URL %s."
msgstr "Неправильний тип зображення для URL-адреси аватари %s."
msgstr "Неправильний тип зображення для URL-адреси аватари «%s»."
#: actions/userdesignsettings.php:76 lib/designsettings.php:65
msgid "Profile design"
@ -5928,7 +5929,7 @@ msgstr "Вперед"
#: lib/grantroleform.php:91
#, php-format
msgid "Grant this user the \"%s\" role"
msgstr "Надати цьому користувачеві роль \"%s\""
msgstr "Надати цьому користувачеві роль «%s»"
#: lib/groupeditform.php:163
msgid "URL of the homepage or blog of the group or topic"
@ -6670,7 +6671,7 @@ msgstr "ІД"
#: lib/profileaction.php:196
msgid "Member since"
msgstr "З нами від"
msgstr "Реєстрація"
#. TRANS: Average count of posts made per day since account registration
#: lib/profileaction.php:235
@ -6724,7 +6725,7 @@ msgstr "Повторити цей допис"
#: lib/revokeroleform.php:91
#, php-format
msgid "Revoke the \"%s\" role from this user"
msgstr "Відкликати роль \"%s\" для цього користувача"
msgstr "Відкликати роль «%s» для цього користувача"
#: lib/router.php:709
msgid "No single user defined for single-user mode."

View File

@ -376,7 +376,7 @@ class GeonamesPlugin extends Plugin
return true;
}
$url = 'http://sw.geonames.org/' . $location->location_id . '/';
$url = 'http://sws.geonames.org/' . $location->location_id . '/';
// it's been filled, so don't process further.
return false;

View File

@ -0,0 +1,163 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2010, StatusNet, Inc.
*
* Creates a dynamic sitemap for a StatusNet site
*
* PHP version 5
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Sample
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
// This check helps protect against security problems;
// your code file can't be executed directly from the web.
exit(1);
}
/**
* Sitemap plugin
*
* @category Sample
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
class SitemapPlugin extends Plugin
{
const USERS_PER_MAP = 50000;
const NOTICES_PER_MAP = 50000;
/**
* Load related modules when needed
*
* @param string $cls Name of the class to be loaded
*
* @return boolean hook value; true means continue processing, false means stop.
*/
function onAutoload($cls)
{
$dir = dirname(__FILE__);
switch ($cls)
{
case 'Sitemap_user_count':
case 'Sitemap_notice_count':
require_once $dir . '/' . $cls . '.php';
return false;
case 'SitemapindexAction':
case 'NoticesitemapAction':
case 'UsersitemapAction':
require_once $dir . '/' . strtolower(mb_substr($cls, 0, -6)) . '.php';
return false;
case 'SitemapAction':
require_once $dir . '/' . strtolower($cls) . '.php';
return false;
default:
return true;
}
}
/**
* Add sitemap-related information at the end of robots.txt
*
* @param Action $action Action being run
*
* @return boolean hook value.
*/
function onEndRobotsTxt($action)
{
$url = common_local_url('sitemapindex');
print "\nSitemap: $url\n";
return true;
}
/**
* Map URLs to actions
*
* @param Net_URL_Mapper $m path-to-action mapper
*
* @return boolean hook value; true means continue processing, false means stop.
*/
function onRouterInitialized($m)
{
$m->connect('sitemapindex.xml',
array('action' => 'sitemapindex'));
$m->connect('/notice-sitemap-:year-:month-:day-:index.xml',
array('action' => 'noticesitemap'),
array('year' => '[0-9]{4}',
'month' => '[01][0-9]',
'day' => '[0123][0-9]',
'index' => '[1-9][0-9]*'));
$m->connect('/user-sitemap-:year-:month-:day-:index.xml',
array('action' => 'usersitemap'),
array('year' => '[0-9]{4}',
'month' => '[01][0-9]',
'day' => '[0123][0-9]',
'index' => '[1-9][0-9]*'));
return true;
}
/**
* Database schema setup
*
* We cache some data persistently to avoid overlong queries.
*
* @see Sitemap_user_count
* @see Sitemap_notice_count
*
* @return boolean hook value; true means continue processing, false means stop.
*/
function onCheckSchema()
{
$schema = Schema::get();
$schema->ensureTable('sitemap_user_count',
array(new ColumnDef('registration_date', 'date', null,
true, 'PRI'),
new ColumnDef('user_count', 'integer'),
new ColumnDef('created', 'datetime',
null, false),
new ColumnDef('modified', 'timestamp')));
$schema->ensureTable('sitemap_notice_count',
array(new ColumnDef('notice_date', 'date', null,
true, 'PRI'),
new ColumnDef('notice_count', 'integer'),
new ColumnDef('created', 'datetime',
null, false),
new ColumnDef('modified', 'timestamp')));
return true;
}
}

View File

@ -0,0 +1,288 @@
<?php
/**
* Data class for counting notice postings by date
*
* PHP version 5
*
* @category Data
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
*
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2010, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
if (!defined('STATUSNET')) {
exit(1);
}
require_once INSTALLDIR . '/classes/Memcached_DataObject.php';
/**
* Data class for counting notices by date
*
* We make a separate sitemap for each notice posted by date.
* To save ourselves some (not inconsiderable) processing effort,
* we cache this data in the sitemap_notice_count table. Each
* row represents a day since the site has been started, with a count
* of notices posted on that day. Since, after the end of the day,
* this number doesn't change, it's a good candidate for persistent caching.
*
* @category Data
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
*
* @see DB_DataObject
*/
class Sitemap_notice_count extends Memcached_DataObject
{
public $__table = 'sitemap_notice_count'; // table name
public $notice_date; // date primary_key not_null
public $notice_count; // int(4)
public $created;
public $modified;
/**
* Get an instance by key
*
* This is a utility method to get a single instance with a given key value.
*
* @param string $k Key to use to lookup (usually 'notice_id' for this class)
* @param mixed $v Value to lookup
*
* @return Sitemap_notice_count object found, or null for no hits
*
*/
function staticGet($k, $v=null)
{
return Memcached_DataObject::staticGet('Sitemap_notice_count', $k, $v);
}
/**
* return table definition for DB_DataObject
*
* DB_DataObject needs to know something about the table to manipulate
* instances. This method provides all the DB_DataObject needs to know.
*
* @return array array of column definitions
*/
function table()
{
return array('notice_date' => DB_DATAOBJECT_DATE + DB_DATAOBJECT_NOTNULL,
'notice_count' => DB_DATAOBJECT_INT,
'created' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL,
'modified' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL);
}
/**
* return key definitions for DB_DataObject
*
* DB_DataObject needs to know about keys that the table has; this function
* defines them.
*
* @return array key definitions
*/
function keys()
{
return array('notice_date' => 'K');
}
/**
* return key definitions for Memcached_DataObject
*
* Our caching system uses the same key definitions, but uses a different
* method to get them.
*
* @return array key definitions
*/
function keyTypes()
{
return $this->keys();
}
static function getAll()
{
$noticeCounts = self::cacheGet('sitemap:notice:counts');
if ($noticeCounts === false) {
$snc = new Sitemap_notice_count();
$snc->orderBy('notice_date DESC');
// Fetch the first one to check up-to-date-itude
$n = $snc->find(true);
$today = self::today();
$noticeCounts = array();
if (!$n) { // No counts saved yet
$noticeCounts = self::initializeCounts();
} else if ($snc->notice_date < $today) { // There are counts but not up to today
$noticeCounts = self::fillInCounts($snc->notice_date);
} else if ($snc->notice_date == $today) { // Refresh today's
$noticeCounts[$today] = self::updateToday();
}
// starts with second-to-last date
while ($snc->fetch()) {
$noticeCounts[$snc->notice_date] = $snc->notice_count;
}
self::cacheSet('sitemap:notice:counts', $noticeCounts);
}
return $noticeCounts;
}
static function initializeCounts()
{
$firstDate = self::getFirstDate(); // awww
$today = self::today();
$counts = array();
for ($d = $firstDate; $d <= $today; $d = self::incrementDay($d)) {
$n = self::getCount($d);
self::insertCount($d, $n);
$counts[$d] = $n;
}
return $counts;
}
static function fillInCounts($lastDate)
{
$today = self::today();
$counts = array();
$n = self::getCount($lastDate);
self::updateCount($lastDate, $n);
$counts[$lastDate] = $n;
for ($d = self::incrementDay($lastDate); $d <= $today; $d = self::incrementDay($d)) {
$n = self::getCount($d);
self::insertCount($d, $n);
}
return $counts;
}
static function updateToday()
{
$today = self::today();
$n = self::getCount($today);
self::updateCount($today, $n);
return $n;
}
static function getCount($d)
{
$notice = new Notice();
$notice->whereAdd('created BETWEEN "'.$d.' 00:00:00" AND "'.self::incrementDay($d).' 00:00:00"');
$notice->whereAdd('is_local = ' . Notice::LOCAL_PUBLIC);
$n = $notice->count();
return $n;
}
static function insertCount($d, $n)
{
$snc = new Sitemap_notice_count();
$snc->notice_date = DB_DataObject_Cast::date($d);
$snc->notice_count = $n;
$snc->created = common_sql_now();
$snc->modified = $snc->created;
if (!$snc->insert()) {
common_log(LOG_WARNING, "Could not save user counts for '$d'");
}
}
static function updateCount($d, $n)
{
$snc = Sitemap_notice_count::staticGet('notice_date', DB_DataObject_Cast::date($d));
if (empty($snc)) {
throw new Exception("No such registration date: $d");
}
$orig = clone($snc);
$snc->notice_date = DB_DataObject_Cast::date($d);
$snc->notice_count = $n;
$snc->created = common_sql_now();
$snc->modified = $snc->created;
if (!$snc->update($orig)) {
common_log(LOG_WARNING, "Could not save user counts for '$d'");
}
}
static function incrementDay($d)
{
$dt = self::dateStrToInt($d);
return self::dateIntToStr($dt + 24 * 60 * 60);
}
static function dateStrToInt($d)
{
return strtotime($d.' 00:00:00');
}
static function dateIntToStr($dt)
{
return date('Y-m-d', $dt);
}
static function getFirstDate()
{
$n = new Notice();
$n->selectAdd();
$n->selectAdd('date(min(created)) as first_date');
if ($n->find(true)) {
return $n->first_date;
} else {
// Is this right?
return self::dateIntToStr(time());
}
}
static function today()
{
return self::dateIntToStr(time());
}
}

View File

@ -0,0 +1,284 @@
<?php
/**
* Data class for counting user registrations by date
*
* PHP version 5
*
* @category Data
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
*
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2010, StatusNet, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
if (!defined('STATUSNET')) {
exit(1);
}
require_once INSTALLDIR . '/classes/Memcached_DataObject.php';
/**
* Data class for counting users by date
*
* We make a separate sitemap for each user registered by date.
* To save ourselves some processing effort, we cache this data
*
* @category Action
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
* @link http://status.net/
*
* @see DB_DataObject
*/
class Sitemap_user_count extends Memcached_DataObject
{
public $__table = 'sitemap_user_count'; // table name
public $registration_date; // date primary_key not_null
public $user_count; // int(4)
public $created;
public $modified;
/**
* Get an instance by key
*
* This is a utility method to get a single instance with a given key value.
*
* @param string $k Key to use to lookup (usually 'user_id' for this class)
* @param mixed $v Value to lookup
*
* @return Sitemap_user_count object found, or null for no hits
*
*/
function staticGet($k, $v=null)
{
return Memcached_DataObject::staticGet('Sitemap_user_count', $k, $v);
}
/**
* return table definition for DB_DataObject
*
* DB_DataObject needs to know something about the table to manipulate
* instances. This method provides all the DB_DataObject needs to know.
*
* @return array array of column definitions
*/
function table()
{
return array('registration_date' => DB_DATAOBJECT_DATE + DB_DATAOBJECT_NOTNULL,
'user_count' => DB_DATAOBJECT_INT,
'created' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL,
'modified' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL);
}
/**
* return key definitions for DB_DataObject
*
* DB_DataObject needs to know about keys that the table has; this function
* defines them.
*
* @return array key definitions
*/
function keys()
{
return array('registration_date' => 'K');
}
function sequenceKey()
{
return array(false, false, false);
}
/**
* return key definitions for Memcached_DataObject
*
* Our caching system uses the same key definitions, but uses a different
* method to get them.
*
* @return array key definitions
*/
function keyTypes()
{
return $this->keys();
}
static function getAll()
{
$userCounts = self::cacheGet('sitemap:user:counts');
if ($userCounts === false) {
$suc = new Sitemap_user_count();
$suc->orderBy('registration_date DESC');
// Fetch the first one to check up-to-date-itude
$n = $suc->find(true);
$today = self::today();
$userCounts = array();
if (!$n) { // No counts saved yet
$userCounts = self::initializeCounts();
} else if ($suc->registration_date < $today) { // There are counts but not up to today
$userCounts = self::fillInCounts($suc->registration_date);
} else if ($suc->registration_date == $today) { // Refresh today's
$userCounts[$today] = self::updateToday();
}
// starts with second-to-last date
while ($suc->fetch()) {
$userCounts[$suc->registration_date] = $suc->user_count;
}
self::cacheSet('sitemap:user:counts', $userCounts);
}
return $userCounts;
}
static function initializeCounts()
{
$firstDate = self::getFirstDate(); // awww
$today = self::today();
$counts = array();
for ($d = $firstDate; $d <= $today; $d = self::incrementDay($d)) {
$n = self::getCount($d);
self::insertCount($d, $n);
$counts[$d] = $n;
}
return $counts;
}
static function fillInCounts($lastDate)
{
$today = self::today();
$counts = array();
$n = self::getCount($lastDate);
self::updateCount($lastDate, $n);
$counts[$lastDate] = $n;
for ($d = self::incrementDay($lastDate); $d <= $today; $d = self::incrementDay($d)) {
$n = self::getCount($d);
self::insertCount($d, $n);
}
return $counts;
}
static function updateToday()
{
$today = self::today();
$n = self::getCount($today);
self::updateCount($today, $n);
return $n;
}
static function getCount($d)
{
$user = new User();
$user->whereAdd('created BETWEEN "'.$d.' 00:00:00" AND "'.self::incrementDay($d).' 00:00:00"');
$n = $user->count();
return $n;
}
static function insertCount($d, $n)
{
$suc = new Sitemap_user_count();
$suc->registration_date = DB_DataObject_Cast::date($d);
$suc->user_count = $n;
$suc->created = common_sql_now();
$suc->modified = $suc->created;
if (!$suc->insert()) {
common_log(LOG_WARNING, "Could not save user counts for '$d'");
}
}
static function updateCount($d, $n)
{
$suc = Sitemap_user_count::staticGet('registration_date', DB_DataObject_Cast::date($d));
if (empty($suc)) {
throw new Exception("No such registration date: $d");
}
$orig = clone($suc);
$suc->registration_date = DB_DataObject_Cast::date($d);
$suc->user_count = $n;
$suc->created = common_sql_now();
$suc->modified = $suc->created;
if (!$suc->update($orig)) {
common_log(LOG_WARNING, "Could not save user counts for '$d'");
}
}
static function incrementDay($d)
{
$dt = self::dateStrToInt($d);
return self::dateIntToStr($dt + 24 * 60 * 60);
}
static function dateStrToInt($d)
{
return strtotime($d.' 00:00:00');
}
static function dateIntToStr($dt)
{
return date('Y-m-d', $dt);
}
static function getFirstDate()
{
$u = new User();
$u->selectAdd();
$u->selectAdd('date(min(created)) as first_date');
if ($u->find(true)) {
return $u->first_date;
} else {
// Is this right?
return self::dateIntToStr(time());
}
}
static function today()
{
return self::dateIntToStr(time());
}
}

View File

@ -0,0 +1,137 @@
<?php
/**
* StatusNet, the distributed open-source microblogging tool
*
* Show list of user pages
*
* PHP version 5
*
* LICENCE: This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Sitemap
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
/**
* sitemap for users
*
* @category Sitemap
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
class NoticesitemapAction extends SitemapAction
{
var $notices = null;
var $j = 0;
function prepare($args)
{
parent::prepare($args);
$y = $this->trimmed('year');
$m = $this->trimmed('month');
$d = $this->trimmed('day');
$i = $this->trimmed('index');
$y += 0;
$m += 0;
$d += 0;
$i += 0;
$this->notices = $this->getNotices($y, $m, $d, $i);
$this->j = 0;
return true;
}
function nextUrl()
{
if ($this->j < count($this->notices)) {
$n = $this->notices[$this->j];
$this->j++;
return array(common_local_url('shownotice', array('notice' => $n[0])),
common_date_w3dtf($n[1]),
'never',
null);
} else {
return null;
}
}
function getNotices($y, $m, $d, $i)
{
$n = Notice::cacheGet("sitemap:notice:$y:$m:$d:$i");
if ($n === false) {
$notice = new Notice();
$begindt = sprintf('%04d-%02d-%02d 00:00:00', $y, $m, $d);
// XXX: estimates 1d == 24h, which screws up days
// with leap seconds (1d == 24h + 1s). Thankfully they're
// few and far between.
$theend = strtotime($begindt) + (24 * 60 * 60);
$enddt = common_sql_date($theend);
$notice->selectAdd();
$notice->selectAdd('id, created');
$notice->whereAdd("created >= '$begindt'");
$notice->whereAdd("created < '$enddt'");
$notice->whereAdd('is_local = ' . Notice::LOCAL_PUBLIC);
$notice->orderBy('created');
$offset = ($i-1) * SitemapPlugin::NOTICES_PER_MAP;
$limit = SitemapPlugin::NOTICES_PER_MAP;
$notice->limit($offset, $limit);
$notice->find();
$n = array();
while ($notice->fetch()) {
$n[] = array($notice->id, $notice->created);
}
$c = Cache::instance();
if (!empty($c)) {
$c->set(Cache::key("sitemap:notice:$y:$m:$d:$i"),
$n,
Cache::COMPRESSED,
((time() > $theend) ? (time() + 90 * 24 * 60 * 60) : (time() + 5 * 60)));
}
}
return $n;
}
}

View File

@ -0,0 +1,95 @@
<?php
/**
* StatusNet, the distributed open-source microblogging tool
*
* Superclass for sitemap-generating actions
*
* PHP version 5
*
* LICENCE: This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Sitemap
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
/**
* superclass for sitemap actions
*
* @category Sitemap
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
class SitemapAction extends Action
{
/**
* handle the action
*
* @param array $args unused.
*
* @return void
*/
function handle($args)
{
header('Content-Type: text/xml; charset=UTF-8');
$this->startXML();
$this->elementStart('urlset', array('xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9'));
while (list($url, $lm, $cf, $p) = $this->nextUrl()) {
$this->showUrl($url, $lm, $cf, $p);
}
$this->elementEnd('urlset');
$this->endXML();
}
function showUrl($url, $lastMod=null, $changeFreq=null, $priority=null)
{
$this->elementStart('url');
$this->element('loc', null, $url);
if (!is_null($lastMod)) {
$this->element('lastmod', null, $lastMod);
}
if (!is_null($changeFreq)) {
$this->element('changefreq', null, $changeFreq);
}
if (!is_null($priority)) {
$this->element('priority', null, $priority);
}
$this->elementEnd('url');
}
function nextUrl()
{
return null;
}
function isReadOnly()
{
return true;
}
}

View File

@ -0,0 +1,128 @@
<?php
/**
* StatusNet, the distributed open-source microblogging tool
*
* Generate sitemap index
*
* PHP version 5
*
* LICENCE: This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Sitemap
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
/**
* Show the sitemap index
*
* @category Sitemap
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
class SitemapindexAction extends Action
{
/**
* handle the action
*
* @param array $args unused.
*
* @return void
*/
function handle($args)
{
header('Content-Type: text/xml; charset=UTF-8');
$this->startXML();
$this->elementStart('sitemapindex', array('xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9'));
$this->showNoticeSitemaps();
$this->showUserSitemaps();
$this->elementEnd('sitemapindex');
$this->endXML();
}
function showUserSitemaps()
{
$userCounts = Sitemap_user_count::getAll();
foreach ($userCounts as $dt => $cnt) {
$cnt = $cnt+0;
if ($cnt == 0) {
continue;
}
$n = (int)$cnt / (int)SitemapPlugin::USERS_PER_MAP;
if (($cnt % SitemapPlugin::USERS_PER_MAP) != 0) {
$n++;
}
for ($i = 1; $i <= $n; $i++) {
$this->showSitemap('user', $dt, $i);
}
}
}
function showNoticeSitemaps()
{
$noticeCounts = Sitemap_notice_count::getAll();
foreach ($noticeCounts as $dt => $cnt) {
if ($cnt == 0) {
continue;
}
$n = $cnt / SitemapPlugin::NOTICES_PER_MAP;
if ($cnt % SitemapPlugin::NOTICES_PER_MAP) {
$n++;
}
for ($i = 1; $i <= $n; $i++) {
$this->showSitemap('notice', $dt, $i);
}
}
}
function showSitemap($prefix, $dt, $i)
{
list($y, $m, $d) = explode('-', $dt);
$this->elementStart('sitemap');
$this->element('loc', null, common_local_url($prefix.'sitemap',
array('year' => $y,
'month' => $m,
'day' => $d,
'index' => $i)));
$begdate = strtotime("$y-$m-$d 00:00:00");
$enddate = $begdate + (24 * 60 * 60);
if ($enddate < time()) {
$this->element('lastmod', null, date(DATE_W3C, $enddate));
}
$this->elementEnd('sitemap');
}
}

View File

@ -0,0 +1,128 @@
<?php
/**
* StatusNet, the distributed open-source microblogging tool
*
* Show list of user pages
*
* PHP version 5
*
* LICENCE: This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Sitemap
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2010 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
exit(1);
}
/**
* sitemap for users
*
* @category Sitemap
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link http://status.net/
*/
class UsersitemapAction extends SitemapAction
{
var $users = null;
var $j = 0;
function prepare($args)
{
parent::prepare($args);
$y = $this->trimmed('year');
$m = $this->trimmed('month');
$d = $this->trimmed('day');
$i = $this->trimmed('index');
$y += 0;
$m += 0;
$d += 0;
$i += 0;
$this->users = $this->getUsers($y, $m, $d, $i);
$this->j = 0;
return true;
}
function nextUrl()
{
if ($this->j < count($this->users)) {
$nickname = $this->users[$this->j];
$this->j++;
return array(common_profile_url($nickname), null, null, '1.0');
} else {
return null;
}
}
function getUsers($y, $m, $d, $i)
{
$u = User::cacheGet("sitemap:user:$y:$m:$d:$i");
if ($u === false) {
$user = new User();
$begindt = sprintf('%04d-%02d-%02d 00:00:00', $y, $m, $d);
// XXX: estimates 1d == 24h, which screws up days
// with leap seconds (1d == 24h + 1s). Thankfully they're
// few and far between.
$theend = strtotime($begindt) + (24 * 60 * 60);
$enddt = common_sql_date($theend);
$user->selectAdd();
$user->selectAdd('nickname');
$user->whereAdd("created >= '$begindt'");
$user->whereAdd("created < '$enddt'");
$user->orderBy('created');
$offset = ($i-1) * SitemapPlugin::USERS_PER_MAP;
$limit = SitemapPlugin::USERS_PER_MAP;
$user->limit($offset, $limit);
$user->find();
while ($user->fetch()) {
$u[] = $user->nickname;
}
$c = Cache::instance();
if (!empty($c)) {
$c->set(Cache::key("sitemap:user:$y:$m:$d:$i"),
$u,
Cache::COMPRESSED,
((time() > $theend) ? (time() + 90 * 24 * 60 * 60) : (time() + 5 * 60)));
}
}
return $u;
}
}