code:
# Translation of StatusNet - OStatus to Ukrainian (українська)
# Exported from translatewiki.net
#
# Author: Boogie
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - OStatus\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-06-30 11:07+0000\n"
"PO-Revision-Date: 2012-06-30 11:09:34+0000\n"
"Language-Team: Ukrainian <https://translatewiki.net/wiki/Portal:uk>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-12-03 13:49:04+0000\n"
"X-Generator: MediaWiki 1.20alpha (233fc08); Translate 2012-06-21\n"
"X-Translation-Project: translatewiki.net <https://translatewiki.net>\n"
"X-Language-Code: uk\n"
"X-Message-Group: #out-statusnet-plugin-ostatus\n"
"Plural-Forms: nplurals=3; plural=(n%10 == 1 && n%100 != 11) ? 0 : ( (n%10 >= "
"2 && n%10 <= 4 && (n%100 < 10 || n%100 >= 20)) ? 1 : 2 );\n"

#. TRANS: String in the gettext speed test script. Unimportant.
msgid "Feeds"
msgstr "Веб-стрічки"

#. TRANS: Link to subscribe to a remote entity.
#. TRANS: Link text for a user to subscribe to an OStatus user.
msgid "Subscribe"
msgstr "Підписатись"

#. TRANS: Fieldset legend.
#, fuzzy
msgid "List remote profile"
msgstr "Позначити віддалений профіль."

#. TRANS: Field label.
msgctxt "LABEL"
msgid "Remote profile"
msgstr "Віддалений профіль"

#. TRANS: Field title.
#. TRANS: Tooltip for field label "Subscribe to".
msgid ""
"OStatus user's address, like nickname@example.com or http://example.net/"
"nickname."
msgstr ""
"OStatus-адреса користувача, щось на зразок nickname@example.com або http://"
"example.net/nickname"

#. TRANS: Button text to fetch remote profile.
msgctxt "BUTTON"
msgid "Fetch"
msgstr "Вивести"

#. TRANS: Exception in OStatus when invalid URI was entered.
msgid "Invalid URI."
msgstr "Неправильний URI."

#. TRANS: Error message in OStatus plugin. Do not translate the domain names example.com
#. TRANS: and example.net, as these are official standard domain names for use in examples.
msgid ""
"Sorry, we could not reach that address. Please make sure that the OStatus "
"address is like nickname@example.com or http://example.net/nickname."
msgstr ""
"Вибачайте, але ми в змозі розшукати дану адресу. Будь ласка, переконайтеся, "
"що адресу зазначено згідно правил протоколу OStatus, щось на зразок "
"nickname@example.com або ж http://example.net/nickname."

#. TRANS: Title. %s is a domain name.
#, php-format
msgid "Sent from %s via OStatus"
msgstr "Надіслано з %s через OStatus"

#. TRANS: Exception thrown when setup of remote subscription fails.
msgid "Could not set up remote subscription."
msgstr "Не вдалося створити віддалену підписку."

#. TRANS: Title for unfollowing a remote profile.
msgctxt "TITLE"
msgid "Unfollow"
msgstr "Не читати"

#. TRANS: Success message for unsubscribe from user attempt through OStatus.
#. TRANS: %1$s is the unsubscriber's name, %2$s is the unsubscribed user's name.
#, php-format
msgid "%1$s stopped following %2$s."
msgstr "%1$s припинив читати ваші дописи %2$s."

#. TRANS: Exception thrown when setup of remote group membership fails.
msgid "Could not set up remote group membership."
msgstr "Не вдалося приєднатися до віддаленої спільноти."

#. TRANS: Title for joining a remote groep.
msgctxt "TITLE"
msgid "Join"
msgstr "Приєднатися"

#. TRANS: Success message for subscribe to group attempt through OStatus.
#. TRANS: %1$s is the member name, %2$s is the subscribed group's name.
#, php-format
msgid "%1$s has joined group %2$s."
msgstr "%1$s приєднався до спільноти %2$s."

#. TRANS: Exception thrown when joining a remote group fails.
msgid "Failed joining remote group."
msgstr "Помилка приєднання до віддаленої спільноти."

#. TRANS: Title for leaving a remote group.
msgctxt "TITLE"
msgid "Leave"
msgstr "Залишити"

#. TRANS: Success message for unsubscribe from group attempt through OStatus.
#. TRANS: %1$s is the member name, %2$s is the unsubscribed group's name.
#, php-format
msgid "%1$s has left group %2$s."
msgstr "%1$s залишив спільноту %2$s."

#. TRANS: Exception thrown when setup of remote list subscription fails.
msgid "Could not set up remote list subscription."
msgstr "Не вдалося налаштувати підписку до віддаленого списку."

#. TRANS: Title for following a remote list.
msgctxt "TITLE"
msgid "Follow list"
msgstr "Слідкувати за списком"

#. TRANS: Success message for remote list follow through OStatus.
#. TRANS: %1$s is the subscriber name, %2$s is the list, %3$s is the lister's name.
#, php-format
msgid "%1$s is now following people listed in %2$s by %3$s."
msgstr "%1$s тепер відслідковує дописи людей у списку %2$s користувача %3$s."

#. TRANS: Exception thrown when subscription to remote list fails.
msgid "Failed subscribing to remote list."
msgstr "Помилка підключення до віддаленого списку."

#. TRANS: Title for unfollowing a remote list.
msgid "Unfollow list"
msgstr "Не стежити за списком"

#. TRANS: Success message for remote list unfollow through OStatus.
#. TRANS: %1$s is the subscriber name, %2$s is the list, %3$s is the lister's name.
#, php-format
msgid "%1$s stopped following the list %2$s by %3$s."
msgstr "%1$s припинив слідкувати за списком %2$s користувача %3$s."

#. TRANS: Title for listing a remote profile.
msgctxt "TITLE"
msgid "List"
msgstr "Список"

#. TRANS: Success message for remote list addition through OStatus.
#. TRANS: %1$s is the list creator's name, %2$s is the added list member, %3$s is the list name.
#, php-format
msgid "%1$s listed %2$s in the list %3$s."
msgstr "%1$s включив %2$s до списку %3$s."

#. TRANS: Exception thrown when subscribing to a remote list fails.
#, php-format
msgid ""
"Could not complete subscription to remote profile's feed. List %s could not "
"be saved."
msgstr ""
"Не вдається завершити підписку до каналу віддаленого профілю. Список %s "
"зберегти не вдалося."

#. TRANS: Title for unlisting a remote profile.
msgctxt "TITLE"
msgid "Unlist"
msgstr "Вилучити зі списку"

#. TRANS: Success message for remote list removal through OStatus.
#. TRANS: %1$s is the list creator's name, %2$s is the removed list member, %3$s is the list name.
#, php-format
msgid "%1$s removed %2$s from the list %3$s."
msgstr "%1$s вилучив %2$s зі списку %3$s."

#. TRANS: Title for unliking a remote notice.
msgid "Unlike"
msgstr "Вилучити зі списку обраних"

#. TRANS: Success message for remove a favorite notice through OStatus.
#. TRANS: %1$s is the unfavoring user's name, %2$s is URI to the no longer favored notice.
#, php-format
msgid "%1$s no longer likes %2$s."
msgstr "%1$s вилучив допис %2$s зі свого списку обраних дописів."

#. TRANS: Link text for link to remote subscribe.
msgid "Remote"
msgstr "Віддалено"

#. TRANS: Title for activity.
msgid "Profile update"
msgstr "Оновлення профілю"

#. TRANS: Ping text for remote profile update through OStatus.
#. TRANS: %s is user that updated their profile.
#, php-format
msgid "%s has updated their profile page."
msgstr "%s оновив сторінку свого профілю."

#. TRANS: Link text for a user to list an OStatus user.
#, fuzzy
msgid "List"
msgstr "Список"

#. TRANS: Plugin description.
msgid ""
"Follow people across social networks that implement OStatus."
msgstr ""
"Додає можливість слідкувати за дописами людей з інших мереж, які підтримують "
"протокол OStatus."

#. TRANS: Client exception.
msgid "Publishing outside feeds not supported."
msgstr "Публікація змісту зовнішніх веб-стрічок не підтримується."

#. TRANS: Client exception. %s is a mode.
#, php-format
msgid "Unrecognized mode \"%s\"."
msgstr "Невизначений режим «%s»."

#. TRANS: Client exception. %s is a topic.
#, php-format
msgid ""
"Unsupported hub.topic %s this hub only serves local user and group Atom "
"feeds."
msgstr ""
"hub.topic %s не підтримується. Цей вузол використовується лише тутешніми "
"користувачами та групою веб-стрічок у форматі Atom."

#. TRANS: Client exception. %s is sync or async.
#, php-format
msgid "Invalid hub.verify \"%s\". It must be sync or async."
msgstr "hub.verify «%s» невірний. Він має бути синхронним або ж асинхронним."

#. TRANS: Client exception. %s is the invalid lease value.
#, php-format
msgid "Invalid hub.lease \"%s\". It must be empty or positive integer."
msgstr ""
"hub.lease «%s» невірний. Він має бути порожнім або містити ціле позитивне "
"число."

#. TRANS: Client exception. %s is the invalid hub secret.
#, php-format
msgid "Invalid hub.secret \"%s\". It must be under 200 bytes."
msgstr "hub.secret «%s» невірний. 200 байтів — не більше."

#. TRANS: Client exception. %s is a feed URL.
#, php-format
msgid "Invalid hub.topic \"%s\". User does not exist."
msgstr "Невірний hub.topic «%s». Користувача не існує."

#. TRANS: Client exception. %s is a feed URL.
#, php-format
msgid "Invalid hub.topic \"%s\". Group does not exist."
msgstr "Невірний hub.topic «%s». Спільноти не існує."

#. TRANS: Client exception. %s is a feed URL.
#, php-format
msgid "Invalid hub.topic %s; list does not exist."
msgstr "Невірний hub.topic «%s». Список не існує."

#. TRANS: Client exception.
#. TRANS: %1$s is this argument to the method this exception occurs in, %2$s is a URL.
#, php-format
msgid "Invalid URL passed for %1$s: \"%2$s\""
msgstr "Для %1$s передано невірний URL: «%2$s»"

#. TRANS: Client error displayed when trying to list a local object as if it is remote.
#, fuzzy
msgid "You can use the local list functionality!"
msgstr "Ви можете користуватись локальними підписками!"

#. TRANS: Header for listing a remote object. %s is a remote object's name.
#, fuzzy, php-format
msgid "List %s"
msgstr "Список"

#. TRANS: Button text to list a remote object.
msgctxt "BUTTON"
msgid "Go"
msgstr "Перейти"

#. TRANS: Field label.
msgid "User nickname"
msgstr "Ім’я користувача"

#. TRANS: Field title.
#, fuzzy
msgid "Nickname of the user you want to list."
msgstr "Ім’я користувача, якого ви хотіли б позначити теґом."

#. TRANS: Field label.
msgid "Profile Account"
msgstr "Профіль акаунту"

#. TRANS: Field title.
msgid "Your account id (for example user@identi.ca)."
msgstr "Ідентифікатор вашого акаунту (щось на зразок user@identi.ca)."

#. TRANS: Client error displayed when remote profile could not be looked up.
#. TRANS: Client error.
msgid "Could not look up OStatus account profile."
msgstr "Не вдалося знайти профіль OStatus-акаунту."

#. TRANS: Client error displayed when remote profile address could not be confirmed.
#. TRANS: Client error.
msgid "Could not confirm remote profile address."
msgstr "Не вдалося підтвердити адресу віддаленого профілю."

#. TRANS: Title for an OStatus list.
msgid "OStatus list"
msgstr "Список OStatus"

#. TRANS: Server exception thrown when referring to a non-existing or empty feed.
msgid "Empty or invalid feed id."
msgstr "Порожній або недійсний ідентифікатор веб-стрічки."

#. TRANS: Server exception. %s is a feed ID.
#, php-format
msgid "Unknown PuSH feed id %s"
msgstr "Веб-стрічка за протоколом PuSH має невідомий ідентифікатор %s"

#. TRANS: Client exception. %s is an invalid feed name.
#, php-format
msgid "Bad hub.topic feed \"%s\"."
msgstr "hub.topic веб-стрічки «%s» неправильний."

#. TRANS: Client exception. %1$s the invalid token, %2$s is the topic for which the invalid token was given.
#, php-format
msgid "Bad hub.verify_token %1$s for %2$s."
msgstr "hub.verify_token %1$s для %2$s неправильний."

#. TRANS: Client exception. %s is an invalid topic.
#, php-format
msgid "Unexpected subscribe request for %s."
msgstr "Несподіваний запит підписки для %s."

#. TRANS: Client exception. %s is an invalid topic.
#, php-format
msgid "Unexpected unsubscribe request for %s."
msgstr "Несподіваний запит щодо скасування підписки для %s."

#. TRANS: Client error displayed when referring to a non-existing user.
#. TRANS: Client error.
msgid "No such user."
msgstr "Такого користувача немає."

#. TRANS: Field label for a field that takes an OStatus user address.
msgid "Subscribe to"
msgstr "Підписатися"

#. TRANS: Button text.
#. TRANS: Button text to continue joining a remote list.
msgctxt "BUTTON"
msgid "Continue"
msgstr "Продовжити"

#. TRANS: Button text.
msgid "Join"
msgstr "Приєднатися"

#. TRANS: Tooltip for button "Join".
msgctxt "BUTTON"
msgid "Join this group"
msgstr "Приєднатися до спільноти"

#. TRANS: Button text.
msgctxt "BUTTON"
msgid "Confirm"
msgstr "Підтвердити"

#. TRANS: Tooltip for button "Confirm".
msgid "Subscribe to this user"
msgstr "Підписатись до цього користувача"

#. TRANS: Extra paragraph in remote profile view when already subscribed.
msgid "You are already subscribed to this user."
msgstr "Ви вже підписані до цього користувача."

#. TRANS: Error text.
msgid ""
"Sorry, we could not reach that feed. Please try that OStatus address again "
"later."
msgstr ""
"Вибачайте, але ми не в змозі досягти цієї веб-стрічки. Будь ласка, спробуйте "
"дану адресу ще раз пізніше."

#. TRANS: OStatus remote subscription dialog error.
#. TRANS: OStatus remote group subscription dialog error.
msgid "Already subscribed!"
msgstr "Вже підписаний!"

#. TRANS: OStatus remote subscription dialog error.
msgid "Remote subscription failed!"
msgstr "Підписатися віддалено не вдалося!"

#. TRANS: Client error displayed when the session token does not match or is not given.
msgid "There was a problem with your session token. Try again, please."
msgstr "Виникли певні проблеми з токеном сесії. Спробуйте знов, будь ласка."

#. TRANS: Form title.
msgid "Subscribe to user"
msgstr "Підписатися до користувача"

#. TRANS: Page title for OStatus remote subscription form.
msgid "Confirm"
msgstr "Підтвердити"

#. TRANS: Instructions.
msgid ""
"You can subscribe to users from other supported sites. Paste their address "
"or profile URI below:"
msgstr ""
"Ви маєте можливість підписуватись до користувачів на аналогічних сайтах. "
"Просто вставте їхні адреси або URI профілів тут:"

#. TRANS: Field label.
msgid "Join group"
msgstr "Долучитися до спільноти"

#. TRANS: Tooltip for field label "Join group". Do not translate the "example.net"
#. TRANS: domain name in the URL, as it is an official standard domain name for examples.
msgid "OStatus group's address, like http://example.net/group/nickname."
msgstr ""
"Адреса спільноти згідно протоколу OStatus, наприклад http://example.net/"
"group/nickname."

#. TRANS: Error text displayed when trying to join a remote group the user is already a member of.
msgid "You are already a member of this group."
msgstr "Ви вже є учасником цієї спільноти."

#. TRANS: OStatus remote group subscription dialog error.
msgid "Already a member!"
msgstr "Ви вже учасник!"

#. TRANS: OStatus remote group subscription dialog error.
msgid "Remote group join failed!"
msgstr "Приєднатися до віддаленої спільноти не вдалося!"

#. TRANS: Page title for OStatus remote group join form
msgid "Confirm joining remote group"
msgstr "Підтвердження приєднання до віддаленої спільноти"

#. TRANS: Form instructions.
msgid ""
"You can subscribe to groups from other supported sites. Paste the group's "
"profile URI below:"
msgstr ""
"Ви можете долучатися до спільнот на аналогічних сайтах. Просто вставте URI "
"профілю спільноти тут:"

#. TRANS: Client error displayed trying to perform an action without providing an ID.
#. TRANS: Client error.
#. TRANS: Client error displayed trying to perform an action without providing an ID.
msgid "No ID."
msgstr "Немає ідентифікатора."

#. TRANS: Client exception thrown when an undefied activity is performed.
#. TRANS: Client exception.
msgid "Cannot handle that kind of post."
msgstr "Не вдається обробити такий тип допису."

#. TRANS: Client exception.
msgid "In reply to unknown notice."
msgstr "У відповідь на невідомий допис."

#. TRANS: Client exception.
msgid "In reply to a notice not by this user and not mentioning this user."
msgstr ""
"У відповідь на допис іншого користувача, а даний користувач у ньому навіть "
"не згадується."

#. TRANS: Client exception.
msgid "To the attention of user(s), not including this one."
msgstr "До уваги користувача(ів), не включаючи це."

#. TRANS: Client exception.
msgid "Not to anyone in reply to anything."
msgstr "Ні для кого у відповідь на щось."

#. TRANS: Client exception.
msgid "This is already a favorite."
msgstr "Цей допис вже є обраним."

#. TRANS: Client exception.
msgid "Could not save new favorite."
msgstr "Не вдалося зберегти як новий обраний допис."

#. TRANS: Client exception.
msgid "Notice was not favorited!"
msgstr "Допис не було додано до списку обраних!"

#. TRANS: Client exception.
msgid "Not a person object."
msgstr "Не персональний об’єкт."

#. TRANS: Client exception.
#, fuzzy
msgid "Unidentified profile being listed."
msgstr "До невідомого профілю застосовано теґи."

#. TRANS: Client exception.
#, fuzzy
msgid "This user is not the one being listed."
msgstr "Цей користувач не є тим, до якого застосовано теґи."

#. TRANS: Client exception.
#, fuzzy
msgid "The listing could not be saved."
msgstr "Хмарка теґів не може бути збереженою."

#. TRANS: Client exception.
#, fuzzy
msgid "Unidentified profile being unlisted."
msgstr "З невідомого профілю знято всі теґи."

#. TRANS: Client exception.
#, fuzzy
msgid "This user is not the one being unlisted."
msgstr "Цей користувач не є тим, з профілю якого знято теґи."

#. TRANS: Client exception.
#, fuzzy
msgid "The listing could not be deleted."
msgstr "Хмарка теґів не може бути видаленою."

#. TRANS: Client exception.
msgid "Cannot favorite/unfavorite without an object."
msgstr ""
"Неможливо додати до обраних або видалити зі списку обраних, якщо немає "
"об’єкта."

#. TRANS: Client exception.
msgid "Cannot handle that kind of object for liking/faving."
msgstr ""
"Не вдається обробити подібний об’єкт для додавання його до списку обраних "
"або вилучення з цього списку."

#. TRANS: Client exception. %s is an object ID.
#, php-format
msgid "Notice with ID %s unknown."
msgstr "Допис з ідентифікатором %s є невідомим."

#. TRANS: Client exception. %1$s is a notice ID, %2$s is a user ID.
#, php-format
msgid "Notice with ID %1$s not posted by %2$s."
msgstr "Допис з ідентифікатором %1$s було надіслано не %2$s."

#. TRANS: Field label.
msgid "Subscribe to list"
msgstr "Підписатися до списку"

#. TRANS: Field title.
msgid "Address of the OStatus list, like http://example.net/user/all/tag."
msgstr "Адреса списку OStatus, наприклад, http://example.net/user/all/tag."

#. TRANS: Error text displayed when trying to subscribe to a list already a subscriber to.
msgid "You are already subscribed to this list."
msgstr "Ви вже підписані до цього списку."

#. TRANS: Page title for OStatus remote list subscription form
msgid "Confirm subscription to remote list"
msgstr "Підтвердження підписки до віддаленого списку"

#. TRANS: Instructions for OStatus list subscription form.
msgid ""
"You can subscribe to lists from other supported sites. Paste the list's URI "
"below:"
msgstr ""
"Ви можете підписуватися до списків на аналогічних сайтах. Просто вставте URI "
"списку тут:"

#. TRANS: Client error.
msgid "No such group."
msgstr "Такої спільноти немає."

#. TRANS: Client error.
msgid "Cannot accept remote posts for a remote group."
msgstr "Не можу узгодити віддалену пересилку дописів до віддаленої спільноти."

#. TRANS: Client error.
msgid "Cannot read profile to set up group membership."
msgstr "Не можу прочитати профіль, аби долучитися до спільноти."

#. TRANS: Client error.
#. TRANS: Client error displayed when trying to have a group join another group.
msgid "Groups cannot join groups."
msgstr "Спільноти не можуть приєднуватися до спільнот."

#. TRANS: Client error displayed when trying to join a group the user is blocked from by a group admin.
msgid "You have been blocked from that group by the admin."
msgstr "Адміністратор спільноти заблокував ваш профіль."

#. TRANS: Server error. %1$s is a profile URI, %2$s is a group nickname.
#, php-format
msgid "Could not join remote user %1$s to group %2$s."
msgstr ""
"Віддаленому користувачеві %1$s не вдалося долучитися до спільноти %2$s."

#. TRANS: Client error displayed when group membership cannot be cancelled
#. TRANS: because the remote profile could not be read.
msgid "Cannot read profile to cancel group membership."
msgstr ""
"Не вдається прочитати профіль користувача, щоб скасувати його участь у "
"спільноті."

#. TRANS: Server error. %1$s is a profile URI, %2$s is a group nickname.
#, php-format
msgid "Could not remove remote user %1$s from group %2$s."
msgstr "Не вдалось видалити віддаленого користувача %1$s зі спільноти %2$s."

#. TRANS: Client error displayed when referring to a non-existing list.
#. TRANS: Client error.
msgid "No such list."
msgstr "Такого списку немає."

#. TRANS: Client error displayed when trying to send a message to a remote list.
msgid "Cannot accept remote posts for a remote list."
msgstr "Не можу узгодити віддалену пересилку дописів для віддаленого списку."

#. TRANS: Client error displayed when referring to a non-existing remote list.
msgid "Cannot read profile to set up list subscription."
msgstr "Не можу прочитати профіль, аби налаштувати підписку до списку."

#. TRANS: Client error displayed when trying to subscribe a group to a list.
#. TRANS: Client error displayed when trying to unsubscribe a group from a list.
msgid "Groups cannot subscribe to lists."
msgstr "Спільноти не можуть підписуватись до списків."

#. TRANS: Server error displayed when subscribing a remote user to a list fails.
#. TRANS: %1$s is a profile URI, %2$s is a list name.
#, php-format
msgid "Could not subscribe remote user %1$s to list %2$s."
msgstr "Не можу підписати віддаленого користувача %1$s до списку %2$s."

#. TRANS: Client error displayed when trying to unsubscribe from non-existing list.
msgid "Cannot read profile to cancel list subscription."
msgstr ""
"Не вдається прочитати профіль користувача, щоб скасувати підписку до списку."

#. TRANS: Client error displayed when trying to unsubscribe a remote user from a list fails.
#. TRANS: %1$s is a profile URL, %2$s is a list name.
#, php-format
msgid "Could not unsubscribe remote user %1$s from list %2$s."
msgstr "Не можу відписати віддаленого користувача %1$s від списку %2$s."

#. TRANS: Client error.
msgid "You can use the local subscription!"
msgstr "Ви можете користуватись локальними підписками!"

#. TRANS: Form title.
msgctxt "TITLE"
msgid "Subscribe to user"
msgstr "Підписатися до користувача"

#. TRANS: Form legend. %s is a group name.
#, php-format
msgid "Join group %s"
msgstr "Приєднатися до спільноти %s"

#. TRANS: Button text to join a group.
msgctxt "BUTTON"
msgid "Join"
msgstr "Приєднатися"

#. TRANS: Form legend. %1$s is a list, %2$s is a lister's name.
#, php-format
msgid "Subscribe to list %1$s by %2$s"
msgstr "Підписатися до списку %1$s користувача %2$s"

#. TRANS: Button text to subscribe to a list.
#. TRANS: Button text to subscribe to a profile.
msgctxt "BUTTON"
msgid "Subscribe"
msgstr "Підписатись"

#. TRANS: Form legend. %s is a nickname.
#, php-format
msgid "Subscribe to %s"
msgstr "Підписатися до %s"

#. TRANS: Field label.
msgid "Group nickname"
msgstr "Назва спільноти"

#. TRANS: Field title.
msgid "Nickname of the group you want to join."
msgstr "Назва спільноти, до якої ви хотіли б приєднатися."

#. TRANS: Field title.
msgid "Nickname of the user you want to follow."
msgstr "Ім’я користувача, дописи якого ви хотіли б читати."

#. TRANS: Tooltip for field label "Profile Account".
msgid "Your account ID (e.g. user@identi.ca)."
msgstr "Ідентифікатор вашого акаунту (щось на зразок user@identi.ca)."

#. TRANS: Client error.
msgid "Must provide a remote profile."
msgstr "Мусите зазначити віддалений профіль."

#. TRANS: Client error.
msgid "No local user or group nickname provided."
msgstr "Не зазначено псевдоніму ані локального користувача ані спільноти."

#. TRANS: Page title.
msgid "OStatus Connect"
msgstr "З’єднання OStatus"

#. TRANS: Server exception. %s is a URL.
#, php-format
msgid "Invalid avatar URL %s."
msgstr "Невірна URL-адреса аватари %s."

#. TRANS: Server exception. %s is a URI.
#, php-format
msgid "Tried to update avatar for unsaved remote profile %s."
msgstr "Намагаюся оновити аватару для не збереженого віддаленого профілю %s."

#. TRANS: Server exception. %s is a URL.
#, php-format
msgid "Unable to fetch avatar from %s."
msgstr "Неможливо завантажити аватару з %s."

#. TRANS: Exception. %s is a URL.
#, php-format
msgid "Could not find a feed URL for profile page %s."
msgstr "Не вдалося знайти URL веб-стрічки для сторінки профілю %s."

#. TRANS: Exception.
msgid "Not a valid webfinger address."
msgstr "Це недійсна адреса для протоколу WebFinger."

#. TRANS: Exception. %s is a webfinger address.
#, php-format
msgid "Could not find a valid profile for \"%s\"."
msgstr "Не можу знайти відповідний й профіль для «%s»."

#. TRANS: Server exception.
msgid "Attempting to start PuSH subscription for feed with no hub."
msgstr ""
"Спроба підписатися за допомогою PuSH до веб-стрічки, котра не має вузла."

#. TRANS: Server exception.
msgid "Attempting to end PuSH subscription for feed with no hub."
msgstr ""
"Спроба скасувати підписку за допомогою PuSH до веб-стрічки, котра не має "
"вузла."

#. TRANS: Server exception. %s is a URI
#, php-format
msgid "Invalid ostatus_profile state: Two or more IDs set for %s."
msgstr ""
"Невірний стан параметру ostatus_profile: два або більше ідентифікатори "
"встановлено для %s."

#. TRANS: Server exception. %s is a URI
#, php-format
msgid "Invalid ostatus_profile state: All IDs empty for %s."
msgstr ""
"Невірний стан параметру ostatus_profile: всі ідентифікатори порожні для %s."

#. TRANS: Server exception.
#. TRANS: %1$s is the method name the exception occured in, %2$s is the actor type.
#, php-format
msgid "Invalid actor passed to %1$s: %2$s."
msgstr "До %1$s передано невірний об’єкт: %2$s."

#. TRANS: Server exception.
msgid ""
"Invalid type passed to Ostatus_profile::notify. It must be XML string or "
"Activity entry."
msgstr ""
"До параметру Ostatus_profile::notify передано невірний тип. Це має бути або "
"рядок у форматі XML, або запис активності."

#. TRANS: Exception.
msgid "Unknown feed format."
msgstr "Невідомий формат веб-стрічки."

#. TRANS: Exception.
msgid "RSS feed without a channel."
msgstr "RSS-стрічка не має каналу."

#. TRANS: Client exception thrown when trying to share multiple activities at once.
msgid "Can only handle share activities with exactly one object."
msgstr ""

#. TRANS: Client exception thrown when trying to share a non-activity object.
msgid "Can only handle shared activities."
msgstr ""

#. TRANS: Client exception thrown when saving an activity share fails.
#. TRANS: %s is a share ID.
#, php-format
msgid "Failed to save activity %s."
msgstr ""

#. TRANS: Client exception. %s is a source URI.
#, php-format
msgid "No content for notice %s."
msgstr "Допис %s не має змісту."

#. TRANS: Shown when a notice is longer than supported and/or when attachments are present. At runtime
#. TRANS: this will usually be replaced with localised text from StatusNet core messages.
msgid "Show more"
msgstr "Розгорнути"

#. TRANS: Exception. %s is a profile URL.
#, php-format
msgid "Could not reach profile page %s."
msgstr "Не вдалося досягти сторінки профілю %s."

#. TRANS: Feed sub exception.
msgid "Cannot find enough profile information to make a feed."
msgstr ""
"Не можу знайти достатньо інформації про профіль, аби сформувати веб-стрічку."

#. TRANS: Server exception.
msgid "No author ID URI found."
msgstr "Не знайдено URI ідентифікатора автора."

#. TRANS: Exception.
msgid "No profile URI."
msgstr "Немає URI профілю."

#. TRANS: Exception.
msgid "Local user cannot be referenced as remote."
msgstr "Місцевий користувач не може бути зазначеним у якості віддаленого."

#. TRANS: Exception.
msgid "Local group cannot be referenced as remote."
msgstr "Локальну спільноту не можна зазначити у якості віддаленої."

#. TRANS: Exception.
msgid "Local list cannot be referenced as remote."
msgstr "Місцевий список не може бути зазначений у якості віддаленого."

#. TRANS: Server exception.
msgid "Cannot save local profile."
msgstr "Не вдається зберегти місцевий профіль."

#. TRANS: Server exception.
msgid "Cannot save local list."
msgstr "Не вдається зберегти місцевий список."

#. TRANS: Server exception.
msgid "Cannot save OStatus profile."
msgstr "Не вдається зберегти профіль OStatus."

#. TRANS: Exception. %s is a webfinger address.
#, php-format
msgid "Could not save profile for \"%s\"."
msgstr "Не можу зберегти профіль для «%s»."

#. TRANS: Exception. %s is a webfinger address.
#, php-format
msgid "Could not save OStatus profile for \"%s\"."
msgstr "Не можу зберегти профіль OStatus для «%s»."

#. TRANS: Server exception.
msgid "Could not store HTML content of long post as file."
msgstr "Не можу зберегти HTML місткого допису у якості файлу."

#. TRANS: Server exception.
#. TRANS: %1$s is a protocol, %2$s is a URI.
#, php-format
msgid "Unrecognized URI protocol for profile: %1$s (%2$s)."
msgstr "Нерозпізнаний URI протоколу для профілю: %1$s (%2$s)."

#. TRANS: Server exception. %s is a URI.
#, php-format
msgid "No URI protocol for profile: %s."
msgstr "Немає URI протоколу для профілю: %s."

#. TRANS: Client exception. %s is a HTTP status code.
#, php-format
msgid "Hub subscriber verification returned HTTP %s."
msgstr "Перевірка вузла підписки завершилася зі статусом HTTP %s."

#. TRANS: Exception. %1$s is a response status code, %2$s is the body of the response.
#, php-format
msgid "Callback returned status: %1$s. Body: %2$s"
msgstr "Зворотній виклик повернуто зі статусом: %1$s. Зміст: %2$s"

#. TRANS: Exception.
msgid "Unable to locate signer public key."
msgstr "Не вдалося знайти публічного ключа підписанта."

#. TRANS: Exception.
msgid "Salmon invalid actor for signing."
msgstr "Недійсний учасник подій за протоколом Salmon для підписання."

#. TRANS: Client error. POST is a HTTP command. It should not be translated.
msgid "This method requires a POST."
msgstr "Цей метод вимагає команди POST."

#. TRANS: Client error. Do not translate "application/magic-envelope+xml".
msgid "Salmon requires \"application/magic-envelope+xml\"."
msgstr "Протокол Salmon вимагає \"application/magic-envelope+xml\"."

#. TRANS: Client error.
msgid "Salmon signature verification failed."
msgstr "Перевірка підпису протоколу Salmon не вдалася."

#. TRANS: Client error.
msgid "Salmon post must be an Atom entry."
msgstr "Дописи за протоколом Salmon мають бути у форматі Atom."

#. TRANS: Client exception.
msgid "Unrecognized activity type."
msgstr "Невідомий тип діяльності."

#. TRANS: Client exception.
msgid "This target does not understand posts."
msgstr "Ціль не розуміє, що таке «дописи»."

#. TRANS: Client exception.
msgid "This target does not understand follows."
msgstr "Ціль не розуміє, що таке «слідувати»."

#. TRANS: Client exception.
msgid "This target does not understand unfollows."
msgstr "Ціль не розуміє, що таке «не слідувати»."

#. TRANS: Client exception.
msgid "This target does not understand favorites."
msgstr "Ціль не розуміє, що таке «додати до обраних»."

#. TRANS: Client exception.
msgid "This target does not understand unfavorites."
msgstr "Ціль не розуміє, що таке «вилучити з обраних»."

#. TRANS: Client exception.
msgid "This target does not understand share events."
msgstr "Ціль не розуміє, що таке «поділитися подією»."

#. TRANS: Client exception.
msgid "This target does not understand joins."
msgstr "Ціль не розуміє, що таке «приєднатися»."

#. TRANS: Client exception.
msgid "This target does not understand leave events."
msgstr "Ціль не розуміє, що таке «залишати подію»."

#. TRANS: Client exception.
#, fuzzy
msgid "This target does not understand list events."
msgstr "!Ціль не розуміє, що таке «позначити подію»."

#. TRANS: Client exception.
#, fuzzy
msgid "This target does not understand unlist events."
msgstr "Ціль не розуміє, що таке «зняти теґ з події»."

#. TRANS: Exception.
msgid "Received a salmon slap from unidentified actor."
msgstr "Отримано ляпаса від невизначеного учасника за протоколом Salmon."


code:
# Translation of StatusNet - OStatus to Simplified Chinese (中文(简体))
# Expored from translatewiki.net
#
# Author: ZhengYiFeng
# --
# This file is distributed under the same license as the StatusNet package.
#
msgid ""
msgstr ""
"Project-Id-Version: StatusNet - OStatus\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-01-15 00:20+0000\n"
"PO-Revision-Date: 2011-01-15 00:24:30+0000\n"
"Language-Team: Simplified Chinese <http://translatewiki.net/wiki/Portal:zh-"
"hans>\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-POT-Import-Date: 2011-01-14 13:21:17+0000\n"
"X-Generator: MediaWiki 1.18alpha (r80364); Translate extension (2010-09-17)\n"
"X-Translation-Project: translatewiki.net at http://translatewiki.net\n"
"X-Language-Code: zh-hans\n"
"X-Message-Group: #out-statusnet-plugin-ostatus\n"
"Plural-Forms: nplurals=1; plural=0;\n"

#. TRANS: Link description for link to subscribe to a remote user.
#. TRANS: Link text for a user to subscribe to an OStatus user.
#: OStatusPlugin.php:223 OStatusPlugin.php:933
msgid "Subscribe"
msgstr "关注"

#. TRANS: Link description for link to join a remote group.
#: OStatusPlugin.php:242 OStatusPlugin.php:651 actions/ostatussub.php:109
msgid "Join"
msgstr "加入"

#. TRANSLATE: %s is a domain.
#: OStatusPlugin.php:455
#, php-format
msgid "Sent from %s via OStatus"
msgstr "从 %s 通过 OStatus 发布"

#. TRANS: Exception.
#: OStatusPlugin.php:527
msgid "Could not set up remote subscription."
msgstr "无法设置远程关注。"

#: OStatusPlugin.php:601
msgid "Unfollow"
msgstr "取消关注"

#. TRANS: Success message for unsubscribe from user attempt through OStatus.
#. TRANS: %1$s is the unsubscriber's name, %2$s is the unsubscribed user's name.
#: OStatusPlugin.php:604
#, php-format
msgid "%1$s stopped following %2$s."
msgstr "%1$s 取消了对 %2$s 的关注。"

#: OStatusPlugin.php:632
msgid "Could not set up remote group membership."
msgstr "无法设置远程的小组成员。"

#. TRANS: Success message for subscribe to group attempt through OStatus.
#. TRANS: %1$s is the member name, %2$s is the subscribed group's name.
#: OStatusPlugin.php:654
#, php-format
msgid "%1$s has joined group %2$s."
msgstr ""

#. TRANS: Exception.
#: OStatusPlugin.php:663
msgid "Failed joining remote group."
msgstr "加入远程小组失败。"

#: OStatusPlugin.php:703
msgid "Leave"
msgstr "离开"

#. TRANS: Success message for unsubscribe from group attempt through OStatus.
#. TRANS: %1$s is the member name, %2$s is the unsubscribed group's name.
#: OStatusPlugin.php:706
#, php-format
msgid "%1$s has left group %2$s."
msgstr ""

#: OStatusPlugin.php:781
msgid "Disfavor"
msgstr "取消收藏"

#. TRANS: Success message for remove a favorite notice through OStatus.
#. TRANS: %1$s is the unfavoring user's name, %2$s is URI to the no longer favored notice.
#: OStatusPlugin.php:784
#, php-format
msgid "%1$s marked notice %2$s as no longer a favorite."
msgstr "%1$s 将消息 %2$s 取消了收藏。"

#. TRANS: Link text for link to remote subscribe.
#: OStatusPlugin.php:860
msgid "Remote"
msgstr "远程"

#. TRANS: Title for activity.
#: OStatusPlugin.php:900
msgid "Profile update"
msgstr "个人信息更新"

#. TRANS: Ping text for remote profile update through OStatus.
#. TRANS: %s is user that updated their profile.
#: OStatusPlugin.php:903
#, php-format
msgid "%s has updated their profile page."
msgstr "%s 更新了他/她的个人信息页。"

#. TRANS: Plugin description.
#: OStatusPlugin.php:948
msgid ""
"Follow people across social networks that implement OStatus."
msgstr ""

#: classes/FeedSub.php:252
msgid "Attempting to start PuSH subscription for feed with no hub."
msgstr ""

#: classes/FeedSub.php:282
msgid "Attempting to end PuSH subscription for feed with no hub."
msgstr ""

#. TRANS: Server exception. %s is a URI.
#: classes/Ostatus_profile.php:192
#, php-format
msgid "Invalid ostatus_profile state: both group and profile IDs set for %s."
msgstr ""

#. TRANS: Server exception. %s is a URI.
#: classes/Ostatus_profile.php:195
#, php-format
msgid "Invalid ostatus_profile state: both group and profile IDs empty for %s."
msgstr ""

#. TRANS: Server exception.
#. TRANS: %1$s is the method name the exception occured in, %2$s is the actor type.
#: classes/Ostatus_profile.php:285
#, php-format
msgid "Invalid actor passed to %1$s: %2$s."
msgstr ""

#. TRANS: Server exception.
#: classes/Ostatus_profile.php:378
msgid ""
"Invalid type passed to Ostatus_profile::notify. It must be XML string or "
"Activity entry."
msgstr ""

#. TRANS: Exception.
#: classes/Ostatus_profile.php:409
msgid "Unknown feed format."
msgstr ""

#. TRANS: Exception.
#: classes/Ostatus_profile.php:433
msgid "RSS feed without a channel."
msgstr ""

#. TRANS: Client exception.
#: classes/Ostatus_profile.php:479
msgid "Can't handle that kind of post."
msgstr ""

#. TRANS: Client exception. %s is a source URI.
#: classes/Ostatus_profile.php:537
#, php-format
msgid "No content for notice %s."
msgstr ""

#. TRANS: Shown when a notice is longer than supported and/or when attachments are present. At runtime
#. TRANS: this will usually be replaced with localised text from StatusNet core messages.
#: classes/Ostatus_profile.php:572
msgid "Show more"
msgstr ""

#. TRANS: Exception. %s is a profile URL.
#: classes/Ostatus_profile.php:765
#, php-format
msgid "Could not reach profile page %s."
msgstr ""

#. TRANS: Exception. %s is a URL.
#: classes/Ostatus_profile.php:823
#, php-format
msgid "Could not find a feed URL for profile page %s."
msgstr ""

#. TRANS: Feed sub exception.
#: classes/Ostatus_profile.php:922
msgid "Can't find enough profile information to make a feed."
msgstr ""

#. TRANS: Server exception. %s is a URL.
#: classes/Ostatus_profile.php:986
#, php-format
msgid "Invalid avatar URL %s."
msgstr ""

#. TRANS: Server exception. %s is a URI.
#: classes/Ostatus_profile.php:997
#, php-format
msgid "Tried to update avatar for unsaved remote profile %s."
msgstr ""

#. TRANS: Server exception. %s is a URL.
#: classes/Ostatus_profile.php:1007
#, php-format
msgid "Unable to fetch avatar from %s."
msgstr ""

#. TRANS: Exception.
#: classes/Ostatus_profile.php:1233
msgid "Local user can't be referenced as remote."
msgstr ""

#. TRANS: Exception.
#: classes/Ostatus_profile.php:1238
msgid "Local group can't be referenced as remote."
msgstr ""

#. TRANS: Server exception.
#: classes/Ostatus_profile.php:1290 classes/Ostatus_profile.php:1301
msgid "Can't save local profile."
msgstr ""

#. TRANS: Server exception.
#: classes/Ostatus_profile.php:1309
msgid "Can't save OStatus profile."
msgstr ""

#. TRANS: Exception.
#: classes/Ostatus_profile.php:1573 classes/Ostatus_profile.php:1601
msgid "Not a valid webfinger address."
msgstr ""

#. TRANS: Exception. %s is a webfinger address.
#: classes/Ostatus_profile.php:1683
#, php-format
msgid "Couldn't save profile for \"%s\"."
msgstr ""

#. TRANS: Exception. %s is a webfinger address.
#: classes/Ostatus_profile.php:1702
#, php-format
msgid "Couldn't save ostatus_profile for \"%s\"."
msgstr ""

#. TRANS: Exception. %s is a webfinger address.
#: classes/Ostatus_profile.php:1710
#, php-format
msgid "Couldn't find a valid profile for \"%s\"."
msgstr ""

#. TRANS: Server exception.
#: classes/Ostatus_profile.php:1753
msgid "Could not store HTML content of long post as file."
msgstr ""

#. TRANS: Client exception. %s is a HTTP status code.
#: classes/HubSub.php:212
#, php-format
msgid "Hub subscriber verification returned HTTP %s."
msgstr ""

#. TRANS: Exception. %1$s is a response status code, %2$s is the body of the response.
#: classes/HubSub.php:359
#, php-format
msgid "Callback returned status: %1$s. Body: %2$s"
msgstr ""

#. TRANS: Client error. POST is a HTTP command. It should not be translated.
#: lib/salmonaction.php:43
msgid "This method requires a POST."
msgstr ""

#. TRANS: Client error. Do not translate "application/magic-envelope+xml"
#: lib/salmonaction.php:48
msgid "Salmon requires \"application/magic-envelope+xml\"."
msgstr ""

#. TRANS: Client error.
#: lib/salmonaction.php:58
msgid "Salmon signature verification failed."
msgstr ""

#. TRANS: Client error.
#: lib/salmonaction.php:70
msgid "Salmon post must be an Atom entry."
msgstr ""

#. TRANS: Client exception.
#: lib/salmonaction.php:120
msgid "Unrecognized activity type."
msgstr ""

#. TRANS: Client exception.
#: lib/salmonaction.php:130
msgid "This target doesn't understand posts."
msgstr ""

#. TRANS: Client exception.
#: lib/salmonaction.php:136
msgid "This target doesn't understand follows."
msgstr ""

#. TRANS: Client exception.
#: lib/salmonaction.php:142
msgid "This target doesn't understand unfollows."
msgstr ""

#. TRANS: Client exception.
#: lib/salmonaction.php:148
msgid "This target doesn't understand favorites."
msgstr ""

#. TRANS: Client exception.
#: lib/salmonaction.php:154
msgid "This target doesn't understand unfavorites."
msgstr ""

#. TRANS: Client exception.
#: lib/salmonaction.php:160
msgid "This target doesn't understand share events."
msgstr ""

#. TRANS: Client exception.
#: lib/salmonaction.php:166
msgid "This target doesn't understand joins."
msgstr ""

#. TRANS: Client exception.
#: lib/salmonaction.php:172
msgid "This target doesn't understand leave events."
msgstr ""

#. TRANS: Exception.
#: lib/salmonaction.php:200
msgid "Received a salmon slap from unidentified actor."
msgstr ""

#. TRANS: Exception.
#: lib/discovery.php:110
#, php-format
msgid "Unable to find services for %s."
msgstr ""

#. TRANS: Exception.
#: lib/magicenvelope.php:80
msgid "Unable to locate signer public key."
msgstr ""

#. TRANS: Exception.
#: lib/salmon.php:93
msgid "Salmon invalid actor for signing."
msgstr ""

#: tests/gettext-speedtest.php:57
msgid "Feeds"
msgstr ""

#. TRANS: Client exception.
#: actions/pushhub.php:70
msgid "Publishing outside feeds not supported."
msgstr ""

#. TRANS: Client exception. %s is a mode.
#: actions/pushhub.php:73
#, php-format
msgid "Unrecognized mode \"%s\"."
msgstr ""

#. TRANS: Client exception. %s is a topic.
#: actions/pushhub.php:93
#, php-format
msgid ""
"Unsupported hub.topic %s this hub only serves local user and group Atom "
"feeds."
msgstr ""

#. TRANS: Client exception.
#: actions/pushhub.php:99
#, php-format
msgid "Invalid hub.verify \"%s\". It must be sync or async."
msgstr ""

#. TRANS: Client exception.
#: actions/pushhub.php:105
#, php-format
msgid "Invalid hub.lease \"%s\". It must be empty or positive integer."
msgstr ""

#. TRANS: Client exception.
#: actions/pushhub.php:113
#, php-format
msgid "Invalid hub.secret \"%s\". It must be under 200 bytes."
msgstr ""

#. TRANS: Client exception.
#: actions/pushhub.php:165
#, php-format
msgid "Invalid hub.topic \"%s\". User doesn't exist."
msgstr ""

#. TRANS: Client exception.
#: actions/pushhub.php:174
#, php-format
msgid "Invalid hub.topic \"%s\". Group doesn't exist."
msgstr ""

#. TRANS: Client exception.
#. TRANS: %1$s is this argument to the method this exception occurs in, %2$s is a URL.
#: actions/pushhub.php:199
#, php-format
msgid "Invalid URL passed for %1$s: \"%2$s\""
msgstr ""

#: actions/ownerxrd.php:39 actions/usersalmon.php:43
msgid "No such user."
msgstr ""

#. TRANS: Client error.
#: actions/usersalmon.php:37 actions/groupsalmon.php:40
msgid "No ID."
msgstr ""

#. TRANS: Client exception.
#: actions/usersalmon.php:83
msgid "In reply to unknown notice."
msgstr ""

#. TRANS: Client exception.
#: actions/usersalmon.php:88
msgid "In reply to a notice not by this user and not mentioning this user."
msgstr ""

#. TRANS: Client exception.
#: actions/usersalmon.php:165
msgid "Could not save new favorite."
msgstr ""

#. TRANS: Client exception.
#: actions/usersalmon.php:197
msgid "Can't favorite/unfavorite without an object."
msgstr ""

#. TRANS: Client exception.
#: actions/usersalmon.php:209
msgid "Can't handle that kind of object for liking/faving."
msgstr ""

#. TRANS: Client exception. %s is an object ID.
#: actions/usersalmon.php:216
#, php-format
msgid "Notice with ID %s unknown."
msgstr ""

#. TRANS: Client exception. %1$s is a notice ID, %2$s is a user ID.
#: actions/usersalmon.php:221
#, php-format
msgid "Notice with ID %1$s not posted by %2$s."
msgstr ""

#. TRANS: Field label.
#: actions/ostatusgroup.php:78
msgid "Join group"
msgstr "加入小组"

#. TRANS: Tooltip for field label "Join group".
#: actions/ostatusgroup.php:81
msgid "OStatus group's address, like http://example.net/group/nickname."
msgstr "OStatus 小组的地址，例如 http://example.net/group/nickname。"

#. TRANS: Button text.
#: actions/ostatusgroup.php:86 actions/ostatussub.php:75
msgctxt "BUTTON"
msgid "Continue"
msgstr "继续"

#: actions/ostatusgroup.php:105
msgid "You are already a member of this group."
msgstr "你已经是该小组成员。"

#. TRANS: OStatus remote group subscription dialog error.
#: actions/ostatusgroup.php:140
msgid "Already a member!"
msgstr "已经是成员了！"

#. TRANS: OStatus remote group subscription dialog error.
#: actions/ostatusgroup.php:151
msgid "Remote group join failed!"
msgstr "加入远程小组失败！"

#. TRANS: OStatus remote group subscription dialog error.
#: actions/ostatusgroup.php:155
msgid "Remote group join aborted!"
msgstr "加入远程小组取消！"

#. TRANS: Page title for OStatus remote group join form
#: actions/ostatusgroup.php:167
msgid "Confirm joining remote group"
msgstr "确认加入远程小组"

#. TRANS: Instructions.
#: actions/ostatusgroup.php:178
msgid ""
"You can subscribe to groups from other supported sites. Paste the group's "
"profile URI below:"
msgstr ""

#. TRANS: Client error.
#: actions/groupsalmon.php:47
msgid "No such group."
msgstr ""

#. TRANS: Client error.
#: actions/groupsalmon.php:56
msgid "Can't accept remote posts for a remote group."
msgstr ""

#. TRANS: Client error.
#: actions/groupsalmon.php:130
msgid "Can't read profile to set up group membership."
msgstr ""

#. TRANS: Client error.
#: actions/groupsalmon.php:134 actions/groupsalmon.php:177
msgid "Groups can't join groups."
msgstr ""

#: actions/groupsalmon.php:147
msgid "You have been blocked from that group by the admin."
msgstr ""

#. TRANS: Server error. %1$s is a profile URI, %2$s is a group nickname.
#: actions/groupsalmon.php:162
#, php-format
msgid "Could not join remote user %1$s to group %2$s."
msgstr ""

#: actions/groupsalmon.php:174
msgid "Can't read profile to cancel group membership."
msgstr ""

#. TRANS: Server error. %1$s is a profile URI, %2$s is a group nickname.
#: actions/groupsalmon.php:191
#, php-format
msgid "Could not remove remote user %1$s from group %2$s."
msgstr ""

#. TRANS: Field label for a field that takes an OStatus user address.
#: actions/ostatussub.php:68
msgid "Subscribe to"
msgstr ""

#. TRANS: Tooltip for field label "Subscribe to".
#: actions/ostatussub.php:71
msgid ""
"OStatus user's address, like nickname@example.com or http://example.net/"
"nickname"
msgstr ""
"OStatus 用户的地址，例如 nickname@example.com 或 http://example.net/nickname"

#. TRANS: Button text.
#. TRANS: Tooltip for button "Join".
#: actions/ostatussub.php:112
msgctxt "BUTTON"
msgid "Join this group"
msgstr ""

#. TRANS: Button text.
#: actions/ostatussub.php:115
msgctxt "BUTTON"
msgid "Confirm"
msgstr ""

#. TRANS: Tooltip for button "Confirm".
#: actions/ostatussub.php:117
msgid "Subscribe to this user"
msgstr ""

#: actions/ostatussub.php:138
msgid "You are already subscribed to this user."
msgstr ""

#: actions/ostatussub.php:167
msgid "Photo"
msgstr ""

#: actions/ostatussub.php:178
msgid "Nickname"
msgstr ""

#: actions/ostatussub.php:199
msgid "Location"
msgstr ""

#: actions/ostatussub.php:208
msgid "URL"
msgstr ""

#: actions/ostatussub.php:220
msgid "Note"
msgstr ""

#. TRANS: Error text.
#: actions/ostatussub.php:256 actions/ostatussub.php:263
#: actions/ostatussub.php:288
msgid ""
"Sorry, we could not reach that address. Please make sure that the OStatus "
"address is like nickname@example.com or http://example.net/nickname."
msgstr ""

#. TRANS: Error text.
#: actions/ostatussub.php:267 actions/ostatussub.php:271
#: actions/ostatussub.php:275 actions/ostatussub.php:279
#: actions/ostatussub.php:283
msgid ""
"Sorry, we could not reach that feed. Please try that OStatus address again "
"later."
msgstr ""

#. TRANS: OStatus remote subscription dialog error.
#: actions/ostatussub.php:317
msgid "Already subscribed!"
msgstr ""

#. TRANS: OStatus remote subscription dialog error.
#: actions/ostatussub.php:322
msgid "Remote subscription failed!"
msgstr ""

#: actions/ostatussub.php:369 actions/ostatusinit.php:64
msgid "There was a problem with your session token. Try again, please."
msgstr ""

#. TRANS: Form title.
#: actions/ostatussub.php:397 actions/ostatusinit.php:83
msgid "Subscribe to user"
msgstr ""

#. TRANS: Page title for OStatus remote subscription form
#: actions/ostatussub.php:417
msgid "Confirm"
msgstr ""

#. TRANS: Instructions.
#: actions/ostatussub.php:429
msgid ""
"You can subscribe to users from other supported sites. Paste their address "
"or profile URI below:"
msgstr ""

#. TRANS: Client error.
#: actions/ostatusinit.php:42
msgid "You can use the local subscription!"
msgstr ""

#. TRANS: Form legend.
#: actions/ostatusinit.php:98
#, php-format
msgid "Join group %s"
msgstr ""

#. TRANS: Button text.
#: actions/ostatusinit.php:100
msgctxt "BUTTON"
msgid "Join"
msgstr ""

#. TRANS: Form legend.
#: actions/ostatusinit.php:103
#, php-format
msgid "Subscribe to %s"
msgstr ""

#. TRANS: Button text.
#: actions/ostatusinit.php:105
msgctxt "BUTTON"
msgid "Subscribe"
msgstr ""

#. TRANS: Field label.
#: actions/ostatusinit.php:118
msgid "User nickname"
msgstr ""

#: actions/ostatusinit.php:119
msgid "Nickname of the user you want to follow."
msgstr ""

#. TRANS: Field label.
#: actions/ostatusinit.php:124
msgid "Profile Account"
msgstr ""

#. TRANS: Tooltip for field label "Profile Account".
#: actions/ostatusinit.php:126
msgid "Your account id (e.g. user@identi.ca)."
msgstr ""

#. TRANS: Client error.
#: actions/ostatusinit.php:148
msgid "Must provide a remote profile."
msgstr ""

#. TRANS: Client error.
#: actions/ostatusinit.php:160
msgid "Couldn't look up OStatus account profile."
msgstr ""

#. TRANS: Client error.
#: actions/ostatusinit.php:173
msgid "Couldn't confirm remote profile address."
msgstr ""

#. TRANS: Page title.
#: actions/ostatusinit.php:218
msgid "OStatus Connect"
msgstr ""

#: actions/pushcallback.php:50
msgid "Empty or invalid feed id."
msgstr ""

#. TRANS: Server exception. %s is a feed ID.
#: actions/pushcallback.php:56
#, php-format
msgid "Unknown PuSH feed id %s"
msgstr ""

#. TRANS: Client exception. %s is an invalid feed name.
#: actions/pushcallback.php:96
#, php-format
msgid "Bad hub.topic feed \"%s\"."
msgstr ""

#. TRANS: Client exception. %1$s the invalid token, %2$s is the topic for which the invalid token was given.
#: actions/pushcallback.php:101
#, php-format
msgid "Bad hub.verify_token %1$s for %2$s."
msgstr ""

#. TRANS: Client exception. %s is an invalid topic.
#: actions/pushcallback.php:108
#, php-format
msgid "Unexpected subscribe request for %s."
msgstr ""

#. TRANS: Client exception. %s is an invalid topic.
#: actions/pushcallback.php:113
#, php-format
msgid "Unexpected unsubscribe request for %s."
msgstr ""

license: mit


code:
#!/usr/bin/env php
<?php
/*
 * StatusNet - a 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/>.
 */

define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..'));

$longoptions = array('dry-run');

$helptext = <<<END_OF_USERROLE_HELP
fixup_shadow.php [options]
Patches up stray ostatus_profile entries with corrupted shadow entries
for local users and groups.

     --dry-run  look but don't touch

END_OF_USERROLE_HELP;

require_once INSTALLDIR.'/scripts/commandline.inc';

$dry = have_option('dry-run');

// Look for user.uri matches... These may not match up with the current
// URL schema if the site has changed names.
echo "Checking for bogus ostatus_profile entries matching user.uri...\n";

$user = new User();
$oprofile = new Ostatus_profile();
$user->joinAdd($oprofile, 'INNER', 'oprofile', 'uri');
$user->find();
$count = $user->N;
echo "Found $count...\n";

while ($user->fetch()) {
    $uri = $user->getUri();
    echo "user $user->id ($user->nickname) hidden by $uri";
    if ($dry) {
        echo " - skipping\n";
    } else {
        echo " - removing bogus ostatus_profile entry...";
        $evil = Ostatus_profile::getKV('uri', $uri);
        $evil->delete();
        echo "  ok\n";
    }
}
echo "\n";

// Also try user_group.uri matches for local groups.
// Not all group entries will have this filled out, though, as it's new!
echo "Checking for bogus ostatus_profile entries matching local user_group.uri...\n";
$group = new User_group();
$group->joinAdd(array('uri', 'ostatus_profile:uri'));
$group->joinAdd(array('id', 'local_group:group_id'));
$group->find();
$count = $group->N;
echo "Found $count...\n";

while ($group->fetch()) {
    $uri = $group->getUri();
    echo "group $group->id ($group->nickname) hidden by $uri";
    if ($dry) {
        echo " - skipping\n";
    } else {
        echo " - removing bogus ostatus_profile entry...";
        $evil = Ostatus_profile::getKV('uri', $uri);
        $evil->delete();
        echo "  ok\n";
    }
}
echo "\n";

// And there may be user_group entries remaining where we've already killed
// the ostatus_profile. These were "harmless" until our lookup started actually
// using the uri field, at which point we can clearly see it breaks stuff.
echo "Checking for leftover bogus user_group.uri entries obscuring local_group entries...\n";

$group = new User_group();
$group->joinAdd(array('id', 'local_group:group_id'), 'LEFT');
$group->whereAdd('group_id IS NULL');

$marker = mt_rand(31337, 31337000);
$groupTemplate = common_local_url('groupbyid', array('id' => $marker));
$encGroup = $group->escape($groupTemplate, true);
$encGroup = str_replace($marker, '%', $encGroup);
echo "  LIKE '$encGroup'\n";
$group->whereAdd("uri LIKE '$encGroup'");

$group->find();
$count = $group->N;
echo "Found $count...\n";

while ($group->fetch()) {
    $uri = $group->getUri();
    if (preg_match('!/group/(\d+)/id!', $uri, $matches)) {
        $id = intval($matches[1]);
        $local = Local_group::getKV('group_id', $id);
        if ($local) {
            $nick = $local->nickname;
        } else {
            $nick = '<deleted>';
        }
        echo "local group $id ($local->nickname) hidden by $uri (bogus group id $group->id)";
        if ($dry) {
            echo " - skipping\n";
        } else {
            echo " - removing bogus user_group entry...";
            $evil = User_group::getKV('id', $group->id);
            $evil->delete();
            echo "  ok\n";
        }
    }
}
echo "\n";

// Fallback?
echo "Checking for bogus profiles blocking local users/groups by URI pattern match...\n";
$oprofile = new Ostatus_profile();

$marker = mt_rand(31337, 31337000);

$profileTemplate = common_local_url('userbyid', array('id' => $marker));
$encProfile = $oprofile->escape($profileTemplate, true);
$encProfile = str_replace($marker, '%', $encProfile);
echo "  LIKE '$encProfile'\n";

$groupTemplate = common_local_url('groupbyid', array('id' => $marker));
$encGroup = $oprofile->escape($groupTemplate, true);
$encGroup = str_replace($marker, '%', $encGroup);
echo "  LIKE '$encGroup'\n";

$sql = "SELECT * FROM ostatus_profile WHERE uri LIKE '%s' OR uri LIKE '%s'";
$oprofile->query(sprintf($sql, $encProfile, $encGroup));

$count = $oprofile->N;
echo "Found $count...\n";

while ($oprofile->fetch()) {
    $uri = $oprofile->getUri();
    if (preg_match('!/group/(\d+)/id!', $oprofile->getUri(), $matches)) {
        $id = intval($matches[1]);
        $group = Local_group::getKV('group_id', $id);
        if ($group) {
            $nick = $group->nickname;
        } else {
            $nick = '<deleted>';
        }
        echo "group $id ($nick) hidden by $uri";
    } else if (preg_match('!/user/(\d+)!', $uri, $matches)) {
        $id = intval($matches[1]);
        $user = User::getKV('id', $id);
        if ($user) {
            $nick = $user->nickname;
        } else {
            $nick = '<deleted>';
        }
        echo "user $id ($nick) hidden by $uri";
    } else {
        echo "$uri matched query, but we don't recognize it.\n";
        continue;
    }

    if ($dry) {
        echo " - skipping\n";
    } else {
        echo " - removing bogus ostatus_profile entry...";
        $evil = clone($oprofile);
        $evil->delete();
        echo "  ok\n";
    }
}

if ($count && $dry) {
    echo "NO CHANGES MADE -- To delete the bogus entries, run again without --dry-run option.\n";
} else {
    echo "done.\n";
}


code:
#!/usr/bin/env php
<?php
/*
 * StatusNet - a 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/>.
 */

define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..'));

$longoptions = array('delete-inactive');
$shortoptions = 'd';

$helptext = <<<END_OF_HELP
gcfeeds.php [options]
Clean up feeds that no longer have subscribers.

    -d --delete-inactive    Delete inactive feeds from feedsub table.

END_OF_HELP;

require_once INSTALLDIR.'/scripts/commandline.inc';

$delete_inactive = have_option('d', 'delete-inactive');
$delcount = 0;

$feedsub = new FeedSub();
$feedsub->find();
while ($feedsub->fetch()) {
    try {
        echo $feedsub->getUri() . " ({$feedsub->sub_state})";
        if ($feedsub->garbageCollect()) {
            if ($delete_inactive) {
                $delcount++;
                $feedsub->delete();
                echo " DELETED";
            }
            echo " INACTIVE\n";
        } else {
            echo " ACTIVE\n";
        }
    } catch (NoProfileException $e) {
        echo " DELETED (no profile)\n";
        $feedsub->delete();
        continue;
    } catch (NoUriException $e) {
        // Probably the getUri() call
        echo "[unknown] DELETED (no uri)\n";
        $feedsub->delete();
        continue;
    } catch (Exception $e) {
        echo " ERROR: {$e->getMessage()}\n";
    }
}

if ($delete_inactive) echo "\nDeleted $delcount inactive feeds.\n";


code:
#!/usr/bin/env php
<?php
/*
 * StatusNet - a 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/>.
 */

define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..'));

$helptext = <<<END_OF_HELP
resub-feed.php
Resubscribe to any soon expiring feeds. Default time to expiration is 1 day.

END_OF_HELP;

require_once INSTALLDIR.'/scripts/commandline.inc';

try {
    $sub = FeedSub::renewalCheck();
} catch (NoResultException $e) {
    echo 'There were no expiring feeds.';
    exit;
}

while ($sub->fetch()) {
    echo "Renewing feed subscription\n\tExp.: {$sub->sub_end}\n\tFeed: {$sub->uri}\n\tHub:  {$sub->huburi}\n";
    $sub->renew();
}

echo "Done!";


code:
#!/usr/bin/env php
<?php
/*
 * StatusNet - a 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/>.
 */

define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..'));

$longoptions = array('unsub');
$shortoptions = 'u';

$helptext = <<<END_OF_HELP
resub-feed.php [options] http://example.com/atom-feed-url
Reinitialize the PuSH subscription for the given feed. This may help get
things restarted if we and the hub have gotten our states out of sync.

Options:

   -u --unsub  Unsubscribe instead of subscribing.

END_OF_HELP;

require_once INSTALLDIR.'/scripts/commandline.inc';

if (empty($args[0]) || !Validate::uri($args[0])) {
    print "$helptext";
    exit(1);
}

$feedurl = $args[0];

$sub = FeedSub::getKV('uri', $feedurl);
if (!$sub) {
    print "Feed $feedurl is not subscribed.\n";
    exit(1);
}

print "Old state:\n";
showSub($sub);

try {
    echo "\n";
    if (have_option('u') || have_option('--unsub')) {
        echo "Pinging hub {$sub->huburi} with unsubscription for {$sub->uri}\n";
        $sub->unsubscribe();
    } else {
        echo "Pinging hub {$sub->huburi} with new subscription for {$sub->uri}\n";
        $sub->subscribe();
    }
    echo "ok\n";
} catch (Exception $e) {
    echo 'Could not confirm. '.get_class($e).': '.$e->getMessage()."\n";
}

$sub2 = FeedSub::getKV('uri', $feedurl);

print "\n";
print "New state:\n";
showSub($sub2);

function showSub($sub)
{
    print "  Subscription state: $sub->sub_state\n";
    print "  Verify token: $sub->verify_token\n";
    print "  Signature secret: $sub->secret\n";
    print "  Sub start date: $sub->sub_start\n";
    print "  Record created: $sub->created\n";
    print "  Record modified: $sub->modified\n";
}


code:
#!/usr/bin/env php
<?php
/*
 * StatusNet - a 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/>.
 */

/*
 *  Run this from INSTALLDIR/plugins/OStatus/scripts
 */

define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..'));

$shortoptions = 'd';
$longoptions = array('dry-run');

$helptext = <<<END_OF_HELP
rm_bad_feedsubs.php [options]
Deletes feedsub records that are in the inconsistent state of "subscribe"
and are older than one hour. If the hub hasn't answered back in an hour
the hub is probably either broken or doesn't exist.'

      Options:

    -d --dry-run look but don't mess with it

END_OF_HELP;

require_once INSTALLDIR . '/scripts/commandline.inc';

$dry = false;

if (have_option('d') || have_option('dry-run')) {
    $dry = true;
}

echo "Looking for feed subscriptions with dirty no good huburis...\n";

$feedsub = new FeedSub();
$feedsub->sub_state = 'subscribe';
$feedsub->whereAdd('created < DATE_SUB(NOW(), INTERVAL 1 HOUR)');
$feedsub->find();
$cnt = 0;

while ($feedsub->fetch()) {
    echo "----------------------------------------------------------------------------------------\n";
    echo  '           feed: '
        . $feedsub->uri . "\n"
        . '        hub uri: '
        . $feedsub->huburi ."\n"
        . ' subscribe date: '
        . date('r', strtotime($feedsub->created)) . "\n";

    if (!$dry) {
        $feedsub->delete();
        echo "                 (DELETED)\n";
    } else {
        echo "                 (WOULD BE DELETED)\n";
    }
    echo "----------------------------------------------------------------------------------------\n";
    $cnt++;
}
if ($cnt == 0) {
    echo "None found.\n";
} else {
    echo "Deleted $cnt bogus hub URIs.\n";
}
echo "Done.\n";


code:
#!/usr/bin/env php
<?php
/*
 * StatusNet - a 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/>.
 */

define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..'));

$longoptions = array('skip=', 'count=');

$helptext = <<<END_OF_HELP
testfeed.php [options] http://example.com/atom-feed-url
Pull an Atom feed and run items in it as though they were live PuSH updates.
Mainly intended for testing funky feed formats.

     --skip=N   Ignore the first N items in the feed.
     --count=N  Only process up to N items from the feed, after skipping.

END_OF_HELP;

require_once INSTALLDIR.'/scripts/commandline.inc';

if (empty($args[0]) || !Validate::uri($args[0])) {
    print "$helptext";
    exit(1);
}

$feedurl = $args[0];
$skip = have_option('skip') ? intval(get_option_value('skip')) : 0;
$count = have_option('count') ? intval(get_option_value('count')) : 0;

$sub = FeedSub::getKV('uri', $feedurl);
if (!$sub) {
    print "Feed $feedurl is not subscribed.\n";
    exit(1);
}

// Fetch the URL
try {
    $xml = HTTPClient::quickGet($feedurl, 'text/html,application/xhtml+xml');
} catch (Exception $e) {
    echo sprintf("Could not fetch feedurl %s (%d).\n", $e->getMessage(), $e->getCode());
    exit(1);
}

$feed = new DOMDocument();
if (!$feed->loadXML($xml)) {
    print "Bad XML.\n";
    exit(1);
}

if ($skip || $count) {
    $entries = $feed->getElementsByTagNameNS(ActivityUtils::ATOM, 'entry');
    $remove = array();
    for ($i = 0; $i < $skip && $i < $entries->length; $i++) {
        $item = $entries->item($i);
        if ($item) {
            $remove[] = $item;
        }
    }
    if ($count) {
        for ($i = $skip + $count; $i < $entries->length; $i++) {
            $item = $entries->item($i);
            if ($item) {
                $remove[] = $item;
            }
        }
    }
    foreach ($remove as $item) {
        $item->parentNode->removeChild($item);
    }
}

echo "Calling event StartFeedSubReceive\n";
Event::handle('StartFeedSubReceive', array($sub, $feed));


code:
#!/usr/bin/env php
<?php
/*
 * StatusNet - a 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/>.
 */

define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..'));

$longoptions = array('all', 'suspicious', 'quiet');

$helptext = <<<END_OF_HELP
update-profile-data.php [options] [http://example.com/profile/url]

Rerun profile discovery for the given OStatus remote profile, and save the
updated profile data (nickname, fullname, avatar, bio, etc).
Doesn't touch feed state.
Can be used to clean up after breakages.

Options:
  --all        Run for all known OStatus profiles
  --suspicious Run for OStatus profiles with all-numeric nicknames
               (fixes 0.9.7 prerelease back-compatibility bug)

END_OF_HELP;

require_once INSTALLDIR.'/scripts/commandline.inc';

function showProfileInfo(Ostatus_profile $oprofile) {
    if ($oprofile->isGroup()) {
        echo "group\n";
    } else {
        $profile = $oprofile->localProfile();
        try {
            foreach (array('nickname', 'fullname', 'bio', 'homepage', 'location') as $field) {
                print "  $field: {$profile->$field}\n";
            }
        } catch (NoProfileException $e) {
            print "local profile not found";
        }
    }
    echo "\n";
}

function fixProfile($uri) {
    $oprofile = Ostatus_profile::getKV('uri', $uri);

    if (!$oprofile) {
        print "No OStatus remote profile known for URI $uri\n";
        return false;
    }

    echo "Before:\n";
    showProfileInfo($oprofile);

    $feedurl = $oprofile->feeduri;
    $client = new HttpClient();
    $response = $client->get($feedurl);
    if ($response->isOk()) {
        echo "Updating profile from feed: $feedurl\n";
        $dom = new DOMDocument();
        if ($dom->loadXML($response->getBody())) {
            $feed = $dom->documentElement;
            $entries = $dom->getElementsByTagNameNS(Activity::ATOM, 'entry');
            if ($entries->length) {
                $entry = $entries->item(0);
                $activity = new Activity($entry, $feed);
                $oprofile->checkAuthorship($activity);
                echo "  (ok)\n";
            } else {
                echo "  (no entry; skipping)\n";
                return false;
            }
        } else {
            echo "  (bad feed; skipping)\n";
            return false;
        }
    } else {
        echo "Failed feed fetch: {$response->getStatus()} for $feedurl\n";
        return false;
    }

    echo "After:\n";
    showProfileInfo($oprofile);
    return true;
}

$ok = true;
if (have_option('all')) {
    $oprofile = new Ostatus_profile();
    $oprofile->find();
    echo "Found $oprofile->N profiles:\n\n";
    while ($oprofile->fetch()) {
        $ok = fixProfile($oprofile->uri) && $ok;
    }
} else if (have_option('suspicious')) {
    $oprofile = new Ostatus_profile();
    $oprofile->joinAdd(array('profile_id', 'profile:id'));
    $oprofile->whereAdd("nickname rlike '^[0-9]$'");
    $oprofile->find();
    echo "Found $oprofile->N matching profiles:\n\n";
    while ($oprofile->fetch()) {
        $ok = fixProfile($oprofile->uri) && $ok;
    }
} else if (!empty($args[0]) && Validate::uri($args[0])) {
    $uri = $args[0];
    $ok = fixProfile($uri);
} else {
    print "$helptext";
    $ok = false;
}

exit($ok ? 0 : 1);


code:
#!/usr/bin/env php
<?php
/*
 * StatusNet - a 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/>.
 */

define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..'));

$helptext = <<<END_OF_HELP
update-profile.php [options] http://example.com/profile/url

Rerun profile and feed info discovery for the given OStatus remote profile,
and reinitialize its PuSH subscription for the given feed. This may help get
things restarted if the hub or feed URLs have changed for the profile.

END_OF_HELP;

require_once INSTALLDIR.'/scripts/commandline.inc';

if (empty($args[0]) || !Validate::uri($args[0])) {
    print "$helptext";
    exit(1);
}

$uri = $args[0];

$oprofile = Ostatus_profile::getKV('uri', $uri);

if (!$oprofile) {
    print "No OStatus remote profile known for URI $uri\n";
    exit(1);
}

print "Old profile state for $oprofile->uri\n";
showProfile($oprofile);

print "\n";
print "Re-running feed discovery for profile URL $oprofile->uri\n";
// @fixme will bork where the URI isn't the profile URL for now
$discover = new FeedDiscovery();
$feedurl = $discover->discoverFromURL($oprofile->uri);
$huburi = $discover->getHubLink();
$salmonuri = $discover->getAtomLink(Salmon::REL_SALMON)
                ?: $discover->getAtomLink(Salmon::NS_REPLIES);

print "  Feed URL: $feedurl\n";
print "  Hub URL: $huburi\n";
print "  Salmon URL: $salmonuri\n";

if ($feedurl != $oprofile->feeduri || $salmonuri != $oprofile->salmonuri) {
    print "\n";
    print "Updating...\n";
    // @fixme update keys :P
    #$orig = clone($oprofile);
    #$oprofile->feeduri = $feedurl;
    #$oprofile->salmonuri = $salmonuri;
    #$ok = $oprofile->update($orig);
    $ok = $oprofile->query('UPDATE ostatus_profile SET ' .
        'feeduri=\'' . $oprofile->escape($feedurl) . '\',' .
        'salmonuri=\'' . $oprofile->escape($salmonuri) . '\' ' .
        'WHERE uri=\'' . $oprofile->escape($uri) . '\'');

    if (!$ok) {
        print "Failed to update profile record...\n";
        exit(1);
    }

    $oprofile->decache();
} else {
    print "\n";
    print "Ok, ostatus_profile record unchanged.\n\n";
}

$sub = FeedSub::ensureFeed($feedurl);

if ($huburi != $sub->huburi) {
    print "\n";
    print "Updating hub record for feed; was $sub->huburi\n";
    $orig = clone($sub);
    $sub->huburi = $huburi;
    $ok = $sub->update($orig);

    if (!$ok) {
        print "Failed to update sub record...\n";
        exit(1);
    }
} else {
    print "\n";
    print "Feed record ok, not changing.\n\n";
}

echo "\n";
echo "Pinging hub {$sub->huburi} with new subscription for {$sub->uri}\n";
try {
    $sub->subscribe();
    echo "ok\n";
} catch (Exception $e) {
    echo 'Could not confirm. '.get_class($e).': '.$e->getMessage()."\n";
}

$o2 = Ostatus_profile::getKV('uri', $uri);

print "\n";
print "New profile state:\n";
showProfile($o2);

print "\n";
print "New feed state:\n";
$sub2 = FeedSub::ensureFeed($feedurl);
showSub($sub2);

function showProfile($oprofile)
{
    print "  Feed URL: $oprofile->feeduri\n";
    print "  Salmon URL: $oprofile->salmonuri\n";
    print "  Avatar URL: $oprofile->avatar\n";
    print "  Profile ID: $oprofile->profile_id\n";
    print "  Group ID: $oprofile->group_id\n";
    print "  Record created: $oprofile->created\n";
    print "  Record modified: $oprofile->modified\n";
}

function showSub($sub)
{
    print "  Subscription state: $sub->sub_state\n";
    print "  Verify token: $sub->verify_token\n";
    print "  Signature secret: $sub->secret\n";
    print "  Sub start date: $sub->sub_start\n";
    print "  Record created: $sub->created\n";
    print "  Record modified: $sub->modified\n";
}


code:
#!/usr/bin/env php
<?php
/*
 * StatusNet - a distributed open-source microblogging tool
 * Copyright (C) 2011, 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/>.
 */

define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..'));

$shortoptions = 'u:af';
$longoptions = array('uri=', 'all', 'force');

$helptext = <<<UPDATE_OSTATUS_PROFILES
update_ostatus_profiles.php [options]
Refetch / update OStatus profile info and avatars. Useful if you
do something like accidentally delete your avatars directory when
you have no backup.

    -u --uri OStatus profile URI to update
    -a --all update all

    -f --force  Force update (despite identical avatar URLs etc.)

UPDATE_OSTATUS_PROFILES;

require_once INSTALLDIR . '/scripts/commandline.inc';

/*
 * Hacky class to remove some checks and get public access to
 * protected mentods
 */
class LooseOstatusProfile extends Ostatus_profile
{
    /**
     * Look up and if necessary create an Ostatus_profile for the remote entity
     * with the given profile page URL. This should never return null -- you
     * will either get an object or an exception will be thrown.
     *
     * @param string $profile_url
     * @return Ostatus_profile
     * @throws Exception on various error conditions
     * @throws OStatusShadowException if this reference would obscure a local user/group
     */
    public static function updateProfileURL($profile_url, $hints=array())
    {
        $oprofile = null;

        $hints['profileurl'] = $profile_url;

        // Fetch the URL
        // XXX: HTTP caching

        $client = new HTTPClient();
        $client->setHeader('Accept', 'text/html,application/xhtml+xml');
        $response = $client->get($profile_url);

        if (!$response->isOk()) {
            // TRANS: Exception. %s is a profile URL.
            throw new Exception(sprintf(_('Could not reach profile page %s.'),$profile_url));
        }

        // Check if we have a non-canonical URL

        $finalUrl = $response->getUrl();

        if ($finalUrl != $profile_url) {
            $hints['profileurl'] = $finalUrl;
        }

        // Try to get some hCard data

        $body = $response->getBody();

        $hcardHints = DiscoveryHints::hcardHints($body, $finalUrl);

        if (!empty($hcardHints)) {
            $hints = array_merge($hints, $hcardHints);
        }

        // Check if they've got an LRDD header

        $lrdd = LinkHeader::getLink($response, 'lrdd', 'application/xrd+xml');
        try {
            $xrd = new XML_XRD();
            $xrd->loadFile($lrdd);
            $xrdHints = DiscoveryHints::fromXRD($xrd);
            $hints = array_merge($hints, $xrdHints);
        } catch (Exception $e) {
            // No hints available from XRD
        }

        // If discovery found a feedurl (probably from LRDD), use it.

        if (array_key_exists('feedurl', $hints)) {
            return self::ensureFeedURL($hints['feedurl'], $hints);
        }

        // Get the feed URL from HTML

        $discover = new FeedDiscovery();

        $feedurl = $discover->discoverFromHTML($finalUrl, $body);

        if (!empty($feedurl)) {
            $hints['feedurl'] = $feedurl;
            return self::ensureFeedURL($feedurl, $hints);
        }

        // TRANS: Exception. %s is a URL.
        throw new Exception(sprintf(_m('Could not find a feed URL for profile page %s.'),$finalUrl));
    }

    /**
     * Look up, and if necessary create, an Ostatus_profile for the remote
     * entity with the given webfinger address.
     * This should never return null -- you will either get an object or
     * an exception will be thrown.
     *
     * @param string $addr webfinger address
     * @return Ostatus_profile
     * @throws Exception on error conditions
     * @throws OStatusShadowException if this reference would obscure a local user/group
     */
    public static function updateWebfinger($addr)
    {
        $disco = new Discovery();

        try {
            $xrd = $disco->lookup($addr);
        } catch (Exception $e) {
            // Save negative cache entry so we don't waste time looking it up again.
            // @fixme distinguish temporary failures?
            self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), null);
            // TRANS: Exception.
            throw new Exception(_m('Not a valid webfinger address.'));
        }

        $hints = array('webfinger' => $addr);

        try {
            $dHints = DiscoveryHints::fromXRD($xrd);
            $hints = array_merge($hints, $xrdHints);
        } catch (Exception $e) {
            // No hints available from XRD
        }

        // If there's an Hcard, let's grab its info
        if (array_key_exists('hcard', $hints)) {
            if (!array_key_exists('profileurl', $hints) ||
                $hints['hcard'] != $hints['profileurl']) {
                $hcardHints = DiscoveryHints::fromHcardUrl($hints['hcard']);
                $hints = array_merge($hcardHints, $hints);
            }
        }

        // If we got a feed URL, try that
        if (array_key_exists('feedurl', $hints)) {
            try {
                common_log(LOG_INFO, "Discovery on acct:$addr with feed URL " . $hints['feedurl']);
                $oprofile = self::ensureFeedURL($hints['feedurl'], $hints);
                self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), $oprofile->uri);
                return $oprofile;
            } catch (Exception $e) {
                common_log(LOG_WARNING, "Failed creating profile from feed URL '$feedUrl': " . $e->getMessage());
                // keep looking
            }
        }

        // If we got a profile page, try that!
        if (array_key_exists('profileurl', $hints)) {
            try {
                common_log(LOG_INFO, "Discovery on acct:$addr with profile URL $profileUrl");
                $oprofile = self::ensureProfileURL($hints['profileurl'], $hints);
                self::cacheSet(sprintf('ostatus_profile:webfinger:%s', $addr), $oprofile->uri);
                return $oprofile;
            } catch (OStatusShadowException $e) {
                // We've ended up with a remote reference to a local user or group.
                // @fixme ideally we should be able to say who it was so we can
                // go back and refer to it the regular way
                throw $e;
            } catch (Exception $e) {
                common_log(LOG_WARNING, "Failed creating profile from profile URL '$profileUrl': " . $e->getMessage());
                // keep looking
                //
                // @fixme this means an error discovering from profile page
                // may give us a corrupt entry using the webfinger URI, which
                // will obscure the correct page-keyed profile later on.
            }
        }
        throw new Exception(sprintf(_m('Could not find a valid profile for "%s".'),$addr));
    }
}

function pullOstatusProfile($uri) {

    $oprofile = null;

    if (Validate::email($uri)) {
        $oprofile = LooseOstatusProfile::updateWebfinger($uri);
    } else if (Validate::uri($uri)) {
        $oprofile = LooseOstatusProfile::updateProfileURL($uri);
    } else {
        print "Sorry, we could not reach the address: $uri\n";
        return false;
    }

   return $oprofile;
}

$quiet = have_option('q', 'quiet');

$lop = new LooseOstatusProfile();

if (have_option('u', 'uri')) {
    $lop->uri = get_option_value('u', 'uri');
} else if (!have_option('a', 'all')) {
    show_help();
    exit(1);
}

$forceUpdates = have_option('f', 'force');

$cnt = $lop->find();

if (!empty($cnt)) {
    if (!$quiet) { echo "Found {$cnt} OStatus profiles:\n"; }
} else {
    if (have_option('u', 'uri')) {
        if (!$quiet) { echo "Couldn't find an existing OStatus profile with that URI.\n"; }
    } else {
        if (!$quiet) { echo "Couldn't find any existing OStatus profiles.\n"; }
    }
    exit(0);
}

while($lop->fetch()) {
    if (!$quiet) { echo "Updating OStatus profile '{$lop->uri}' ... "; }
    try {
        $oprofile = pullOstatusProfile($lop->uri);

        if (!empty($oprofile)) {
            $orig = clone($lop);
            $lop->avatar = $oprofile->avatar;
            $lop->update($orig);
            $lop->updateAvatar($oprofile->avatar, $forceUpdates);
            if (!$quiet) { print "Done.\n"; }
        }
    } catch (Exception $e) {
        if (!$quiet) { print $e->getMessage() . "\n"; }
        common_log(LOG_WARNING, $e->getMessage(), __FILE__);
        // continue on error
    }
}

if (!$quiet) { echo "OK.\n"; }


code:
<?php

if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) {
    print "This script must be run from the command line\n";
    exit();
}

define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..'));
define('GNUSOCIAL', true);
define('STATUSNET', true);  // compatibility

require_once INSTALLDIR . '/lib/common.php';
require_once INSTALLDIR . '/plugins/OStatus/lib/feeddiscovery.php';

class FeedDiscoveryTest extends PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider provider
     *
     */
    public function testProduction($url, $html, $expected)
    {
        $sub = new FeedDiscovery();
        $url = $sub->discoverFromHTML($url, $html);
        $this->assertEquals($expected, $url);
    }

    static public function provider()
    {
        $sampleHeader = <<<END
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<title>leŭksman  </title>

<meta name="generator" content="WordPress 2.8.6" />

<link rel="stylesheet" href="http://leuksman.com/log/wp-content/themes/leuksman/style.css" type="text/css" media="screen" />
<link rel="alternate" type="application/rss+xml" title="leŭksman RSS Feed" href="http://leuksman.com/log/feed/" />
<link rel="pingback" href="http://leuksman.com/log/xmlrpc.php" />

<meta name="viewport" content="width = 640" />

<xmeta name="viewport" content="initial-scale=2.3, user-scalable=no" />

<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://leuksman.com/log/xmlrpc.php?rsd" />
<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://leuksman.com/log/wp-includes/wlwmanifest.xml" />
<link rel='index' title='leŭksman' href='http://leuksman.com/log' />
<meta name="generator" content="WordPress 2.8.6" />

END;
        return array(
                     array('http://example.com/',
                           '<link rel="alternate" href="http://example.com/feed/rss" type="application/rss+xml">',
                           'http://example.com/feed/rss'),
                     array('http://example.com/atom',
                           '<link rel="alternate" href="http://example.com/feed/atom" type="application/atom+xml">',
                           'http://example.com/feed/atom'),
                     array('http://example.com/empty',
                           '<link rel="alternate" href="http://example.com/index.pdf" type="application/pdf">',
                           false),
                     array('http://example.com/tagsoup',
                           '
<LINK rel=alternate hRef=http://example.com/feed/rss type=application/rss+xml><fnork',
                           'http://example.com/feed/rss'),
                     // 'rel' attribute must be lowercase, alone per http://www.rssboard.org/rss-autodiscovery
                     // but we're going to be liberal in what we receive.
                     array('http://example.com/tagsoup2',
                           '
<LINK rel=" feeders    alternate 467" hRef=http://example.com/feed/rss type=application/rss+xml><fnork',
                           'http://example.com/feed/rss'),
                     array('http://example.com/tagsoup3',
                           '
<LINK rel=ALTERNATE hRef=http://example.com/feed/rss type=application/rss+xml><fnork',
                           false),
                     array('http://example.com/relative/link1',
                           '<link rel="alternate" href="/feed/rss" type="application/rss+xml">',
                           'http://example.com/feed/rss'),
                     array('http://example.com/relative/link2',
                           '<link rel="alternate" href="../feed/rss" type="application/rss+xml">',
                           'http://example.com/feed/rss'),
                     // This one can't resolve correctly; relative link is bogus.
                     array('http://example.com/relative/link3',
                           '<link rel="alternate" href="http:/feed/rss" type="application/rss+xml">',
                           'http:/feed/rss'),
                     array('http://example.com/base/link1',
                           '<link rel="alternate" href="/feed/rss" type="application/rss+xml"><base href="http://target.example.com/">',
                           'http://target.example.com/feed/rss'),
                     array('http://example.com/base/link2',
                           '<link rel="alternate" href="feed/rss" type="application/rss+xml"><base href="http://target.example.com/">',
                           'http://target.example.com/feed/rss'),
                     // This one can't resolve; relative link is bogus.
                     array('http://example.com/base/link3',
                           '<link rel="alternate" href="http:/feed/rss" type="application/rss+xml"><base href="http://target.example.com/">',
                           'http:/feed/rss'),
                     // Trick question! There's a <base> but no href on it
                     array('http://example.com/relative/fauxbase',
                           '<link rel="alternate" href="../feed/rss" type="application/rss+xml"><base target="top">',
                           'http://example.com/feed/rss'),
                     // Actual WordPress blog header example
                     array('http://leuksman.com/log/',
                           $sampleHeader,
                           'http://leuksman.com/log/feed/'));
    }
}


code:
<?php

if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) {
    print "This script must be run from the command line\n";
    exit();
}

define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..'));
define('GNUSOCIAL', true);
define('STATUSNET', true);  // compatibility

require_once INSTALLDIR . '/lib/common.php';

class MagicEnvelopeTest extends PHPUnit_Framework_TestCase
{
    /**
     * Test that MagicEnvelope builds the correct plaintext for signing.
     * @dataProvider provider
     */
    public function testSignatureText(MagicEnvelope $env, $expected)
    {
        $text = $env->signingText();

        $this->assertEquals($expected, $text, "'$text' should be '$expected'");
    }

    static public function provider()
    {
        // Sample case given in spec:
        // http://salmon-protocol.googlecode.com/svn/trunk/draft-panzer-magicsig-00.html#signing
        $magic_env = new MagicEnvelope();
        $magic_env->data = 'Tm90IHJlYWxseSBBdG9t';
        $magic_env->data_type = 'application/atom+xml';
        $magic_env->encoding = 'base64url';
        $magic_env->alg = 'RSA-SHA256';

        return array(
            array(
                $magic_env,
                'Tm90IHJlYWxseSBBdG9t.YXBwbGljYXRpb24vYXRvbSt4bWw=.YmFzZTY0dXJs.UlNBLVNIQTI1Ng=='
            )
        );
    }
}


code:
<?php

if (isset($_SERVER) && array_key_exists('REQUEST_METHOD', $_SERVER)) {
    print "This script must be run from the command line\n";
    exit();
}

define('INSTALLDIR', realpath(dirname(__FILE__) . '/../../..'));
define('GNUSOCIAL', true);
define('STATUSNET', true);  // compatibility

require_once INSTALLDIR . '/scripts/commandline.inc';
require_once INSTALLDIR . '/extlib/php-gettext/gettext.inc';

common_init_locale("en_US");
common_init_locale('fr');

putenv("LANG=fr");
putenv("LANGUAGE=fr");
setlocale('fr.utf8');
_setlocale('fr.utf8');

_bindtextdomain("statusnet", INSTALLDIR . '/locale');
_bindtextdomain("FeedSub", INSTALLDIR . '/plugins/FeedSub/locale');

$times = 10000;
$delta = array();

$start = microtime(true);
for($i = 0; $i < $times; $i++) {
    $result = _("Send");
}
$delta["_"] = array((microtime(true) - $start) / $times, $result);

$start = microtime(true);
for($i = 0; $i < $times; $i++) {
    $result = __("Send");
}
$delta["__"] = array((microtime(true) - $start) / $times, $result);

$start = microtime(true);
for($i = 0; $i < $times; $i++) {
    $result = dgettext("FeedSub", "Feeds");
}
$delta["dgettext"] = array((microtime(true) - $start) / $times, $result);

$start = microtime(true);
for($i = 0; $i < $times; $i++) {
    $result = _dgettext("FeedSub", "Feeds");
}
$delta["_dgettext"] = array((microtime(true) - $start) / $times, $result);

$start = microtime(true);
for($i = 0; $i < $times; $i++) {
    // TRANS: String in the gettext speed test script. Unimportant.
    $result = _m("Feeds");
}
$delta["_m"] = array((microtime(true) - $start) / $times, $result);

$start = microtime(true);
for($i = 0; $i < $times; $i++) {
    $result = fake("Feeds");
}
$delta["fake"] = array((microtime(true) - $start) / $times, $result);

foreach ($delta as $func => $bits) {
    list($time, $result) = $bits;
    $ms = $time * 1000.0;
    printf("%10s %2.4fms %s\n", $func, $ms, $result);
}

function fake($str) {
    return $str;
}