Merge pull request #303 from mastodon/release/1.2.0

Release v1.2.0
This commit is contained in:
CMK 2021-12-06 12:37:34 +08:00 committed by GitHub
commit feb748676f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
310 changed files with 12835 additions and 2633 deletions

View File

@ -19,8 +19,8 @@ jobs:
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: force Xcode 12.5.1 - name: force Xcode 13.1
run: sudo xcode-select -switch /Applications/Xcode_12.5.1.app run: sudo xcode-select -switch /Applications/Xcode_13.1.app
- name: setup - name: setup
run: exec ./.github/scripts/setup.sh run: exec ./.github/scripts/setup.sh
- name: build - name: build

4
.gitignore vendored
View File

@ -58,6 +58,7 @@ Packages/
.swiftpm .swiftpm
.build/ .build/
!**/swiftpm/Package.resolved
# CocoaPods # CocoaPods
# We recommend against adding the Pods directory to your .gitignore. However # We recommend against adding the Pods directory to your .gitignore. However
@ -121,5 +122,4 @@ xcuserdata
Localization/StringsConvertor/input Localization/StringsConvertor/input
Localization/StringsConvertor/output Localization/StringsConvertor/output
.DS_Store .DS_Store
/Mastodon.xcworkspace/xcshareddata/swiftpm

View File

@ -15,8 +15,8 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string> <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.0.8</string> <string>1.2.0</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>60</string> <string>88</string>
</dict> </dict>
</plist> </plist>

View File

@ -0,0 +1,40 @@
//
// UserDefaults+Notification.swift
// AppShared
//
// Created by Cirno MainasuK on 2021-10-9.
//
import UIKit
import CryptoKit
extension UserDefaults {
// always use hash value (SHA256) from accessToken as key
private static func deriveKey(from accessToken: String, prefix: String) -> String {
let digest = SHA256.hash(data: Data(accessToken.utf8))
let bytes = [UInt8](digest)
let hex = bytes.toHexString()
let key = prefix + "@" + hex
return key
}
private static let notificationCountKeyPrefix = "notification_count"
public func getNotificationCountWithAccessToken(accessToken: String) -> Int {
let prefix = UserDefaults.notificationCountKeyPrefix
let key = UserDefaults.deriveKey(from: accessToken, prefix: prefix)
return integer(forKey: key)
}
public func setNotificationCountWithAccessToken(accessToken: String, value: Int) {
let prefix = UserDefaults.notificationCountKeyPrefix
let key = UserDefaults.deriveKey(from: accessToken, prefix: prefix)
setValue(value, forKey: key)
}
public func increaseNotificationCount(accessToken: String) {
let count = getNotificationCountWithAccessToken(accessToken: accessToken)
setNotificationCountWithAccessToken(accessToken: accessToken, value: count + 1)
}
}

View File

@ -10,3 +10,4 @@ import UIKit
extension UserDefaults { extension UserDefaults {
public static let shared = UserDefaults(suiteName: AppName.groupID)! public static let shared = UserDefaults(suiteName: AppName.groupID)!
} }

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>_XCCurrentVersionName</key>
<string>CoreData 2.xcdatamodel</string>
</dict>
</plist>

View File

@ -0,0 +1,306 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="19206" systemVersion="20G165" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="Application" representedClassName=".Application" syncable="YES">
<attribute name="identifier" optional="YES" attributeType="UUID" usesScalarValueType="NO"/>
<attribute name="name" attributeType="String"/>
<attribute name="vapidKey" optional="YES" attributeType="String"/>
<attribute name="website" optional="YES" attributeType="String"/>
<relationship name="status" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Status" inverseName="application" inverseEntity="Status"/>
</entity>
<entity name="Attachment" representedClassName=".Attachment" syncable="YES">
<attribute name="blurhash" optional="YES" attributeType="String"/>
<attribute name="createdAt" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="descriptionString" optional="YES" attributeType="String"/>
<attribute name="domain" attributeType="String"/>
<attribute name="id" attributeType="String"/>
<attribute name="index" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="metaData" optional="YES" attributeType="Binary"/>
<attribute name="previewRemoteURL" optional="YES" attributeType="String"/>
<attribute name="previewURL" optional="YES" attributeType="String"/>
<attribute name="remoteURL" optional="YES" attributeType="String"/>
<attribute name="textURL" optional="YES" attributeType="String"/>
<attribute name="typeRaw" attributeType="String"/>
<attribute name="updatedAt" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="url" optional="YES" attributeType="String"/>
<relationship name="status" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Status" inverseName="mediaAttachments" inverseEntity="Status"/>
</entity>
<entity name="DomainBlock" representedClassName=".DomainBlock" syncable="YES">
<attribute name="blockedDomain" attributeType="String"/>
<attribute name="createAt" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="domain" attributeType="String"/>
<attribute name="userID" attributeType="String"/>
<uniquenessConstraints>
<uniquenessConstraint>
<constraint value="userID"/>
<constraint value="domain"/>
<constraint value="blockedDomain"/>
</uniquenessConstraint>
</uniquenessConstraints>
</entity>
<entity name="Emoji" representedClassName=".Emoji" syncable="YES">
<attribute name="category" optional="YES" attributeType="String"/>
<attribute name="createAt" attributeType="Date" defaultDateTimeInterval="631123200" usesScalarValueType="NO"/>
<attribute name="identifier" attributeType="UUID" usesScalarValueType="NO"/>
<attribute name="shortcode" attributeType="String"/>
<attribute name="staticURL" attributeType="String"/>
<attribute name="url" attributeType="String"/>
<attribute name="visibleInPicker" attributeType="Boolean" usesScalarValueType="YES"/>
</entity>
<entity name="History" representedClassName=".History" syncable="YES">
<attribute name="accounts" optional="YES" attributeType="String"/>
<attribute name="createAt" attributeType="Date" defaultDateTimeInterval="631123200" usesScalarValueType="NO"/>
<attribute name="day" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="identifier" optional="YES" attributeType="UUID" usesScalarValueType="NO"/>
<attribute name="uses" optional="YES" attributeType="String"/>
<relationship name="tag" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Tag" inverseName="histories" inverseEntity="Tag"/>
</entity>
<entity name="HomeTimelineIndex" representedClassName=".HomeTimelineIndex" syncable="YES">
<attribute name="createdAt" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="deletedAt" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="domain" attributeType="String"/>
<attribute name="hasMore" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="identifier" attributeType="String"/>
<attribute name="userID" attributeType="String"/>
<relationship name="status" maxCount="1" deletionRule="Nullify" destinationEntity="Status" inverseName="homeTimelineIndexes" inverseEntity="Status"/>
</entity>
<entity name="Instance" representedClassName=".Instance" syncable="YES">
<attribute name="configurationRaw" optional="YES" attributeType="Binary"/>
<attribute name="createdAt" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="domain" attributeType="String"/>
<attribute name="updatedAt" attributeType="Date" usesScalarValueType="NO"/>
<relationship name="authentications" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonAuthentication" inverseName="instance" inverseEntity="MastodonAuthentication"/>
</entity>
<entity name="MastodonAuthentication" representedClassName=".MastodonAuthentication" syncable="YES">
<attribute name="activedAt" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="appAccessToken" attributeType="String"/>
<attribute name="clientID" attributeType="String"/>
<attribute name="clientSecret" attributeType="String"/>
<attribute name="createdAt" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="domain" attributeType="String"/>
<attribute name="identifier" attributeType="UUID" usesScalarValueType="NO"/>
<attribute name="updatedAt" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="userAccessToken" attributeType="String"/>
<attribute name="userID" attributeType="String"/>
<attribute name="username" attributeType="String"/>
<relationship name="instance" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Instance" inverseName="authentications" inverseEntity="Instance"/>
<relationship name="user" maxCount="1" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="mastodonAuthentication" inverseEntity="MastodonUser"/>
</entity>
<entity name="MastodonNotification" representedClassName=".MastodonNotification" syncable="YES">
<attribute name="createAt" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="domain" attributeType="String"/>
<attribute name="id" attributeType="String"/>
<attribute name="identifier" attributeType="UUID" usesScalarValueType="NO"/>
<attribute name="typeRaw" attributeType="String"/>
<attribute name="updatedAt" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="userID" attributeType="String"/>
<relationship name="account" maxCount="1" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="notifications" inverseEntity="MastodonUser"/>
<relationship name="status" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Status" inverseName="inNotifications" inverseEntity="Status"/>
<uniquenessConstraints>
<uniquenessConstraint>
<constraint value="id"/>
</uniquenessConstraint>
</uniquenessConstraints>
</entity>
<entity name="MastodonUser" representedClassName=".MastodonUser" syncable="YES">
<attribute name="acct" attributeType="String"/>
<attribute name="avatar" attributeType="String"/>
<attribute name="avatarStatic" optional="YES" attributeType="String"/>
<attribute name="bot" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="createdAt" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="displayName" attributeType="String"/>
<attribute name="domain" attributeType="String"/>
<attribute name="emojisData" optional="YES" attributeType="Binary"/>
<attribute name="fieldsData" optional="YES" attributeType="Binary"/>
<attribute name="followersCount" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="followingCount" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="header" attributeType="String"/>
<attribute name="headerStatic" optional="YES" attributeType="String"/>
<attribute name="id" attributeType="String"/>
<attribute name="identifier" attributeType="String"/>
<attribute name="locked" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="note" optional="YES" attributeType="String"/>
<attribute name="statusesCount" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="suspended" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="updatedAt" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="url" optional="YES" attributeType="String"/>
<attribute name="username" attributeType="String"/>
<relationship name="blocking" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="blockingBy" inverseEntity="MastodonUser"/>
<relationship name="blockingBy" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="blocking" inverseEntity="MastodonUser"/>
<relationship name="bookmarked" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Status" inverseName="bookmarkedBy" inverseEntity="Status"/>
<relationship name="domainBlocking" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="domainBlockingBy" inverseEntity="MastodonUser"/>
<relationship name="domainBlockingBy" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="domainBlocking" inverseEntity="MastodonUser"/>
<relationship name="endorsed" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="endorsedBy" inverseEntity="MastodonUser"/>
<relationship name="endorsedBy" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="endorsed" inverseEntity="MastodonUser"/>
<relationship name="favourite" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Status" inverseName="favouritedBy" inverseEntity="Status"/>
<relationship name="following" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="followingBy" inverseEntity="MastodonUser"/>
<relationship name="followingBy" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="following" inverseEntity="MastodonUser"/>
<relationship name="followRequested" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="followRequestedBy" inverseEntity="MastodonUser"/>
<relationship name="followRequestedBy" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="followRequested" inverseEntity="MastodonUser"/>
<relationship name="mastodonAuthentication" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="MastodonAuthentication" inverseName="user" inverseEntity="MastodonAuthentication"/>
<relationship name="muted" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Status" inverseName="mutedBy" inverseEntity="Status"/>
<relationship name="muting" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="mutingBy" inverseEntity="MastodonUser"/>
<relationship name="mutingBy" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="muting" inverseEntity="MastodonUser"/>
<relationship name="notifications" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonNotification" inverseName="account" inverseEntity="MastodonNotification"/>
<relationship name="pinnedStatus" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Status" inverseName="pinnedBy" inverseEntity="Status"/>
<relationship name="privateNotes" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="PrivateNote" inverseName="to" inverseEntity="PrivateNote"/>
<relationship name="privateNotesTo" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="PrivateNote" inverseName="from" inverseEntity="PrivateNote"/>
<relationship name="reblogged" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Status" inverseName="rebloggedBy" inverseEntity="Status"/>
<relationship name="searchHistories" toMany="YES" deletionRule="Nullify" destinationEntity="SearchHistory" inverseName="account" inverseEntity="SearchHistory"/>
<relationship name="statuses" toMany="YES" deletionRule="Nullify" destinationEntity="Status" inverseName="author" inverseEntity="Status"/>
<relationship name="votePollOptions" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="PollOption" inverseName="votedBy" inverseEntity="PollOption"/>
<relationship name="votePolls" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Poll" inverseName="votedBy" inverseEntity="Poll"/>
</entity>
<entity name="Mention" representedClassName=".Mention" syncable="YES">
<attribute name="acct" attributeType="String"/>
<attribute name="createAt" attributeType="Date" defaultDateTimeInterval="631123200" usesScalarValueType="NO"/>
<attribute name="id" attributeType="String"/>
<attribute name="identifier" attributeType="UUID" usesScalarValueType="NO"/>
<attribute name="index" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="url" attributeType="String"/>
<attribute name="username" attributeType="String"/>
<relationship name="status" maxCount="1" deletionRule="Nullify" destinationEntity="Status" inverseName="mentions" inverseEntity="Status"/>
</entity>
<entity name="Poll" representedClassName=".Poll" syncable="YES">
<attribute name="createdAt" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="expired" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="expiresAt" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="id" attributeType="String"/>
<attribute name="multiple" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="updatedAt" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="votersCount" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="votesCount" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<relationship name="options" toMany="YES" deletionRule="Cascade" destinationEntity="PollOption" inverseName="poll" inverseEntity="PollOption"/>
<relationship name="status" maxCount="1" deletionRule="Nullify" destinationEntity="Status" inverseName="poll" inverseEntity="Status"/>
<relationship name="votedBy" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="votePolls" inverseEntity="MastodonUser"/>
</entity>
<entity name="PollOption" representedClassName=".PollOption" syncable="YES">
<attribute name="createdAt" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="index" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="title" attributeType="String"/>
<attribute name="updatedAt" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="votesCount" optional="YES" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<relationship name="poll" maxCount="1" deletionRule="Nullify" destinationEntity="Poll" inverseName="options" inverseEntity="Poll"/>
<relationship name="votedBy" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="votePollOptions" inverseEntity="MastodonUser"/>
</entity>
<entity name="PrivateNote" representedClassName=".PrivateNote" syncable="YES">
<attribute name="note" optional="YES" attributeType="String"/>
<attribute name="updatedAt" attributeType="Date" usesScalarValueType="NO"/>
<relationship name="from" maxCount="1" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="privateNotesTo" inverseEntity="MastodonUser"/>
<relationship name="to" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="privateNotes" inverseEntity="MastodonUser"/>
</entity>
<entity name="SearchHistory" representedClassName=".SearchHistory" syncable="YES">
<attribute name="createAt" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="domain" attributeType="String" defaultValueString=""/>
<attribute name="identifier" attributeType="UUID" usesScalarValueType="NO"/>
<attribute name="updatedAt" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="userID" attributeType="String" defaultValueString=""/>
<relationship name="account" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="searchHistories" inverseEntity="MastodonUser"/>
<relationship name="hashtag" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Tag" inverseName="searchHistories" inverseEntity="Tag"/>
<relationship name="status" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Status" inverseName="searchHistories" inverseEntity="Status"/>
</entity>
<entity name="Setting" representedClassName=".Setting" syncable="YES">
<attribute name="createdAt" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="domain" attributeType="String"/>
<attribute name="preferredStaticAvatar" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="preferredStaticEmoji" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="preferredTrueBlackDarkMode" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="preferredUsingDefaultBrowser" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="updatedAt" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="userID" attributeType="String"/>
<relationship name="subscriptions" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Subscription" inverseName="setting" inverseEntity="Subscription"/>
</entity>
<entity name="Status" representedClassName=".Status" syncable="YES">
<attribute name="content" attributeType="String"/>
<attribute name="createdAt" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="deletedAt" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="domain" attributeType="String"/>
<attribute name="emojisData" optional="YES" attributeType="Binary"/>
<attribute name="favouritesCount" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="id" attributeType="String"/>
<attribute name="identifier" attributeType="String"/>
<attribute name="inReplyToAccountID" optional="YES" attributeType="String"/>
<attribute name="inReplyToID" optional="YES" attributeType="String"/>
<attribute name="language" optional="YES" attributeType="String"/>
<attribute name="reblogsCount" attributeType="Integer 64" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="repliesCount" optional="YES" attributeType="Integer 64" usesScalarValueType="NO"/>
<attribute name="revealedAt" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="sensitive" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="spoilerText" optional="YES" attributeType="String"/>
<attribute name="text" optional="YES" attributeType="String"/>
<attribute name="updatedAt" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="uri" attributeType="String"/>
<attribute name="url" attributeType="String"/>
<attribute name="visibility" optional="YES" attributeType="String"/>
<relationship name="application" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Application" inverseName="status" inverseEntity="Application"/>
<relationship name="author" maxCount="1" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="statuses" inverseEntity="MastodonUser"/>
<relationship name="bookmarkedBy" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="bookmarked" inverseEntity="MastodonUser"/>
<relationship name="favouritedBy" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="favourite" inverseEntity="MastodonUser"/>
<relationship name="homeTimelineIndexes" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="HomeTimelineIndex" inverseName="status" inverseEntity="HomeTimelineIndex"/>
<relationship name="inNotifications" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="MastodonNotification" inverseName="status" inverseEntity="MastodonNotification"/>
<relationship name="mediaAttachments" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Attachment" inverseName="status" inverseEntity="Attachment"/>
<relationship name="mentions" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="Mention" inverseName="status" inverseEntity="Mention"/>
<relationship name="mutedBy" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="muted" inverseEntity="MastodonUser"/>
<relationship name="pinnedBy" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="pinnedStatus" inverseEntity="MastodonUser"/>
<relationship name="poll" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="Poll" inverseName="status" inverseEntity="Poll"/>
<relationship name="reblog" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Status" inverseName="reblogFrom" inverseEntity="Status"/>
<relationship name="reblogFrom" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="Status" inverseName="reblog" inverseEntity="Status"/>
<relationship name="rebloggedBy" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="reblogged" inverseEntity="MastodonUser"/>
<relationship name="replyFrom" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Status" inverseName="replyTo" inverseEntity="Status"/>
<relationship name="replyTo" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Status" inverseName="replyFrom" inverseEntity="Status"/>
<relationship name="searchHistories" toMany="YES" deletionRule="Nullify" destinationEntity="SearchHistory" inverseName="status" inverseEntity="SearchHistory"/>
</entity>
<entity name="Subscription" representedClassName=".Subscription" syncable="YES">
<attribute name="activedAt" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="createdAt" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="endpoint" optional="YES" attributeType="String"/>
<attribute name="id" optional="YES" attributeType="String"/>
<attribute name="policyRaw" attributeType="String"/>
<attribute name="serverKey" optional="YES" attributeType="String"/>
<attribute name="updatedAt" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="userToken" optional="YES" attributeType="String"/>
<relationship name="alert" maxCount="1" deletionRule="Cascade" destinationEntity="SubscriptionAlerts" inverseName="subscription" inverseEntity="SubscriptionAlerts"/>
<relationship name="setting" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Setting" inverseName="subscriptions" inverseEntity="Setting"/>
</entity>
<entity name="SubscriptionAlerts" representedClassName=".SubscriptionAlerts" syncable="YES">
<attribute name="createdAt" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="favouriteRaw" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="followRaw" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="followRequestRaw" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="mentionRaw" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="pollRaw" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="reblogRaw" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
<attribute name="updatedAt" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<relationship name="subscription" maxCount="1" deletionRule="Nullify" destinationEntity="Subscription" inverseName="alert" inverseEntity="Subscription"/>
</entity>
<entity name="Tag" representedClassName=".Tag" syncable="YES">
<attribute name="createAt" attributeType="Date" defaultDateTimeInterval="631123200" usesScalarValueType="NO"/>
<attribute name="identifier" attributeType="UUID" usesScalarValueType="NO"/>
<attribute name="name" attributeType="String"/>
<attribute name="updatedAt" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
<attribute name="url" attributeType="String"/>
<relationship name="histories" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="History" inverseName="tag" inverseEntity="History"/>
<relationship name="searchHistories" toMany="YES" deletionRule="Nullify" destinationEntity="SearchHistory" inverseName="hashtag" inverseEntity="SearchHistory"/>
</entity>
<elements>
<element name="Application" positionX="0" positionY="0" width="128" height="104"/>
<element name="Attachment" positionX="0" positionY="0" width="128" height="254"/>
<element name="DomainBlock" positionX="45" positionY="162" width="128" height="89"/>
<element name="Emoji" positionX="0" positionY="0" width="128" height="134"/>
<element name="History" positionX="0" positionY="0" width="128" height="119"/>
<element name="HomeTimelineIndex" positionX="0" positionY="0" width="128" height="134"/>
<element name="MastodonAuthentication" positionX="0" positionY="0" width="128" height="224"/>
<element name="MastodonNotification" positionX="9" positionY="162" width="128" height="164"/>
<element name="MastodonUser" positionX="0" positionY="0" width="128" height="734"/>
<element name="Mention" positionX="0" positionY="0" width="128" height="149"/>
<element name="Poll" positionX="0" positionY="0" width="128" height="194"/>
<element name="PollOption" positionX="0" positionY="0" width="128" height="134"/>
<element name="PrivateNote" positionX="0" positionY="0" width="128" height="89"/>
<element name="SearchHistory" positionX="0" positionY="0" width="128" height="149"/>
<element name="Setting" positionX="72" positionY="162" width="128" height="164"/>
<element name="Status" positionX="0" positionY="0" width="128" height="599"/>
<element name="Subscription" positionX="81" positionY="171" width="128" height="179"/>
<element name="SubscriptionAlerts" positionX="72" positionY="162" width="128" height="14"/>
<element name="Tag" positionX="0" positionY="0" width="128" height="134"/>
<element name="Instance" positionX="45" positionY="162" width="128" height="104"/>
</elements>
</model>

View File

@ -13,6 +13,8 @@ import AppShared
public final class CoreDataStack { public final class CoreDataStack {
static let logger = Logger(subsystem: "CoreDataStack", category: "DB")
private(set) var storeDescriptions: [NSPersistentStoreDescription] private(set) var storeDescriptions: [NSPersistentStoreDescription]
public let didFinishLoad = CurrentValueSubject<Bool, Never>(false) public let didFinishLoad = CurrentValueSubject<Bool, Never>(false)
@ -90,8 +92,22 @@ public final class CoreDataStack {
container.viewContext.automaticallyMergesChangesFromParent = true container.viewContext.automaticallyMergesChangesFromParent = true
os_log("%{public}s[%{public}ld], %{public}s: %s", ((#file as NSString).lastPathComponent), #line, #function, storeDescription.debugDescription) os_log("%{public}s[%{public}ld], %{public}s: %s", ((#file as NSString).lastPathComponent), #line, #function, storeDescription.debugDescription)
callback() callback()
#if DEBUG
do {
let storeURL = URL.storeURL(for: AppName.groupID, databaseName: "shared")
let data = try Data(contentsOf: storeURL)
let formatter = ByteCountFormatter()
formatter.allowedUnits = [.useMB]
formatter.countStyle = .file
let size = formatter.string(fromByteCount: Int64(data.count))
CoreDataStack.logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): Database size: \(size)")
} catch {
CoreDataStack.logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): Cannot get database size")
}
#endif
}) })
} }

View File

@ -0,0 +1,70 @@
//
// Instance.swift
// CoreDataStack
//
// Created by Cirno MainasuK on 2021-10-9.
//
import Foundation
import CoreData
public final class Instance: NSManagedObject {
@NSManaged public var domain: String
@NSManaged public private(set) var createdAt: Date
@NSManaged public private(set) var updatedAt: Date
@NSManaged public private(set) var configurationRaw: Data?
// MARK: one-to-many relationships
@NSManaged public var authentications: Set<MastodonAuthentication>
}
extension Instance {
public override func awakeFromInsert() {
super.awakeFromInsert()
let now = Date()
setPrimitiveValue(now, forKey: #keyPath(Instance.createdAt))
setPrimitiveValue(now, forKey: #keyPath(Instance.updatedAt))
}
@discardableResult
public static func insert(
into context: NSManagedObjectContext,
property: Property
) -> Instance {
let instance: Instance = context.insertObject()
instance.domain = property.domain
return instance
}
public func update(configurationRaw: Data?) {
self.configurationRaw = configurationRaw
}
public func didUpdate(at networkDate: Date) {
self.updatedAt = networkDate
}
}
extension Instance {
public struct Property {
public let domain: String
public init(domain: String) {
self.domain = domain
}
}
}
extension Instance: Managed {
public static var defaultSortDescriptors: [NSSortDescriptor] {
return [NSSortDescriptor(keyPath: \Instance.createdAt, ascending: false)]
}
}
extension Instance {
public static func predicate(domain: String) -> NSPredicate {
return NSPredicate(format: "%K == %@", #keyPath(Instance.domain), domain)
}
}

View File

@ -30,6 +30,9 @@ final public class MastodonAuthentication: NSManagedObject {
// one-to-one relationship // one-to-one relationship
@NSManaged public private(set) var user: MastodonUser @NSManaged public private(set) var user: MastodonUser
// many-to-one relationship
@NSManaged public private(set) var instance: Instance?
} }
extension MastodonAuthentication { extension MastodonAuthentication {
@ -97,6 +100,12 @@ extension MastodonAuthentication {
} }
} }
public func update(instance: Instance) {
if self.instance != instance {
self.instance = instance
}
}
public func didUpdate(at networkDate: Date) { public func didUpdate(at networkDate: Date) {
self.updatedAt = networkDate self.updatedAt = networkDate
} }
@ -143,7 +152,7 @@ extension MastodonAuthentication: Managed {
extension MastodonAuthentication { extension MastodonAuthentication {
static func predicate(domain: String) -> NSPredicate { public static func predicate(domain: String) -> NSPredicate {
return NSPredicate(format: "%K == %@", #keyPath(MastodonAuthentication.domain), domain) return NSPredicate(format: "%K == %@", #keyPath(MastodonAuthentication.domain), domain)
} }
@ -158,4 +167,8 @@ extension MastodonAuthentication {
]) ])
} }
public static func predicate(userAccessToken: String) -> NSPredicate {
return NSPredicate(format: "%K == %@", #keyPath(MastodonAuthentication.userAccessToken), userAccessToken)
}
} }

View File

@ -43,11 +43,11 @@ final public class MastodonUser: NSManagedObject {
// one-to-one relationship // one-to-one relationship
@NSManaged public private(set) var pinnedStatus: Status? @NSManaged public private(set) var pinnedStatus: Status?
@NSManaged public private(set) var mastodonAuthentication: MastodonAuthentication? @NSManaged public private(set) var mastodonAuthentication: MastodonAuthentication?
@NSManaged public private(set) var searchHistory: SearchHistory?
// one-to-many relationship // one-to-many relationship
@NSManaged public private(set) var statuses: Set<Status>? @NSManaged public private(set) var statuses: Set<Status>?
@NSManaged public private(set) var notifications: Set<MastodonNotification>? @NSManaged public private(set) var notifications: Set<MastodonNotification>?
@NSManaged public private(set) var searchHistories: Set<SearchHistory>
// many-to-many relationship // many-to-many relationship
@NSManaged public private(set) var favourite: Set<Status>? @NSManaged public private(set) var favourite: Set<Status>?
@ -274,6 +274,15 @@ extension MastodonUser {
} }
extension MastodonUser {
public func findSearchHistory(domain: String, userID: MastodonUser.ID) -> SearchHistory? {
return searchHistories.first { searchHistory in
return searchHistory.domain == domain
&& searchHistory.userID == userID
}
}
}
extension MastodonUser { extension MastodonUser {
public struct Property { public struct Property {
public let identifier: String public let identifier: String

View File

@ -16,7 +16,7 @@ public final class SearchHistory: NSManagedObject {
@NSManaged public private(set) var createAt: Date @NSManaged public private(set) var createAt: Date
@NSManaged public private(set) var updatedAt: Date @NSManaged public private(set) var updatedAt: Date
// one-to-one relationship // many-to-one relationship
@NSManaged public private(set) var account: MastodonUser? @NSManaged public private(set) var account: MastodonUser?
@NSManaged public private(set) var hashtag: Tag? @NSManaged public private(set) var hashtag: Tag?
@NSManaged public private(set) var status: Status? @NSManaged public private(set) var status: Status?
@ -31,10 +31,10 @@ extension SearchHistory {
setPrimitiveValue(Date(), forKey: #keyPath(SearchHistory.updatedAt)) setPrimitiveValue(Date(), forKey: #keyPath(SearchHistory.updatedAt))
} }
public override func willSave() { // public override func willSave() {
super.willSave() // super.willSave()
setPrimitiveValue(Date(), forKey: #keyPath(SearchHistory.updatedAt)) // setPrimitiveValue(Date(), forKey: #keyPath(SearchHistory.updatedAt))
} // }
@discardableResult @discardableResult
public static func insert( public static func insert(

View File

@ -13,7 +13,7 @@ public final class Setting: NSManagedObject {
@NSManaged public var domain: String @NSManaged public var domain: String
@NSManaged public var userID: String @NSManaged public var userID: String
@NSManaged public var appearanceRaw: String // @NSManaged public var appearanceRaw: String
@NSManaged public var preferredTrueBlackDarkMode: Bool @NSManaged public var preferredTrueBlackDarkMode: Bool
@NSManaged public var preferredStaticAvatar: Bool @NSManaged public var preferredStaticAvatar: Bool
@NSManaged public var preferredStaticEmoji: Bool @NSManaged public var preferredStaticEmoji: Bool
@ -41,17 +41,17 @@ extension Setting {
property: Property property: Property
) -> Setting { ) -> Setting {
let setting: Setting = context.insertObject() let setting: Setting = context.insertObject()
setting.appearanceRaw = property.appearanceRaw // setting.appearanceRaw = property.appearanceRaw
setting.domain = property.domain setting.domain = property.domain
setting.userID = property.userID setting.userID = property.userID
return setting return setting
} }
public func update(appearanceRaw: String) { // public func update(appearanceRaw: String) {
guard appearanceRaw != self.appearanceRaw else { return } // guard appearanceRaw != self.appearanceRaw else { return }
self.appearanceRaw = appearanceRaw // self.appearanceRaw = appearanceRaw
didUpdate(at: Date()) // didUpdate(at: Date())
} // }
public func update(preferredTrueBlackDarkMode: Bool) { public func update(preferredTrueBlackDarkMode: Bool) {
guard preferredTrueBlackDarkMode != self.preferredTrueBlackDarkMode else { return } guard preferredTrueBlackDarkMode != self.preferredTrueBlackDarkMode else { return }
@ -87,12 +87,16 @@ extension Setting {
public struct Property { public struct Property {
public let domain: String public let domain: String
public let userID: String public let userID: String
public let appearanceRaw: String // public let appearanceRaw: String
public init(domain: String, userID: String, appearanceRaw: String) { public init(
domain: String,
userID: String
// appearanceRaw: String
) {
self.domain = domain self.domain = domain
self.userID = userID self.userID = userID
self.appearanceRaw = appearanceRaw // self.appearanceRaw = appearanceRaw
} }
} }
} }

View File

@ -52,18 +52,18 @@ public final class Status: NSManagedObject {
// one-to-one relationship // one-to-one relationship
@NSManaged public private(set) var pinnedBy: MastodonUser? @NSManaged public private(set) var pinnedBy: MastodonUser?
@NSManaged public private(set) var poll: Poll? @NSManaged public private(set) var poll: Poll?
@NSManaged public private(set) var searchHistory: SearchHistory?
// one-to-many relationship // one-to-many relationship
@NSManaged public private(set) var reblogFrom: Set<Status>? @NSManaged public private(set) var reblogFrom: Set<Status>?
@NSManaged public private(set) var mentions: Set<Mention>? @NSManaged public private(set) var mentions: Set<Mention>?
@NSManaged public private(set) var tags: Set<Tag>?
@NSManaged public private(set) var homeTimelineIndexes: Set<HomeTimelineIndex>? @NSManaged public private(set) var homeTimelineIndexes: Set<HomeTimelineIndex>?
@NSManaged public private(set) var mediaAttachments: Set<Attachment>? @NSManaged public private(set) var mediaAttachments: Set<Attachment>?
@NSManaged public private(set) var replyFrom: Set<Status>? @NSManaged public private(set) var replyFrom: Set<Status>?
@NSManaged public private(set) var inNotifications: Set<MastodonNotification>? @NSManaged public private(set) var inNotifications: Set<MastodonNotification>?
@NSManaged public private(set) var searchHistories: Set<SearchHistory>
@NSManaged public private(set) var updatedAt: Date @NSManaged public private(set) var updatedAt: Date
@NSManaged public private(set) var deletedAt: Date? @NSManaged public private(set) var deletedAt: Date?
@NSManaged public private(set) var revealedAt: Date? @NSManaged public private(set) var revealedAt: Date?
@ -81,7 +81,6 @@ extension Status {
replyTo: Status?, replyTo: Status?,
poll: Poll?, poll: Poll?,
mentions: [Mention]?, mentions: [Mention]?,
tags: [Tag]?,
mediaAttachments: [Attachment]?, mediaAttachments: [Attachment]?,
favouritedBy: MastodonUser?, favouritedBy: MastodonUser?,
rebloggedBy: MastodonUser?, rebloggedBy: MastodonUser?,
@ -126,9 +125,6 @@ extension Status {
if let mentions = mentions { if let mentions = mentions {
status.mutableSetValue(forKey: #keyPath(Status.mentions)).addObjects(from: mentions) status.mutableSetValue(forKey: #keyPath(Status.mentions)).addObjects(from: mentions)
} }
if let tags = tags {
status.mutableSetValue(forKey: #keyPath(Status.tags)).addObjects(from: tags)
}
if let mediaAttachments = mediaAttachments { if let mediaAttachments = mediaAttachments {
status.mutableSetValue(forKey: #keyPath(Status.mediaAttachments)).addObjects(from: mediaAttachments) status.mutableSetValue(forKey: #keyPath(Status.mediaAttachments)).addObjects(from: mediaAttachments)
} }

View File

@ -18,13 +18,12 @@ public final class Tag: NSManagedObject {
@NSManaged public private(set) var url: String @NSManaged public private(set) var url: String
// one-to-one relationship // one-to-one relationship
@NSManaged public private(set) var searchHistory: SearchHistory?
// many-to-many relationship // many-to-many relationship
@NSManaged public private(set) var statuses: Set<Status>?
// one-to-many relationship // one-to-many relationship
@NSManaged public private(set) var histories: Set<History>? @NSManaged public private(set) var histories: Set<History>?
@NSManaged public private(set) var searchHistories: Set<SearchHistory>
} }
public extension Tag { public extension Tag {
@ -55,6 +54,15 @@ public extension Tag {
} }
} }
extension Tag {
public func findSearchHistory(domain: String, userID: MastodonUser.ID) -> SearchHistory? {
return searchHistories.first { searchHistory in
return searchHistory.domain == domain
&& searchHistory.userID == userID
}
}
}
public extension Tag { public extension Tag {
struct Property { struct Property {
public let name: String public let name: String

View File

@ -15,8 +15,8 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string> <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.0.8</string> <string>1.2.0</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>60</string> <string>88</string>
</dict> </dict>
</plist> </plist>

View File

@ -15,8 +15,8 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string> <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.0.8</string> <string>1.2.0</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>60</string> <string>88</string>
</dict> </dict>
</plist> </plist>

View File

@ -2,6 +2,28 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>a11y.plural.count.unread.notification</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@notification_count_unread_notification@</string>
<key>notification_count_unread_notification</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>zero</key>
<string>no unread notification</string>
<key>one</key>
<string>1 unread notification</string>
<key>few</key>
<string>%ld unread notifications</string>
<key>many</key>
<string>%ld unread notification</string>
<key>other</key>
<string>%ld unread notification</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_exceeds</key> <key>a11y.plural.count.input_limit_exceeds</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>

View File

@ -1,51 +1,51 @@
"16wxgf" = "Post on Mastodon"; "16wxgf" = "النَشر على ماستودون";
"751xkl" = "Text Content"; "751xkl" = "محتوى نصي";
"CsR7G2" = "Post on Mastodon"; "CsR7G2" = "انشر على ماستدون";
"HZSGTr" = "What content to post?"; "HZSGTr" = "ما المُحتوى المُراد نشره؟";
"HdGikU" = "Posting failed"; "HdGikU" = "فَشَلَ النشر";
"KDNTJ4" = "Failure Reason"; "KDNTJ4" = "سبب الإخفاق";
"RHxKOw" = "Send Post with text content"; "RHxKOw" = "إرسال مَنشور يَحوي نص";
"RxSqsb" = "Post"; "RxSqsb" = "مَنشور";
"WCIR3D" = "Post ${content} on Mastodon"; "WCIR3D" = "نَشر ${content} على ماستودون";
"ZKJSNu" = "Post"; "ZKJSNu" = "مَنشور";
"ZS1XaK" = "${content}"; "ZS1XaK" = "${content}";
"ZbSjzC" = "Visibility"; "ZbSjzC" = "مدى الظهور";
"Zo4jgJ" = "Post Visibility"; "Zo4jgJ" = "مدى ظهور المنشور";
"apSxMG-dYQ5NN" = "There are ${count} options matching Public."; "apSxMG-dYQ5NN" = "هُناك عدد ${count} خِيار مُطابق لِـ\"عام\".";
"apSxMG-ehFLjY" = "There are ${count} options matching Followers Only."; "apSxMG-ehFLjY" = "هُناك عدد ${count} خِيار مُطابق لِـ\"المُتابِعُون فقط\".";
"ayoYEb-dYQ5NN" = "${content}, Public"; "ayoYEb-dYQ5NN" = "${content}، عام";
"ayoYEb-ehFLjY" = "${content}, Followers Only"; "ayoYEb-ehFLjY" = "${content}، المُتابِعُون فقط";
"dUyuGg" = "Post on Mastodon"; "dUyuGg" = "النشر على ماستدون";
"dYQ5NN" = "Public"; "dYQ5NN" = "للعامة";
"ehFLjY" = "Followers Only"; "ehFLjY" = "لمتابعيك فقط";
"gfePDu" = "Posting failed. ${failureReason}"; "gfePDu" = "فَشَلَ النشر، ${failureReason}";
"k7dbKQ" = "Post was sent successfully."; "k7dbKQ" = "تمَّ إرسال المنشور بِنجاح.";
"oGiqmY-dYQ5NN" = "Just to confirm, you wanted Public?"; "oGiqmY-dYQ5NN" = "للتأكيد، هل تَريد \"عام\"؟";
"oGiqmY-ehFLjY" = "Just to confirm, you wanted Followers Only?"; "oGiqmY-ehFLjY" = "للتأكيد، هل تُريد \"للمُتابِعين فقط\"؟";
"rM6dvp" = "URL"; "rM6dvp" = "عنوان URL";
"ryJLwG" = "Post was sent successfully. "; "ryJLwG" = "تم إرسال المنشور بنجاح. ";

View File

@ -5,7 +5,7 @@
<key>There are ${count} options matching ${content}. - 2</key> <key>There are ${count} options matching ${content}. - 2</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>
<string>There are %#@count_option@ matching ${content}.</string> <string>هُناك %#@count_option@ تتطابق مَعَ '${content}'.</string>
<key>count_option</key> <key>count_option</key>
<dict> <dict>
<key>NSStringFormatSpecTypeKey</key> <key>NSStringFormatSpecTypeKey</key>
@ -13,23 +13,23 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>%ld</string> <string>%ld</string>
<key>zero</key> <key>zero</key>
<string>%ld options</string> <string>لا خيار</string>
<key>one</key> <key>one</key>
<string>1 option</string> <string>خيار واحد</string>
<key>two</key> <key>two</key>
<string>%ld options</string> <string>خياران</string>
<key>few</key> <key>few</key>
<string>%ld options</string> <string>%ld خيارات</string>
<key>many</key> <key>many</key>
<string>%ld options</string> <string>%ld خيارًا</string>
<key>other</key> <key>other</key>
<string>%ld options</string> <string>%ld خيار</string>
</dict> </dict>
</dict> </dict>
<key>There are ${count} options matching ${visibility}.</key> <key>There are ${count} options matching ${visibility}.</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>
<string>There are %#@count_option@ matching ${visibility}.</string> <string>هُناك %#@count_option@ تتطابق مَعَ '${visibility}'.</string>
<key>count_option</key> <key>count_option</key>
<dict> <dict>
<key>NSStringFormatSpecTypeKey</key> <key>NSStringFormatSpecTypeKey</key>
@ -37,17 +37,17 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>%ld</string> <string>%ld</string>
<key>zero</key> <key>zero</key>
<string>%ld options</string> <string>لا خيار</string>
<key>one</key> <key>one</key>
<string>1 option</string> <string>خيار واحد</string>
<key>two</key> <key>two</key>
<string>%ld options</string> <string>خياران</string>
<key>few</key> <key>few</key>
<string>%ld options</string> <string>%ld خيارات</string>
<key>many</key> <key>many</key>
<string>%ld options</string> <string>%ld خيارًا</string>
<key>other</key> <key>other</key>
<string>%ld options</string> <string>%ld خيار</string>
</dict> </dict>
</dict> </dict>
</dict> </dict>

View File

@ -1,28 +1,28 @@
"16wxgf" = "Post on Mastodon"; "16wxgf" = "Publier sur Mastodon";
"751xkl" = "Text Content"; "751xkl" = "Contenu textuel";
"CsR7G2" = "Post on Mastodon"; "CsR7G2" = "Publier sur Mastodon";
"HZSGTr" = "What content to post?"; "HZSGTr" = "Quel contenu à publier ?";
"HdGikU" = "Posting failed"; "HdGikU" = "Échec lors de la publication";
"KDNTJ4" = "Failure Reason"; "KDNTJ4" = "Raison de léchec";
"RHxKOw" = "Send Post with text content"; "RHxKOw" = "Envoyer une publication avec du contenu texte";
"RxSqsb" = "Post"; "RxSqsb" = "Post";
"WCIR3D" = "Post ${content} on Mastodon"; "WCIR3D" = "Publier du ${content} sur Mastodon";
"ZKJSNu" = "Post"; "ZKJSNu" = "Publication";
"ZS1XaK" = "${content}"; "ZS1XaK" = "${content}";
"ZbSjzC" = "Visibility"; "ZbSjzC" = "Visibilité";
"Zo4jgJ" = "Post Visibility"; "Zo4jgJ" = "Visibilité de la publication";
"apSxMG-dYQ5NN" = "There are ${count} options matching Public."; "apSxMG-dYQ5NN" = "There are ${count} options matching Public.";
@ -30,22 +30,22 @@
"ayoYEb-dYQ5NN" = "${content}, Public"; "ayoYEb-dYQ5NN" = "${content}, Public";
"ayoYEb-ehFLjY" = "${content}, Followers Only"; "ayoYEb-ehFLjY" = "${content}, abonné·e·s seulement";
"dUyuGg" = "Post on Mastodon"; "dUyuGg" = "Publier sur Mastodon";
"dYQ5NN" = "Public"; "dYQ5NN" = "Public";
"ehFLjY" = "Followers Only"; "ehFLjY" = "Abonné·e·s seulement";
"gfePDu" = "Posting failed. ${failureReason}"; "gfePDu" = "Échec lors de la publication. ${failureReason}";
"k7dbKQ" = "Post was sent successfully."; "k7dbKQ" = "Message publié avec succès.";
"oGiqmY-dYQ5NN" = "Just to confirm, you wanted Public?"; "oGiqmY-dYQ5NN" = "Juste pour confirmer, vous vouliez « Public » ?";
"oGiqmY-ehFLjY" = "Just to confirm, you wanted Followers Only?"; "oGiqmY-ehFLjY" = "Juste pour confirmer, vous vouliez bien diffuser vers « abonné·e·s uniquement » ?";
"rM6dvp" = "URL"; "rM6dvp" = "URL";
"ryJLwG" = "Post was sent successfully. "; "ryJLwG" = "La publication a été envoyée avec succès. ";

View File

@ -5,7 +5,7 @@
<key>There are ${count} options matching ${content}. - 2</key> <key>There are ${count} options matching ${content}. - 2</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>
<string>There are %#@count_option@ matching ${content}.</string> <string>Il y a %#@count_option@ correspondant à « ${content} ».</string>
<key>count_option</key> <key>count_option</key>
<dict> <dict>
<key>NSStringFormatSpecTypeKey</key> <key>NSStringFormatSpecTypeKey</key>
@ -21,7 +21,7 @@
<key>There are ${count} options matching ${visibility}.</key> <key>There are ${count} options matching ${visibility}.</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>
<string>There are %#@count_option@ matching ${visibility}.</string> <string>Il y a %#@count_option@ correspondant à « ${visibility} ».</string>
<key>count_option</key> <key>count_option</key>
<dict> <dict>
<key>NSStringFormatSpecTypeKey</key> <key>NSStringFormatSpecTypeKey</key>

View File

@ -24,9 +24,9 @@
"Zo4jgJ" = "Faicsinneachd a phuist"; "Zo4jgJ" = "Faicsinneachd a phuist";
"apSxMG-dYQ5NN" = "There are ${count} options matching Public."; "apSxMG-dYQ5NN" = "Tha ${count} roghainn(ean) dha “Poblach” ann.";
"apSxMG-ehFLjY" = "There are ${count} options matching Followers Only."; "apSxMG-ehFLjY" = "Tha ${count} roghainn(ean) dha “Luchd-leantainn a-mhàin” ann.";
"ayoYEb-dYQ5NN" = "${content}, poblach"; "ayoYEb-dYQ5NN" = "${content}, poblach";

View File

@ -13,11 +13,11 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>%ld</string> <string>%ld</string>
<key>one</key> <key>one</key>
<string>1 option</string> <string>%ld roghainn</string>
<key>two</key> <key>two</key>
<string>%ld options</string> <string>%ld roghainn</string>
<key>few</key> <key>few</key>
<string>%ld options</string> <string>%ld roghainnean</string>
<key>other</key> <key>other</key>
<string>%ld roghainn</string> <string>%ld roghainn</string>
</dict> </dict>
@ -33,11 +33,11 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>%ld</string> <string>%ld</string>
<key>one</key> <key>one</key>
<string>1 option</string> <string>%ld roghainn</string>
<key>two</key> <key>two</key>
<string>%ld options</string> <string>%ld roghainn</string>
<key>few</key> <key>few</key>
<string>%ld options</string> <string>%ld roghainnean</string>
<key>other</key> <key>other</key>
<string>%ld roghainn</string> <string>%ld roghainn</string>
</dict> </dict>

View File

@ -0,0 +1,51 @@
"16wxgf" = "Di Mastodon de biweşîne";
"751xkl" = "Naveroka nivîsê";
"CsR7G2" = "Di Mastodon de biweşîne";
"HZSGTr" = "Kîjan naverok bila bê şandin?";
"HdGikU" = "Şandin têkçû";
"KDNTJ4" = "Sedema têkçûnê";
"RHxKOw" = "Bi naveroka nivîsî şandiyan bişîne";
"RxSqsb" = "Şandî";
"WCIR3D" = "${content} biweşîne di Mastodon de";
"ZKJSNu" = "Şandî";
"ZS1XaK" = "${content}";
"ZbSjzC" = "Xuyanî";
"Zo4jgJ" = "Xuyaniya şandiyê";
"apSxMG-dYQ5NN" = "Vebijarkên ${count} hene ku li gorî 'Gelemperî' ne.";
"apSxMG-ehFLjY" = "Vebijarkên ${count} hene ku li gorî 'Tenê Şopaneran' hene.";
"ayoYEb-dYQ5NN" = "${content}, Gelemperî";
"ayoYEb-ehFLjY" = "${content}, Tenê şopînêr";
"dUyuGg" = "Di Mastodon de biweşîne";
"dYQ5NN" = "Gelemperî";
"ehFLjY" = "Tenê şopîneran";
"gfePDu" = "Weşandin bi ser neket. ${failureReason}";
"k7dbKQ" = "Şandî bi serkeftî hate şandin.";
"oGiqmY-dYQ5NN" = "Tenê ji bo pejirandinê, te 'Gelemperî' dixwest?";
"oGiqmY-ehFLjY" = "Tenê ji bo pejirandinê, te 'Tenê Şopîner' dixwest?";
"rM6dvp" = "Girêdan";
"ryJLwG" = "Şandî bi serkeftî hate şandin. ";

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>There are ${count} options matching ${content}. - 2</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count_option@ heye ku bi ${content} re têkildar e.</string>
<key>count_option</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>%ld</string>
<key>one</key>
<string>1 vebijêrk</string>
<key>other</key>
<string>%ld vebijêrk</string>
</dict>
</dict>
<key>There are ${count} options matching ${visibility}.</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count_option@ heye ku bi ${visibility} re têkildar e.</string>
<key>count_option</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>%ld</string>
<key>one</key>
<string>1 vebijêrk</string>
<key>other</key>
<string>%ld vebijêrk</string>
</dict>
</dict>
</dict>
</plist>

View File

@ -5,7 +5,7 @@
<key>There are ${count} options matching ${content}. - 2</key> <key>There are ${count} options matching ${content}. - 2</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>
<string>There are %#@count_option@ matching ${content}.</string> <string>Er zijn %#@count_option@ die overeenkomen met ${content}.</string>
<key>count_option</key> <key>count_option</key>
<dict> <dict>
<key>NSStringFormatSpecTypeKey</key> <key>NSStringFormatSpecTypeKey</key>
@ -13,7 +13,7 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>%ld</string> <string>%ld</string>
<key>one</key> <key>one</key>
<string>1 option</string> <string>1 optie</string>
<key>other</key> <key>other</key>
<string>%ld options</string> <string>%ld options</string>
</dict> </dict>
@ -21,7 +21,7 @@
<key>There are ${count} options matching ${visibility}.</key> <key>There are ${count} options matching ${visibility}.</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>
<string>There are %#@count_option@ matching ${visibility}.</string> <string>Er zijn %#@count_option@ die overeenkomen met ${visibility}.</string>
<key>count_option</key> <key>count_option</key>
<dict> <dict>
<key>NSStringFormatSpecTypeKey</key> <key>NSStringFormatSpecTypeKey</key>
@ -29,7 +29,7 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>%ld</string> <string>%ld</string>
<key>one</key> <key>one</key>
<string>1 option</string> <string>1 optie</string>
<key>other</key> <key>other</key>
<string>%ld options</string> <string>%ld options</string>
</dict> </dict>

View File

@ -51,6 +51,7 @@ private func map(language: String) -> String? {
case "fr_FR": return "fr" // French case "fr_FR": return "fr" // French
case "de_DE": return "de" // German case "de_DE": return "de" // German
case "ja_JP": return "ja" // Japanese case "ja_JP": return "ja" // Japanese
case "kmr_TR": return "ku-TR" // Kurmanji (Kurdish)
case "ru_RU": return "ru" // Russian case "ru_RU": return "ru" // Russian
case "gd_GB": return "gd-GB" // Scottish Gaelic case "gd_GB": return "gd-GB" // Scottish Gaelic
case "es_ES": return "es" // Spanish case "es_ES": return "es" // Spanish

View File

@ -2,10 +2,34 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>a11y.plural.count.unread.notification</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@notification_count_unread_notification@</string>
<key>notification_count_unread_notification</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>zero</key>
<string>لا إشعار غير مقروء</string>
<key>one</key>
<string>إشعار واحِد غير مقروء</string>
<key>two</key>
<string>إشعاران غير مقروءان</string>
<key>few</key>
<string>%ld إشعارات غير مقروءة</string>
<key>many</key>
<string>%ld إشعارًا غيرَ مقروء</string>
<key>other</key>
<string>%ld إشعار غير مقروء</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_exceeds</key> <key>a11y.plural.count.input_limit_exceeds</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>
<string>Input limit exceeds %#@character_count@</string> <string>تمَّ تجاوز حدّ الإدخال %#@character_count@</string>
<key>character_count</key> <key>character_count</key>
<dict> <dict>
<key>NSStringFormatSpecTypeKey</key> <key>NSStringFormatSpecTypeKey</key>
@ -13,23 +37,23 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>zero</key> <key>zero</key>
<string>%ld characters</string> <string>لا حرف</string>
<key>one</key> <key>one</key>
<string>1 character</string> <string>حرفٌ واحِد</string>
<key>two</key> <key>two</key>
<string>%ld characters</string> <string>حرفان اثنان</string>
<key>few</key> <key>few</key>
<string>%ld characters</string> <string>%ld حُرُوف</string>
<key>many</key> <key>many</key>
<string>%ld characters</string> <string>%ld حرفًا</string>
<key>other</key> <key>other</key>
<string>%ld characters</string> <string>%ld حَرف</string>
</dict> </dict>
</dict> </dict>
<key>a11y.plural.count.input_limit_remains</key> <key>a11y.plural.count.input_limit_remains</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>
<string>Input limit remains %#@character_count@</string> <string>يتبقَّى على حدّ الإدخال %#@character_count@</string>
<key>character_count</key> <key>character_count</key>
<dict> <dict>
<key>NSStringFormatSpecTypeKey</key> <key>NSStringFormatSpecTypeKey</key>
@ -37,17 +61,17 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>zero</key> <key>zero</key>
<string>%ld characters</string> <string>لا حرف</string>
<key>one</key> <key>one</key>
<string>1 character</string> <string>حرفٌ واحِد</string>
<key>two</key> <key>two</key>
<string>%ld characters</string> <string>حرفان اثنان</string>
<key>few</key> <key>few</key>
<string>%ld characters</string> <string>%ld حُرُوف</string>
<key>many</key> <key>many</key>
<string>%ld characters</string> <string>%ld حرفًا</string>
<key>other</key> <key>other</key>
<string>%ld characters</string> <string>%ld حَرف</string>
</dict> </dict>
</dict> </dict>
<key>plural.count.metric_formatted.post</key> <key>plural.count.metric_formatted.post</key>
@ -61,17 +85,17 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>zero</key> <key>zero</key>
<string>posts</string> <string>لا منشور</string>
<key>one</key> <key>one</key>
<string>post</string> <string>منشور</string>
<key>two</key> <key>two</key>
<string>posts</string> <string>منشوران</string>
<key>few</key> <key>few</key>
<string>posts</string> <string>منشورات</string>
<key>many</key> <key>many</key>
<string>posts</string> <string>منشورًا</string>
<key>other</key> <key>other</key>
<string>posts</string> <string>منشور</string>
</dict> </dict>
</dict> </dict>
<key>plural.count.post</key> <key>plural.count.post</key>
@ -85,17 +109,17 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>zero</key> <key>zero</key>
<string>%ld posts</string> <string>لا منشور</string>
<key>one</key> <key>one</key>
<string>1 post</string> <string>منشورٌ واحِد</string>
<key>two</key> <key>two</key>
<string>%ld posts</string> <string>منشورانِ اثنان</string>
<key>few</key> <key>few</key>
<string>%ld posts</string> <string>%ld منشورات</string>
<key>many</key> <key>many</key>
<string>%ld posts</string> <string>%ld منشورًا</string>
<key>other</key> <key>other</key>
<string>%ld posts</string> <string>%ld منشور</string>
</dict> </dict>
</dict> </dict>
<key>plural.count.favorite</key> <key>plural.count.favorite</key>
@ -109,17 +133,17 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>zero</key> <key>zero</key>
<string>%ld favorites</string> <string>لا إعجاب</string>
<key>one</key> <key>one</key>
<string>1 favorite</string> <string>إعجابٌ واحِد</string>
<key>two</key> <key>two</key>
<string>%ld favorites</string> <string>إعجابانِ اثنان</string>
<key>few</key> <key>few</key>
<string>%ld favorites</string> <string>%ld إعجابات</string>
<key>many</key> <key>many</key>
<string>%ld favorites</string> <string>%ld إعجابًا</string>
<key>other</key> <key>other</key>
<string>%ld favorites</string> <string>%ld إعجاب</string>
</dict> </dict>
</dict> </dict>
<key>plural.count.reblog</key> <key>plural.count.reblog</key>
@ -133,17 +157,17 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>zero</key> <key>zero</key>
<string>%ld reblogs</string> <string>لا إعاد تدوين</string>
<key>one</key> <key>one</key>
<string>1 reblog</string> <string>إعادةُ تدوينٍ واحِدة</string>
<key>two</key> <key>two</key>
<string>%ld reblogs</string> <string>إعادتا تدوين</string>
<key>few</key> <key>few</key>
<string>%ld reblogs</string> <string>%ld إعاداتِ تدوين</string>
<key>many</key> <key>many</key>
<string>%ld reblogs</string> <string>%ld إعادةٍ للتدوين</string>
<key>other</key> <key>other</key>
<string>%ld reblogs</string> <string>%ld إعادة تدوين</string>
</dict> </dict>
</dict> </dict>
<key>plural.count.vote</key> <key>plural.count.vote</key>
@ -157,17 +181,17 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>zero</key> <key>zero</key>
<string>%ld votes</string> <string>لا صوت</string>
<key>one</key> <key>one</key>
<string>1 vote</string> <string>صوتٌ واحِد</string>
<key>two</key> <key>two</key>
<string>%ld votes</string> <string>صوتانِ اثنان</string>
<key>few</key> <key>few</key>
<string>%ld votes</string> <string>%ld أصوات</string>
<key>many</key> <key>many</key>
<string>%ld votes</string> <string>%ld صوتًا</string>
<key>other</key> <key>other</key>
<string>%ld votes</string> <string>%ld صوت</string>
</dict> </dict>
</dict> </dict>
<key>plural.count.voter</key> <key>plural.count.voter</key>
@ -181,17 +205,17 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>zero</key> <key>zero</key>
<string>%ld voters</string> <string>لا مُصوِّتون</string>
<key>one</key> <key>one</key>
<string>1 voter</string> <string>مُصوِّتٌ واحِد</string>
<key>two</key> <key>two</key>
<string>%ld voters</string> <string>مُصوِّتانِ اثنان</string>
<key>few</key> <key>few</key>
<string>%ld voters</string> <string>%ld مُصوِّتين</string>
<key>many</key> <key>many</key>
<string>%ld voters</string> <string>%ld مُصوِّتًا</string>
<key>other</key> <key>other</key>
<string>%ld voters</string> <string>%ld مُصوِّت</string>
</dict> </dict>
</dict> </dict>
<key>plural.people_talking</key> <key>plural.people_talking</key>
@ -205,17 +229,17 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>zero</key> <key>zero</key>
<string>%ld people talking</string> <string>لا أحَدَ يتحدَّث</string>
<key>one</key> <key>one</key>
<string>1 people talking</string> <string>شخصٌ واحدٌ يتحدَّث</string>
<key>two</key> <key>two</key>
<string>%ld people talking</string> <string>شخصانِ اثنان يتحدَّثا</string>
<key>few</key> <key>few</key>
<string>%ld people talking</string> <string>%ld أشخاصٍ يتحدَّثون</string>
<key>many</key> <key>many</key>
<string>%ld people talking</string> <string>%ld شخصًا يتحدَّثون</string>
<key>other</key> <key>other</key>
<string>%ld people talking</string> <string>%ld شخصٍ يتحدَّثون</string>
</dict> </dict>
</dict> </dict>
<key>plural.count.following</key> <key>plural.count.following</key>
@ -229,17 +253,17 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>zero</key> <key>zero</key>
<string>%ld following</string> <string>لا مُتابَع</string>
<key>one</key> <key>one</key>
<string>1 following</string> <string>مُتابَعٌ واحد</string>
<key>two</key> <key>two</key>
<string>%ld following</string> <string>مُتابَعانِ</string>
<key>few</key> <key>few</key>
<string>%ld following</string> <string>%ld مُتابَعين</string>
<key>many</key> <key>many</key>
<string>%ld following</string> <string>%ld مُتابَعًا</string>
<key>other</key> <key>other</key>
<string>%ld following</string> <string>%ld مُتابَع</string>
</dict> </dict>
</dict> </dict>
<key>plural.count.follower</key> <key>plural.count.follower</key>
@ -253,17 +277,17 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>zero</key> <key>zero</key>
<string>%ld followers</string> <string>لا مُتابِع</string>
<key>one</key> <key>one</key>
<string>1 follower</string> <string>مُتابِعٌ واحد</string>
<key>two</key> <key>two</key>
<string>%ld followers</string> <string>مُتابِعانِ اثنان</string>
<key>few</key> <key>few</key>
<string>%ld followers</string> <string>%ld مُتابِعين</string>
<key>many</key> <key>many</key>
<string>%ld followers</string> <string>%ld مُتابِعًا</string>
<key>other</key> <key>other</key>
<string>%ld followers</string> <string>%ld مُتابِع</string>
</dict> </dict>
</dict> </dict>
<key>date.year.left</key> <key>date.year.left</key>
@ -277,17 +301,17 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>zero</key> <key>zero</key>
<string>%ld years left</string> <string>تتبقى لَحظة</string>
<key>one</key> <key>one</key>
<string>1 year left</string> <string>تتبقى سنة</string>
<key>two</key> <key>two</key>
<string>%ld years left</string> <string>تتبقى سنتين</string>
<key>few</key> <key>few</key>
<string>%ld years left</string> <string>تتبقى %ld سنوات</string>
<key>many</key> <key>many</key>
<string>%ld years left</string> <string>تتبقى %ld سنةً</string>
<key>other</key> <key>other</key>
<string>%ld years left</string> <string>تتبقى %ld سنة</string>
</dict> </dict>
</dict> </dict>
<key>date.month.left</key> <key>date.month.left</key>
@ -301,17 +325,17 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>zero</key> <key>zero</key>
<string>%ld months left</string> <string>تتبقى لَحظة</string>
<key>one</key> <key>one</key>
<string>1 months left</string> <string>يتبقى شهر</string>
<key>two</key> <key>two</key>
<string>%ld months left</string> <string>يتبقى شهرين</string>
<key>few</key> <key>few</key>
<string>%ld months left</string> <string>يتبقى %ld أشهر</string>
<key>many</key> <key>many</key>
<string>%ld months left</string> <string>يتبقى %ld شهرًا</string>
<key>other</key> <key>other</key>
<string>%ld months left</string> <string>يتبقى %ld شهر</string>
</dict> </dict>
</dict> </dict>
<key>date.day.left</key> <key>date.day.left</key>
@ -325,17 +349,17 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>zero</key> <key>zero</key>
<string>%ld days left</string> <string>تتبقى لحظة</string>
<key>one</key> <key>one</key>
<string>1 day left</string> <string>يتبقى يوم</string>
<key>two</key> <key>two</key>
<string>%ld days left</string> <string>يتبقى يومين</string>
<key>few</key> <key>few</key>
<string>%ld days left</string> <string>يتبقى %ld أيام</string>
<key>many</key> <key>many</key>
<string>%ld days left</string> <string>يتبقى %ld يومًا</string>
<key>other</key> <key>other</key>
<string>%ld days left</string> <string>يتبقى %ld يوم</string>
</dict> </dict>
</dict> </dict>
<key>date.hour.left</key> <key>date.hour.left</key>
@ -349,17 +373,17 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>zero</key> <key>zero</key>
<string>%ld hours left</string> <string>تتبقى لَحظة</string>
<key>one</key> <key>one</key>
<string>1 hour left</string> <string>تتبقى ساعة</string>
<key>two</key> <key>two</key>
<string>%ld hours left</string> <string>تتبقى ساعتين</string>
<key>few</key> <key>few</key>
<string>%ld hours left</string> <string>تتبقى %ld ساعات</string>
<key>many</key> <key>many</key>
<string>%ld hours left</string> <string>تتبقى %ld ساعةً</string>
<key>other</key> <key>other</key>
<string>%ld hours left</string> <string>تتبقى %ld ساعة</string>
</dict> </dict>
</dict> </dict>
<key>date.minute.left</key> <key>date.minute.left</key>
@ -373,17 +397,17 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>zero</key> <key>zero</key>
<string>%ld minutes left</string> <string>تتبقى لَحظة</string>
<key>one</key> <key>one</key>
<string>1 minute left</string> <string>تتبقى دقيقة</string>
<key>two</key> <key>two</key>
<string>%ld minutes left</string> <string>تتبقى دقيقتين</string>
<key>few</key> <key>few</key>
<string>%ld minutes left</string> <string>تتبقى %ld دقائق</string>
<key>many</key> <key>many</key>
<string>%ld minutes left</string> <string>تتبقى %ld دقيقةً</string>
<key>other</key> <key>other</key>
<string>%ld minutes left</string> <string>تتبقى %ld دقيقة</string>
</dict> </dict>
</dict> </dict>
<key>date.second.left</key> <key>date.second.left</key>
@ -397,17 +421,17 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>zero</key> <key>zero</key>
<string>%ld seconds left</string> <string>تتبقى لَحظة</string>
<key>one</key> <key>one</key>
<string>1 second left</string> <string>تتبقى ثانية</string>
<key>two</key> <key>two</key>
<string>%ld seconds left</string> <string>تتبقى ثانيتين</string>
<key>few</key> <key>few</key>
<string>%ld seconds left</string> <string>تتبقى %ld ثوان</string>
<key>many</key> <key>many</key>
<string>%ld seconds left</string> <string>تتبقى %ld ثانيةً</string>
<key>other</key> <key>other</key>
<string>%ld seconds left</string> <string>تتبقى %ld ثانية</string>
</dict> </dict>
</dict> </dict>
<key>date.year.ago.abbr</key> <key>date.year.ago.abbr</key>
@ -421,17 +445,17 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>zero</key> <key>zero</key>
<string>%ldy ago</string> <string>مُنذُ لَحظة</string>
<key>one</key> <key>one</key>
<string>1y ago</string> <string>مُنذُ سنة</string>
<key>two</key> <key>two</key>
<string>%ldy ago</string> <string>مُنذُ سنتين</string>
<key>few</key> <key>few</key>
<string>%ldy ago</string> <string>مُنذُ %ld سنين</string>
<key>many</key> <key>many</key>
<string>%ldy ago</string> <string>مُنذُ %ld سنةً</string>
<key>other</key> <key>other</key>
<string>%ldy ago</string> <string>مُنذُ %ld سنة</string>
</dict> </dict>
</dict> </dict>
<key>date.month.ago.abbr</key> <key>date.month.ago.abbr</key>
@ -445,17 +469,17 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>zero</key> <key>zero</key>
<string>%ldM ago</string> <string>مُنذُ لَحظة</string>
<key>one</key> <key>one</key>
<string>1M ago</string> <string>مُنذُ شهر</string>
<key>two</key> <key>two</key>
<string>%ldM ago</string> <string>مُنذُ شهرين</string>
<key>few</key> <key>few</key>
<string>%ldM ago</string> <string>مُنذُ %ld أشهُر</string>
<key>many</key> <key>many</key>
<string>%ldM ago</string> <string>مُنذُ %ld شهرًا</string>
<key>other</key> <key>other</key>
<string>%ldM ago</string> <string>مُنذُ %ld شهر</string>
</dict> </dict>
</dict> </dict>
<key>date.day.ago.abbr</key> <key>date.day.ago.abbr</key>
@ -469,17 +493,17 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>zero</key> <key>zero</key>
<string>%ldd ago</string> <string>مُنذُ لَحظة</string>
<key>one</key> <key>one</key>
<string>1d ago</string> <string>مُنذُ يوم</string>
<key>two</key> <key>two</key>
<string>%ldd ago</string> <string>مُنذُ يومين</string>
<key>few</key> <key>few</key>
<string>%ldd ago</string> <string>مُنذُ %ld أيام</string>
<key>many</key> <key>many</key>
<string>%ldd ago</string> <string>مُنذُ %ld يومًا</string>
<key>other</key> <key>other</key>
<string>%ldd ago</string> <string>مُنذُ %ld يوم</string>
</dict> </dict>
</dict> </dict>
<key>date.hour.ago.abbr</key> <key>date.hour.ago.abbr</key>
@ -493,17 +517,17 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>zero</key> <key>zero</key>
<string>%ldh ago</string> <string>مُنذُ لَحظة</string>
<key>one</key> <key>one</key>
<string>1h ago</string> <string>مُنذُ ساعة</string>
<key>two</key> <key>two</key>
<string>%ldh ago</string> <string>مُنذُ ساعتين</string>
<key>few</key> <key>few</key>
<string>%ldh ago</string> <string>مُنذُ %ld ساعات</string>
<key>many</key> <key>many</key>
<string>%ldh ago</string> <string>مُنذُ %ld ساعةًَ</string>
<key>other</key> <key>other</key>
<string>%ldh ago</string> <string>مُنذُ %ld ساعة</string>
</dict> </dict>
</dict> </dict>
<key>date.minute.ago.abbr</key> <key>date.minute.ago.abbr</key>
@ -517,17 +541,17 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>zero</key> <key>zero</key>
<string>%ldm ago</string> <string>مُنذُ لَحظة</string>
<key>one</key> <key>one</key>
<string>1m ago</string> <string>مُنذُ دقيقة</string>
<key>two</key> <key>two</key>
<string>%ldm ago</string> <string>مُنذُ دقيقتان</string>
<key>few</key> <key>few</key>
<string>%ldm ago</string> <string>مُنذُ %ld دقائق</string>
<key>many</key> <key>many</key>
<string>%ldm ago</string> <string>مُنذُ %ld دقيقةً</string>
<key>other</key> <key>other</key>
<string>%ldm ago</string> <string>مُنذُ %ld دقيقة</string>
</dict> </dict>
</dict> </dict>
<key>date.second.ago.abbr</key> <key>date.second.ago.abbr</key>
@ -541,17 +565,17 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>zero</key> <key>zero</key>
<string>%lds ago</string> <string>مُنذُ لَحظة</string>
<key>one</key> <key>one</key>
<string>1s ago</string> <string>مُنذُ ثانية</string>
<key>two</key> <key>two</key>
<string>%lds ago</string> <string>مُنذُ ثانيتين</string>
<key>few</key> <key>few</key>
<string>%lds ago</string> <string>مُنذُ %ld ثوان</string>
<key>many</key> <key>many</key>
<string>%lds ago</string> <string>مُنذُ %ld ثانية</string>
<key>other</key> <key>other</key>
<string>%lds ago</string> <string>مُنذُ %ld ثانية</string>
</dict> </dict>
</dict> </dict>
</dict> </dict>

View File

@ -2,55 +2,55 @@
"common": { "common": {
"alerts": { "alerts": {
"common": { "common": {
"please_try_again": "الرجاء المحاولة مرة أخرى.", "please_try_again": "يُرجى المحاولة مرة أُخرى.",
"please_try_again_later": "الرجاء المحاولة مرة أخرى لاحقاً." "please_try_again_later": "يُرجى المحاولة مرة أُخرى لاحقاً."
}, },
"sign_up_failure": { "sign_up_failure": {
"title": "فشل التسجيل" "title": "إخفاق في التسجيل"
}, },
"server_error": { "server_error": {
"title": "خطأ في الخادم" "title": "خطأ في الخادم"
}, },
"vote_failure": { "vote_failure": {
"title": "فشل التصويت", "title": "إخفاق في التصويت",
"poll_ended": "The poll has ended" "poll_ended": "انتهى استطلاع الرأي"
}, },
"discard_post_content": { "discard_post_content": {
"title": "تجاهل المسودة", "title": "التخلص من المسودة",
"message": "Confirm to discard composed post content." "message": "أكِّد للتخلص مِن مُحتوى مَنشور مؤلَّف."
}, },
"publish_post_failure": { "publish_post_failure": {
"title": "أخفقت عملية النشر", "title": "إخفاق في عمليَّة النشر",
"message": "Failed to publish the post.\nPlease check your internet connection.", "message": "فَشَلَ نَشر المَنشور.\nيُرجى التحقق من اتصالك بالإنترنت.",
"attachments_message": { "attachments_message": {
"video_attach_with_photo": "Cannot attach a video to a post that already contains images.", "video_attach_with_photo": "لا يُمكن إرفاق مقطع مرئي إلى مَنشور يحتوي بالفعل على صُوَر.",
"more_than_one_video": "Cannot attach more than one video." "more_than_one_video": "لا يُمكِنُ إرفاق أكثر مِن مَقطع مرئي واحِد."
} }
}, },
"edit_profile_failure": { "edit_profile_failure": {
"title": "Edit Profile Error", "title": "خطأ في تَحرير الملف الشخصي",
"message": "Cannot edit profile. Please try again." "message": "لا يمكن تعديل الملف الشخصي. يُرجى المحاولة مرة أُخرى."
}, },
"sign_out": { "sign_out": {
"title": "تسجيل الخروج", "title": "تسجيل الخروج",
"message": "هل أنت متأكد من أنك تريد تسجيل الخروج؟", "message": "هل أنت متأكد من رغبتك في تسجيل الخروج؟",
"confirm": "تسجيل الخروج" "confirm": "تسجيل الخروج"
}, },
"block_domain": { "block_domain": {
"title": "Are you really, really sure you want to block the entire %s? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain and any of your followers from that domain will be removed.", "title": "هل أنتَ مُتأكِّدٌ حقًا مِن رغبتك في حظر %s بالكامل؟ في معظم الحالات، يكون مِنَ الكافي والمُفَضَّل استهداف عدد محدود للحظر أو الكتم. لن ترى محتوى من هذا النطاق وسوف يتم إزالة جميع متابعيك المتواجدين فيه.",
"block_entire_domain": "حظر النطاق" "block_entire_domain": "حظر النِطاق"
}, },
"save_photo_failure": { "save_photo_failure": {
"title": "فشل حفظ الصورة", "title": "إخفاق في حفظ الصورة",
"message": "Please enable the photo library access permission to save the photo." "message": "يُرجى إتاحة إذن الوصول إلى مكتبة الصور لحفظ الصورة."
}, },
"delete_post": { "delete_post": {
"title": "هل أنت متأكد من أنك تريد حذف هذا المنشور؟", "title": "هل أنت متأكد من رغبتك في حذف هذا المنشور؟",
"delete": "احذف" "delete": "احذف"
}, },
"clean_cache": { "clean_cache": {
"title": "تنظيف ذاكرة التخزين المؤقت", "title": "مَحو ذاكرة التخزين المؤقت",
"message": "تم تنظيف ذاكرة التخزين المؤقت %s بنجاح." "message": "تمَّ مَحو ذاكرة التخزين المؤقت %s بنجاح."
} }
}, },
"controls": { "controls": {
@ -61,30 +61,31 @@
"open": "افتح", "open": "افتح",
"add": "إضافة", "add": "إضافة",
"remove": "احذف", "remove": "احذف",
"edit": عديل", "edit": حرير",
"save": "حفظ", "save": "حفظ",
"ok": "حسنًا", "ok": "حسنًا",
"done": "تم", "done": "تمّ",
"confirm": "تأكيد", "confirm": "تأكيد",
"continue": "واصل", "continue": "واصل",
"compose": "تأليف",
"cancel": "إلغاء", "cancel": "إلغاء",
"discard": "تجاهل", "discard": "تجاهل",
"try_again": "حاول مرة أخرى", "try_again": "المُحاولة مرة أُخرى",
"take_photo": "التقط صورة", "take_photo": "التقاط صورة",
"save_photo": "حفظ الصورة", "save_photo": "حفظ الصورة",
"copy_photo": "نسخ الصورة", "copy_photo": "نسخ الصورة",
"sign_in": "لِج", "sign_in": "تسجيل الدخول",
"sign_up": "انشئ حسابًا", "sign_up": "إنشاء حِساب",
"see_more": "عرض المزيد", "see_more": "عرض المزيد",
"preview": عاينة", "preview": ُعاينة",
"share": "شارك", "share": "المُشارك",
"share_user": "شارك %s", "share_user": "مُشاركة %s",
"share_post": "شارك المنشور", "share_post": "مشارك المنشور",
"open_in_safari": "افتحه في سفاري", "open_in_safari": "الفتح في Safari",
"find_people": "ابحث عن أشخاص لمتابعتهم", "find_people": "ابحث عن أشخاص لمتابعتهم",
"manually_search": "البحث يدوياً بدلاً من ذلك", "manually_search": "البحث يدوياً بدلاً من ذلك",
"skip": "تخطي", "skip": "تخطي",
"reply": "رد", "reply": "الرَد",
"report_user": "ابلغ عن %s", "report_user": "ابلغ عن %s",
"block_domain": "حظر %s", "block_domain": "حظر %s",
"unblock_domain": "إلغاء حظر %s", "unblock_domain": "إلغاء حظر %s",
@ -100,7 +101,7 @@
"keyboard": { "keyboard": {
"common": { "common": {
"switch_to_tab": "التبديل إلى %s", "switch_to_tab": "التبديل إلى %s",
"compose_new_post": "إنشاء منشور جديد", "compose_new_post": "تأليف منشور جديد",
"show_favorites": "إظهار المفضلة", "show_favorites": "إظهار المفضلة",
"open_settings": "أفتح الإعدادات" "open_settings": "أفتح الإعدادات"
}, },
@ -111,9 +112,9 @@
"open_author_profile": "افتح الملف التعريفي للمؤلف", "open_author_profile": "افتح الملف التعريفي للمؤلف",
"open_reblogger_profile": "افتح الملف التعريفي لمشارِك المنشور", "open_reblogger_profile": "افتح الملف التعريفي لمشارِك المنشور",
"reply_status": "رد على المنشور", "reply_status": "رد على المنشور",
"toggle_reblog": "Toggle Reblog on Post", "toggle_reblog": "تبديل إعادة تدوين منشور",
"toggle_favorite": "Toggle Favorite on Post", "toggle_favorite": "تبديل المفضلة لِمنشور",
"toggle_content_warning": "Toggle Content Warning", "toggle_content_warning": "تبديل تحذير المُحتَوى",
"preview_image": "معاينة الصورة" "preview_image": "معاينة الصورة"
}, },
"segmented_control": { "segmented_control": {
@ -122,44 +123,44 @@
} }
}, },
"status": { "status": {
"user_reblogged": "%s reblogged", "user_reblogged": "أعادَ %s تدوينها",
"user_replied_to": "Replied to %s", "user_replied_to": "رد على %s",
"show_post": "Show Post", "show_post": "اظهر المنشور",
"show_user_profile": "Show user profile", "show_user_profile": "اظهر الملف التعريفي للمستخدم",
"content_warning": "Content Warning", "content_warning": "تحذير عن المحتوى",
"media_content_warning": "Tap anywhere to reveal", "media_content_warning": "انقر على أي مكان للكشف",
"poll": { "poll": {
"vote": "Vote", "vote": "صَوِّت",
"closed": "Closed" "closed": "انتهى"
}, },
"actions": { "actions": {
"reply": "Reply", "reply": "رد",
"reblog": "Reblog", "reblog": "إعادة النشر",
"unreblog": "Undo reblog", "unreblog": "تراجع عن إعادة النشر",
"favorite": "Favorite", "favorite": "إضافة إلى المفضلة",
"unfavorite": "Unfavorite", "unfavorite": "إزالة من المفضلة",
"menu": "Menu" "menu": "القائمة"
}, },
"tag": { "tag": {
"url": "URL", "url": "عنوان URL",
"mention": "Mention", "mention": "أشر إلى",
"link": "Link", "link": "الرابط",
"hashtag": "Hashtag", "hashtag": "الوسم",
"email": "البريد الإلكتروني", "email": "البريد الإلكتروني",
"emoji": "Emoji" "emoji": "إيموجي"
} }
}, },
"friendship": { "friendship": {
"follow": "Follow", "follow": "اتبع",
"following": "Following", "following": "مُتابَع",
"request": "Request", "request": "إرسال طَلَب",
"pending": "Pending", "pending": "قيد المُراجعة",
"block": "Block", "block": "حظر",
"block_user": "Block %s", "block_user": "حظر %s",
"block_domain": "Block %s", "block_domain": "حظر %s",
"unblock": "Unblock", "unblock": "إلغاء الحَظر",
"unblock_user": "Unblock %s", "unblock_user": "إلغاء حظر %s",
"blocked": "Blocked", "blocked": "محظور",
"mute": "أكتم", "mute": "أكتم",
"mute_user": "أكتم %s", "mute_user": "أكتم %s",
"unmute": "إلغاء الكتم", "unmute": "إلغاء الكتم",
@ -168,45 +169,45 @@
"edit_info": "تعديل المعلومات" "edit_info": "تعديل المعلومات"
}, },
"timeline": { "timeline": {
"filtered": "Filtered", "filtered": "مُصفَّى",
"timestamp": { "timestamp": {
"now": "الأن" "now": "الأن"
}, },
"loader": { "loader": {
"load_missing_posts": "Load missing posts", "load_missing_posts": "تحميل المنشورات المَفقودة",
"loading_missing_posts": "تحميل المزيد من المنشورات...", "loading_missing_posts": "تحميل المزيد من المنشورات...",
"show_more_replies": "إظهار المزيد من الردود" "show_more_replies": "إظهار المزيد من الردود"
}, },
"header": { "header": {
"no_status_found": "لا توجد هناك منشورات", "no_status_found": "لا توجد هناك منشورات",
"blocking_warning": "You cant view this user's profile\nuntil you unblock them.\nYour profile looks like this to them.", "blocking_warning": "لا يُمكنك الاطلاع على الملف الشخصي لهذا المُستخدِم\nحتَّى تَرفعَ الحَظر عنه.\nملفًّكَ الشخصي يَظهَرُ بِمثل هذِهِ الحالة بالنسبةِ لَهُ أيضًا.",
"user_blocking_warning": "You cant view %ss profile\nuntil you unblock them.\nYour profile looks like this to them.", "user_blocking_warning": "لا يُمكنك الاطلاع على ملف %s الشخصي\nحتَّى تَرفعَ الحَظر عنه.\nملفًّكَ الشخصي يَظهَرُ بِمثل هذِهِ الحالة بالنسبةِ لَهُ أيضًا.",
"blocked_warning": "You cant view this users profile\nuntil they unblock you.", "blocked_warning": "لا يُمكِنُكَ عَرض الملف الشخصي لهذا المُستخدِم\nحتَّى يَرفَعَ الحَظر عَنك.",
"user_blocked_warning": "You cant view %ss profile\nuntil they unblock you.", "user_blocked_warning": "لا يُمكِنُكَ عَرض ملف %s الشخصي\nحتَّى يَرفَعَ الحَظر عَنك.",
"suspended_warning": "This user has been suspended.", "suspended_warning": "تمَّ إيقاف هذا المُستخدِم.",
"user_suspended_warning": "%ss account has been suspended." "user_suspended_warning": "لقد أوقِفَ حِساب %s."
} }
} }
} }
}, },
"scene": { "scene": {
"welcome": { "welcome": {
"slogan": "Social networking\nback in your hands." "slogan": "شبكات التواصل الاجتماعي\nمرة أُخرى بين يديك."
}, },
"server_picker": { "server_picker": {
"title": "Pick a server,\nany server.", "title": "اِختر خادِم،\nأي خادِم.",
"button": { "button": {
"category": { "category": {
"all": "الكل", "all": "الكل",
"all_accessiblity_description": "الفئة: الكل", "all_accessiblity_description": "الفئة: الكل",
"academia": "academia", "academia": "أكاديمي",
"activism": "للنشطاء", "activism": "للنشطاء",
"food": "الطعام", "food": "الطعام",
"furry": "فروي", "furry": "فروي",
"games": "ألعاب", "games": "ألعاب",
"general": "عام", "general": "عام",
"journalism": "صحافة", "journalism": "صحافة",
"lgbt": "lgbt", "lgbt": "مجتمع الشواذ",
"regional": "اقليمي", "regional": "اقليمي",
"art": "فن", "art": "فن",
"music": "موسيقى", "music": "موسيقى",
@ -225,7 +226,7 @@
}, },
"empty_state": { "empty_state": {
"finding_servers": "البحث عن خوادم متوفرة...", "finding_servers": "البحث عن خوادم متوفرة...",
"bad_network": "Something went wrong while loading the data. Check your internet connection.", "bad_network": "حدث خطأٌ ما أثناء تحميل البيانات. تحقَّق من اتصالك بالإنترنت.",
"no_results": "لا توجد نتائج" "no_results": "لا توجد نتائج"
} }
}, },
@ -263,29 +264,29 @@
"reason": "السبب" "reason": "السبب"
}, },
"reason": { "reason": {
"blocked": "%s contains a disallowed email provider", "blocked": "يحتوي %s على موفِّر خدمة بريد إلكتروني غير مسموح به",
"unreachable": "%s does not seem to exist", "unreachable": "يبدوا أنَّ %s غير موجود",
"taken": "%s is already in use", "taken": "إنَّ %s مُستخدَمٌ بالفعل",
"reserved": "%s is a reserved keyword", "reserved": "إنَّ %s عبارة عن كلمة مفتاحيَّة محجوزة",
"accepted": "%s must be accepted", "accepted": "يجب أن يُقبل %s",
"blank": "%s is required", "blank": "%s مطلوب",
"invalid": "%s is invalid", "invalid": "%s غير صالح",
"too_long": "%s is too long", "too_long": "%s طويل جداً",
"too_short": "%s is too short", "too_short": "%s قصير جدا",
"inclusion": "%s is not a supported value" "inclusion": "إنَّ %s قيمة غير مدعومة"
}, },
"special": { "special": {
"username_invalid": "Username must only contain alphanumeric characters and underscores", "username_invalid": "يُمكِن أن يحتوي اسم المستخدم على أحرف أبجدية، أرقام وشرطات سفلية فقط",
"username_too_long": "Username is too long (cant be longer than 30 characters)", "username_too_long": "اسم المستخدم طويل جداً (يجب ألّا يكون أطول من 30 رمز)",
"email_invalid": "This is not a valid email address", "email_invalid": "هذا عنوان بريد إلكتروني غير صالح",
"password_too_short": "Password is too short (must be at least 8 characters)" "password_too_short": "كلمة المرور قصيرة جداً (يجب أن تكون 8 أحرف على الأقل)"
} }
} }
}, },
"server_rules": { "server_rules": {
"title": "Some ground rules.", "title": "بعض القواعد الأساسية.",
"subtitle": "These rules are set by the admins of %s.", "subtitle": "تم سنّ هذه القواعد من قبل مشرفي %s.",
"prompt": "By continuing, youre subject to the terms of service and privacy policy for %s.", "prompt": "إن اخترت المواصلة، فإنك تخضع لشروط الخدمة وسياسة الخصوصية لـ %s.",
"terms_of_service": "شروط الخدمة", "terms_of_service": "شروط الخدمة",
"privacy_policy": "سياسة الخصوصية", "privacy_policy": "سياسة الخصوصية",
"button": { "button": {
@ -294,35 +295,35 @@
}, },
"confirm_email": { "confirm_email": {
"title": "شيء واحد أخير.", "title": "شيء واحد أخير.",
"subtitle": "We just sent an email to %s,\ntap the link to confirm your account.", "subtitle": "لقد أرسلنا للتو رسالة بريد إلكتروني إلى %s،\nاضغط على الرابط لتأكيد حسابك.",
"button": { "button": {
"open_email_app": "Open Email App", "open_email_app": "افتح تطبيق البريد الإلكتروني",
"dont_receive_email": "I never got an email" "dont_receive_email": "لم أستلم أبدًا بريدا إلكترونيا"
}, },
"dont_receive_email": { "dont_receive_email": {
"title": "Check your email", "title": "تحقق من بريدك الإلكتروني",
"description": "Check if your email address is correct as well as your junk folder if you havent.", "description": "تحقق ممَّ إذا كان عنوان بريدك الإلكتروني صحيحًا وكذلك تأكد مِن مجلد البريد غير الهام إذا لم تكن قد فعلت ذلك.",
"resend_email": "Resend Email" "resend_email": "إعادة إرسال البريد الإلكتروني"
}, },
"open_email_app": { "open_email_app": {
"title": "Check your inbox.", "title": "تحقَّق من بريدك الوارِد.",
"description": "We just sent you an email. Check your junk folder if you havent.", "description": "لقد أرسلنا لك بريدًا إلكترونيًا للتو. تحقق من مجلد البريد غير الهام الخاص بك إذا لم تكن قد فعلت ذلك.",
"mail": "البريد", "mail": "البريد",
"open_email_client": "Open Email Client" "open_email_client": "فتح عميل البريد الإلكتروني"
} }
}, },
"home_timeline": { "home_timeline": {
"title": "الخيط الرئيسي", "title": "الخيط الرئيسي",
"navigation_bar_state": { "navigation_bar_state": {
"offline": "غير متصل", "offline": "غير متصل",
"new_posts": "See new posts", "new_posts": "إظهار منشورات جديدة",
"published": "Published!", "published": "تم نشره!",
"Publishing": "Publishing post..." "Publishing": "جارٍ نشر المشاركة…"
} }
}, },
"suggestion_account": { "suggestion_account": {
"title": "Find People to Follow", "title": "ابحث عن أشخاص لمتابعتهم",
"follow_explain": "When you follow someone, youll see their posts in your home feed." "follow_explain": "عِندَ مُتابَعَتِكَ لأحدِهِم، سَوف تَرى مَنشوراته في تغذيَتِكَ الرئيسة."
}, },
"compose": { "compose": {
"title": { "title": {
@ -334,54 +335,54 @@
"photo_library": "مكتبة الصور", "photo_library": "مكتبة الصور",
"browse": "تصفح" "browse": "تصفح"
}, },
"content_input_placeholder": "ما الذي يجول ببالك", "content_input_placeholder": "أخبِرنا بِما يَجُولُ فِي ذِهنَك",
"compose_action": "انشر", "compose_action": "انشر",
"replying_to_user": "رد على %s", "replying_to_user": "رد على %s",
"attachment": { "attachment": {
"photo": "صورة", "photo": "صورة",
"video": "فيديو", "video": "فيديو",
"attachment_broken": "This %s is broken and cant be\nuploaded to Mastodon.", "attachment_broken": "هذا ال%s مُعطَّل ويتعذَّر رفعه إلى ماستودون.",
"description_photo": "Describe the photo for the visually-impaired...", "description_photo": "صِف الصورة للمكفوفين...",
"description_video": "Describe the video for the visually-impaired..." "description_video": "صِف المقطع المرئي للمكفوفين..."
}, },
"poll": { "poll": {
"duration_time": "Duration: %s", "duration_time": "المدة: %s",
"thirty_minutes": "30 دقيقة", "thirty_minutes": "30 دقيقة",
"one_hour": "ساعة واحدة", "one_hour": "ساعة واحدة",
"six_hours": "6 ساعات", "six_hours": "6 ساعات",
"one_day": "يوم واحد", "one_day": "يوم واحد",
"three_days": "3 أيام", "three_days": "3 أيام",
"seven_days": "7 أيام", "seven_days": "7 أيام",
"option_number": "Option %ld" "option_number": "الخيار %ld"
}, },
"content_warning": { "content_warning": {
"placeholder": "Write an accurate warning here..." "placeholder": "اكتب تَحذيرًا دَقيقًا هُنا..."
}, },
"visibility": { "visibility": {
"public": "Public", "public": "للعامة",
"unlisted": "Unlisted", "unlisted": "غير مُدرَج",
"private": "Followers only", "private": "لمتابعيك فقط",
"direct": "Only people I mention" "direct": "ففط للأشخاص المشار إليهم"
}, },
"auto_complete": { "auto_complete": {
"space_to_add": "Space to add" "space_to_add": "انقر مساحة لإضافتِها"
}, },
"accessibility": { "accessibility": {
"append_attachment": "Add Attachment", "append_attachment": "إضافة مُرفَق",
"append_poll": "اضافة استطلاع رأي", "append_poll": "اضافة استطلاع رأي",
"remove_poll": "إزالة الاستطلاع", "remove_poll": "إزالة الاستطلاع",
"custom_emoji_picker": "منتقي مخصص للإيموجي", "custom_emoji_picker": "منتقي مخصص للإيموجي",
"enable_content_warning": "تنشيط تحذير المحتوى", "enable_content_warning": "تنشيط تحذير المحتوى",
"disable_content_warning": "تعطيل تحذير الحتوى", "disable_content_warning": "تعطيل تحذير الحتوى",
"post_visibility_menu": "Post Visibility Menu" "post_visibility_menu": "قائمة ظهور المنشور"
}, },
"keyboard": { "keyboard": {
"discard_post": "Discard Post", "discard_post": "تجاهُل المنشور",
"publish_post": "Publish Post", "publish_post": "نَشر المَنشُور",
"toggle_poll": "Toggle Poll", "toggle_poll": "تبديل الاستطلاع",
"toggle_content_warning": "Toggle Content Warning", "toggle_content_warning": "تبديل تحذير المُحتوى",
"append_attachment_entry": "Add Attachment - %s", "append_attachment_entry": "إضافة مُرفَق - %s",
"select_visibility_entry": "Select Visibility - %s" "select_visibility_entry": "اختر مدى الظهور - %s"
} }
}, },
"profile": { "profile": {
@ -393,7 +394,7 @@
"fields": { "fields": {
"add_row": "إضافة صف", "add_row": "إضافة صف",
"placeholder": { "placeholder": {
"label": "Label", "label": "التسمية",
"content": "المحتوى" "content": "المحتوى"
} }
}, },
@ -405,14 +406,20 @@
"relationship_action_alert": { "relationship_action_alert": {
"confirm_unmute_user": { "confirm_unmute_user": {
"title": "إلغاء كتم الحساب", "title": "إلغاء كتم الحساب",
"message": "Confirm to unmute %s" "message": "أكِّد لرفع كتمْ %s"
}, },
"confirm_unblock_usre": { "confirm_unblock_usre": {
"title": "إلغاء حظر الحساب", "title": "إلغاء حظر الحساب",
"message": "Confirm to unblock %s" "message": "أكِّد لرفع حظر %s"
} }
} }
}, },
"follower": {
"footer": "لا يُمكِن عَرض المُتابِعين مِنَ الخوادم الأُخرى."
},
"following": {
"footer": "لا يُمكِن عَرض المُتابَعات مِنَ الخوادم الأُخرى."
},
"search": { "search": {
"title": "بحث", "title": "بحث",
"search_bar": { "search_bar": {
@ -423,12 +430,12 @@
"button_text": "طالع الكل", "button_text": "طالع الكل",
"hash_tag": { "hash_tag": {
"title": "ذات شعبية على ماستدون", "title": "ذات شعبية على ماستدون",
"description": "Hashtags that are getting quite a bit of attention", "description": "الوسوم التي تحظى بقدر كبير من الاهتمام",
"people_talking": "%s people are talking" "people_talking": "%s أشخاص يتحدَّثوا"
}, },
"accounts": { "accounts": {
"title": "Accounts you might like", "title": "حسابات قد تعجبك",
"description": "You may like to follow these accounts", "description": "قد ترغب في متابعة هذه الحسابات",
"follow": "تابع" "follow": "تابع"
} }
}, },
@ -440,34 +447,34 @@
"posts": "المنشورات" "posts": "المنشورات"
}, },
"empty_state": { "empty_state": {
"no_results": "No results" "no_results": "ليس هناك أية نتيجة"
}, },
"recent_search": "Recent searches", "recent_search": "عمليات البحث الأخيرة",
"clear": "Clear" "clear": "مَحو"
} }
}, },
"favorite": { "favorite": {
"title": "Your Favorites" "title": "مفضلتك"
}, },
"notification": { "notification": {
"title": { "title": {
"Everything": "Everything", "Everything": "الكل",
"Mentions": "Mentions" "Mentions": "الإشارات"
}, },
"user_followed_you": "%s followed you", "user_followed_you": "يتابعك %s",
"user_favorited your post": "%s favorited your post", "user_favorited your post": "أضاف %s منشورك إلى مفضلته",
"user_reblogged_your_post": "%s reblogged your post", "user_reblogged_your_post": "أعاد %s تدوين مشاركتك",
"user_mentioned_you": "%s mentioned you", "user_mentioned_you": "أشار إليك %s",
"user_requested_to_follow_you": "%s requested to follow you", "user_requested_to_follow_you": "طلب %s متابعتك",
"user_your_poll_has_ended": "%s Your poll has ended", "user_your_poll_has_ended": "%s اِنتهى استطلاعُكَ للرأي",
"keyobard": { "keyobard": {
"show_everything": "Show Everything", "show_everything": "إظهار كل شيء",
"show_mentions": "Show Mentions" "show_mentions": "إظهار الإشارات"
} }
}, },
"thread": { "thread": {
"back_title": "Post", "back_title": "منشور",
"title": "Post from %s" "title": "مَنشور مِن %s"
}, },
"settings": { "settings": {
"title": "الإعدادات", "title": "الإعدادات",
@ -475,44 +482,44 @@
"appearance": { "appearance": {
"title": "المظهر", "title": "المظهر",
"automatic": "تلقائي", "automatic": "تلقائي",
"light": "Always Light", "light": "مضيءٌ دائمًا",
"dark": "Always Dark" "dark": "مظلمٌ دائِمًا"
}, },
"notifications": { "notifications": {
"title": "الإشعارات", "title": "الإشعارات",
"favorites": "Favorites my post", "favorites": "الإعجاب بِمنشوراتي",
"follows": "Follows me", "follows": "يتابعني",
"boosts": "Reblogs my post", "boosts": "إعادة تدوين منشوراتي",
"mentions": "Mentions me", "mentions": "الإشارة لي",
"trigger": { "trigger": {
"anyone": "anyone", "anyone": "أي شخص",
"follower": "a follower", "follower": "مشترِك",
"follow": "anyone I follow", "follow": "أي شخص أُتابِعُه",
"noone": "no one", "noone": "لا أحد",
"title": "Notify me when" "title": "إشعاري عِندَ"
} }
}, },
"preference": { "preference": {
"title": "التفضيلات", "title": "التفضيلات",
"true_black_dark_mode": "True black dark mode", "true_black_dark_mode": "النمط الأسود الداكِن الحقيقي",
"disable_avatar_animation": "Disable animated avatars", "disable_avatar_animation": "تعطيل الصور الرمزية المتحرِّكة",
"disable_emoji_animation": "Disable animated emojis", "disable_emoji_animation": "تعطيل الرموز التعبيرية المتحرِّكَة",
"using_default_browser": "Use default browser to open links" "using_default_browser": "اِستخدام المتصفح الافتراضي لفتح الروابط"
}, },
"boring_zone": { "boring_zone": {
"title": "The Boring Zone", "title": "المنطقة المملة",
"account_settings": "إعدادات الحساب", "account_settings": "إعدادات الحساب",
"terms": "شروط الخدمة", "terms": "شروط الخدمة",
"privacy": "سياسة الخصوصية" "privacy": "سياسة الخصوصية"
}, },
"spicy_zone": { "spicy_zone": {
"title": "The Spicy Zone", "title": "المنطقة الحارة",
"clear": "Clear Media Cache", "clear": "مسح ذاكرة التخزين المؤقت للوسائط",
"signout": "تسجيل الخروج" "signout": "تسجيل الخروج"
} }
}, },
"footer": { "footer": {
"mastodon_description": "ماستدون برنامج مفتوح المصدر. يمكنك المساهمة، أو الإبلاغ عن تقارير الأخطاء، على غيت هب %s (%s)" "mastodon_description": "ماستدون برنامج مفتوح المصدر. يمكنك المساهمة، أو الإبلاغ عن تقارير الأخطاء على GitHub في %s (%s)"
}, },
"keyboard": { "keyboard": {
"close_settings_window": "إغلاق نافذة الإعدادات" "close_settings_window": "إغلاق نافذة الإعدادات"
@ -522,18 +529,28 @@
"title": "ابلغ عن %s", "title": "ابلغ عن %s",
"step1": "الخطوة 1 من 2", "step1": "الخطوة 1 من 2",
"step2": "الخطوة 2 من 2", "step2": "الخطوة 2 من 2",
"content1": "Are there any other posts youd like to add to the report?", "content1": "هل ترغب في إضافة أي مشاركات أُخرى إلى الشكوى؟",
"content2": "Is there anything the moderators should know about this report?", "content2": "هل هناك أي شيء يجب أن يعرفه المُراقبين حول هذه الشكوى؟",
"send": "Send Report", "send": "إرسال الشكوى",
"skip_to_send": "Send without comment", "skip_to_send": "إرسال بدون تعليق",
"text_placeholder": "Type or paste additional comments" "text_placeholder": "اكتب أو الصق تعليقات إضافيَّة"
}, },
"preview": { "preview": {
"keyboard": { "keyboard": {
"close_preview": "إغلاق المعاينة", "close_preview": "إغلاق المُعايَنَة",
"show_next": "إظهار التالي", "show_next": "إظهار التالي",
"show_previous": "إظهار السابق" "show_previous": "إظهار السابق"
} }
},
"account_list": {
"tab_bar_hint": "المِلف المُحدَّد حاليًا: %s. انقر نقرًا مزدوجًا ثم اضغط مع الاستمرار لإظهار مُبدِّل الحِساب",
"dismiss_account_switcher": "تجاهُل مبدِّل الحساب",
"add_account": "إضافة حساب"
},
"wizard": {
"new_in_mastodon": "جديد في ماستودون",
"multiple_account_switch_intro_description": "بدِّل بين حسابات متعددة عبر الاستمرار بالضغط على زر الملف الشخصي.",
"accessibility_hint": "انقر نقرًا مزدوجًا لتجاهل النافذة المنبثقة"
} }
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"NSCameraUsageDescription": "Used to take photo for post status", "NSCameraUsageDescription": "يُستخدم لالتقاط الصورة عِندَ نشر الحالات",
"NSPhotoLibraryAddUsageDescription": "Used to save photo into the Photo Library", "NSPhotoLibraryAddUsageDescription": "يُستخدم لحِفظ الصورة في مكتبة الصور",
"NewPostShortcutItemTitle": "New Post", "NewPostShortcutItemTitle": "منشور جديد",
"SearchShortcutItemTitle": "البحث" "SearchShortcutItemTitle": "البحث"
} }

View File

@ -2,10 +2,26 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>a11y.plural.count.unread.notification</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@notification_count_unread_notification@</string>
<key>notification_count_unread_notification</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 notificació per llegir</string>
<key>other</key>
<string>%ld notificacions per llegir</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_exceeds</key> <key>a11y.plural.count.input_limit_exceeds</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>
<string>El límit dentrada supera a %#@character_count@</string> <string>El límit de la entrada supera a %#@character_count@</string>
<key>character_count</key> <key>character_count</key>
<dict> <dict>
<key>NSStringFormatSpecTypeKey</key> <key>NSStringFormatSpecTypeKey</key>
@ -21,7 +37,7 @@
<key>a11y.plural.count.input_limit_remains</key> <key>a11y.plural.count.input_limit_remains</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>
<string>El límit dentrada continua sent %#@character_count@</string> <string>El límit de la entrada continua sent %#@character_count@</string>
<key>character_count</key> <key>character_count</key>
<dict> <dict>
<key>NSStringFormatSpecTypeKey</key> <key>NSStringFormatSpecTypeKey</key>
@ -95,7 +111,7 @@
<key>one</key> <key>one</key>
<string>1 impuls</string> <string>1 impuls</string>
<key>other</key> <key>other</key>
<string>%ld impuls</string> <string>%ld impulsos</string>
</dict> </dict>
</dict> </dict>
<key>plural.count.vote</key> <key>plural.count.vote</key>
@ -285,9 +301,9 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>one</key> <key>one</key>
<string>fa 1a</string> <string>fa 1 any</string>
<key>other</key> <key>other</key>
<string>fa %ldy anys</string> <string>fa %ld anys</string>
</dict> </dict>
</dict> </dict>
<key>date.month.ago.abbr</key> <key>date.month.ago.abbr</key>
@ -301,9 +317,9 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>one</key> <key>one</key>
<string>fa 1M</string> <string>fa 1 mes</string>
<key>other</key> <key>other</key>
<string>fa %ldM mesos</string> <string>fa %ld mesos</string>
</dict> </dict>
</dict> </dict>
<key>date.day.ago.abbr</key> <key>date.day.ago.abbr</key>
@ -317,9 +333,9 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>one</key> <key>one</key>
<string>fa 1d</string> <string>fa 1 día</string>
<key>other</key> <key>other</key>
<string>fa %ldd dies</string> <string>fa %ld dies</string>
</dict> </dict>
</dict> </dict>
<key>date.hour.ago.abbr</key> <key>date.hour.ago.abbr</key>
@ -335,7 +351,7 @@
<key>one</key> <key>one</key>
<string>fa 1h</string> <string>fa 1h</string>
<key>other</key> <key>other</key>
<string>fa %ldh hores</string> <string>fa %ld hores</string>
</dict> </dict>
</dict> </dict>
<key>date.minute.ago.abbr</key> <key>date.minute.ago.abbr</key>
@ -349,9 +365,9 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>one</key> <key>one</key>
<string>fa 1m</string> <string>fa 1 minut</string>
<key>other</key> <key>other</key>
<string>fa %ldm minuts</string> <string>fa %ld minuts</string>
</dict> </dict>
</dict> </dict>
<key>date.second.ago.abbr</key> <key>date.second.ago.abbr</key>
@ -365,9 +381,9 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>one</key> <key>one</key>
<string>fa 1s</string> <string>fa 1 segon</string>
<key>other</key> <key>other</key>
<string>fa %lds seg</string> <string>fa %ld segons</string>
</dict> </dict>
</dict> </dict>
</dict> </dict>

View File

@ -67,6 +67,7 @@
"done": "Fet", "done": "Fet",
"confirm": "Confirma", "confirm": "Confirma",
"continue": "Continua", "continue": "Continua",
"compose": "Composa",
"cancel": "Cancel·la", "cancel": "Cancel·la",
"discard": "Descarta", "discard": "Descarta",
"try_again": "Torna a provar", "try_again": "Torna a provar",
@ -413,6 +414,12 @@
} }
} }
}, },
"follower": {
"footer": "Els seguidors d'altres servidors no son mostrats."
},
"following": {
"footer": "Els seguits d'altres servidors no son mostrats."
},
"search": { "search": {
"title": "Cerca", "title": "Cerca",
"search_bar": { "search_bar": {
@ -534,6 +541,16 @@
"show_next": "Mostrar Següent", "show_next": "Mostrar Següent",
"show_previous": "Mostrar Anterior" "show_previous": "Mostrar Anterior"
} }
},
"account_list": {
"tab_bar_hint": "Perfil actual seleccionat: %s. Toca dues vegades i manté el dit per a mostrar el commutador de comptes",
"dismiss_account_switcher": "Descartar el commutador de comptes",
"add_account": "Afegir compte"
},
"wizard": {
"new_in_mastodon": "Nou a Mastodon",
"multiple_account_switch_intro_description": "Commuta entre diversos comptes mantenint premut el botó del perfil.",
"accessibility_hint": "Toca dues vegades per descartar l'assistent"
} }
} }
} }

View File

@ -2,6 +2,30 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>a11y.plural.count.unread.notification</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@notification_count_unread_notification@</string>
<key>notification_count_unread_notification</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>zero</key>
<string>%ld unread notification</string>
<key>one</key>
<string>1 unread notification</string>
<key>two</key>
<string>%ld unread notification</string>
<key>few</key>
<string>%ld unread notification</string>
<key>many</key>
<string>%ld unread notification</string>
<key>other</key>
<string>%ld unread notification</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_exceeds</key> <key>a11y.plural.count.input_limit_exceeds</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>

View File

@ -67,6 +67,7 @@
"done": "Done", "done": "Done",
"confirm": "Confirm", "confirm": "Confirm",
"continue": "Continue", "continue": "Continue",
"compose": "Compose",
"cancel": "Cancel", "cancel": "Cancel",
"discard": "Discard", "discard": "Discard",
"try_again": "Try Again", "try_again": "Try Again",
@ -413,6 +414,12 @@
} }
} }
}, },
"follower": {
"footer": "Followers from other servers are not displayed."
},
"following": {
"footer": "Follows from other servers are not displayed."
},
"search": { "search": {
"title": "Search", "title": "Search",
"search_bar": { "search_bar": {
@ -534,6 +541,16 @@
"show_next": "Show Next", "show_next": "Show Next",
"show_previous": "Show Previous" "show_previous": "Show Previous"
} }
},
"account_list": {
"tab_bar_hint": "Current selected profile: %s. Double tap then hold to show account switcher",
"dismiss_account_switcher": "Dismiss Account Switcher",
"add_account": "Add Account"
},
"wizard": {
"new_in_mastodon": "New in Mastodon",
"multiple_account_switch_intro_description": "Switch between multiple accounts by holding the profile button.",
"accessibility_hint": "Double tap to dismiss this wizard"
} }
} }
} }

View File

@ -2,6 +2,22 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>a11y.plural.count.unread.notification</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@notification_count_unread_notification@</string>
<key>notification_count_unread_notification</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 unread notification</string>
<key>other</key>
<string>%ld unread notification</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_exceeds</key> <key>a11y.plural.count.input_limit_exceeds</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>

View File

@ -67,6 +67,7 @@
"done": "Done", "done": "Done",
"confirm": "Confirm", "confirm": "Confirm",
"continue": "Continue", "continue": "Continue",
"compose": "Compose",
"cancel": "Cancel", "cancel": "Cancel",
"discard": "Discard", "discard": "Discard",
"try_again": "Try Again", "try_again": "Try Again",
@ -413,6 +414,12 @@
} }
} }
}, },
"follower": {
"footer": "Followers from other servers are not displayed."
},
"following": {
"footer": "Follows from other servers are not displayed."
},
"search": { "search": {
"title": "Search", "title": "Search",
"search_bar": { "search_bar": {
@ -534,6 +541,16 @@
"show_next": "Show Next", "show_next": "Show Next",
"show_previous": "Show Previous" "show_previous": "Show Previous"
} }
},
"account_list": {
"tab_bar_hint": "Current selected profile: %s. Double tap then hold to show account switcher",
"dismiss_account_switcher": "Dismiss Account Switcher",
"add_account": "Add Account"
},
"wizard": {
"new_in_mastodon": "New in Mastodon",
"multiple_account_switch_intro_description": "Switch between multiple accounts by holding the profile button.",
"accessibility_hint": "Double tap to dismiss this wizard"
} }
} }
} }

View File

@ -2,6 +2,22 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>a11y.plural.count.unread.notification</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@notification_count_unread_notification@</string>
<key>notification_count_unread_notification</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 ungelesene Benachrichtigung</string>
<key>other</key>
<string>%ld ungelesene Benachrichtigungen</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_exceeds</key> <key>a11y.plural.count.input_limit_exceeds</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>

View File

@ -67,6 +67,7 @@
"done": "Fertig", "done": "Fertig",
"confirm": "Bestätigen", "confirm": "Bestätigen",
"continue": "Fortfahren", "continue": "Fortfahren",
"compose": "Compose",
"cancel": "Abbrechen", "cancel": "Abbrechen",
"discard": "Verwerfen", "discard": "Verwerfen",
"try_again": "Nochmals versuchen", "try_again": "Nochmals versuchen",
@ -413,6 +414,12 @@
} }
} }
}, },
"follower": {
"footer": "Followers from other servers are not displayed."
},
"following": {
"footer": "Follows from other servers are not displayed."
},
"search": { "search": {
"title": "Suche", "title": "Suche",
"search_bar": { "search_bar": {
@ -534,6 +541,16 @@
"show_next": "Nächstes anzeigen", "show_next": "Nächstes anzeigen",
"show_previous": "Vorheriges anzeigen" "show_previous": "Vorheriges anzeigen"
} }
},
"account_list": {
"tab_bar_hint": "Aktuell ausgewähltes Profil: %s. Doppeltippen dann gedrückt halten, um den Kontoschalter anzuzeigen",
"dismiss_account_switcher": "Dismiss Account Switcher",
"add_account": "Konto hinzufügen"
},
"wizard": {
"new_in_mastodon": "Neu in Mastodon",
"multiple_account_switch_intro_description": "Wechsel zwischen mehreren Konten durch drücken der Profil-Schaltfläche.",
"accessibility_hint": "Doppeltippen, um diesen Assistenten zu schließen"
} }
} }
} }

View File

@ -2,6 +2,22 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>a11y.plural.count.unread.notification</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@notification_count_unread_notification@</string>
<key>notification_count_unread_notification</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 unread notification</string>
<key>other</key>
<string>%ld unread notification</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_exceeds</key> <key>a11y.plural.count.input_limit_exceeds</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>

View File

@ -67,6 +67,7 @@
"done": "Done", "done": "Done",
"confirm": "Confirm", "confirm": "Confirm",
"continue": "Continue", "continue": "Continue",
"compose": "Compose",
"cancel": "Cancel", "cancel": "Cancel",
"discard": "Discard", "discard": "Discard",
"try_again": "Try Again", "try_again": "Try Again",
@ -413,6 +414,12 @@
} }
} }
}, },
"follower": {
"footer": "Followers from other servers are not displayed."
},
"following": {
"footer": "Follows from other servers are not displayed."
},
"search": { "search": {
"title": "Search", "title": "Search",
"search_bar": { "search_bar": {
@ -534,6 +541,16 @@
"show_next": "Show Next", "show_next": "Show Next",
"show_previous": "Show Previous" "show_previous": "Show Previous"
} }
},
"account_list": {
"tab_bar_hint": "Current selected profile: %s. Double tap then hold to show account switcher",
"dismiss_account_switcher": "Dismiss Account Switcher",
"add_account": "Add Account"
},
"wizard": {
"new_in_mastodon": "New in Mastodon",
"multiple_account_switch_intro_description": "Switch between multiple accounts by holding the profile button.",
"accessibility_hint": "Double tap to dismiss this wizard"
} }
} }
} }

View File

@ -2,6 +2,22 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>a11y.plural.count.unread.notification</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@notification_count_unread_notification@</string>
<key>notification_count_unread_notification</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 notificación sin leer</string>
<key>other</key>
<string>%ld notificaciones sin leer</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_exceeds</key> <key>a11y.plural.count.input_limit_exceeds</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>

View File

@ -67,6 +67,7 @@
"done": "Listo", "done": "Listo",
"confirm": "Confirmar", "confirm": "Confirmar",
"continue": "Continuar", "continue": "Continuar",
"compose": "Redactar",
"cancel": "Cancelar", "cancel": "Cancelar",
"discard": "Descartar", "discard": "Descartar",
"try_again": "Intentá de nuevo", "try_again": "Intentá de nuevo",
@ -413,6 +414,12 @@
} }
} }
}, },
"follower": {
"footer": "No se muestran los seguidores de otros servidores."
},
"following": {
"footer": "No se muestran las cuentas de otros servidores que seguís."
},
"search": { "search": {
"title": "Buscar", "title": "Buscar",
"search_bar": { "search_bar": {
@ -534,6 +541,16 @@
"show_next": "Mostrar siguiente", "show_next": "Mostrar siguiente",
"show_previous": "Mostrar anterior" "show_previous": "Mostrar anterior"
} }
},
"account_list": {
"tab_bar_hint": "Perfil seleccionado actualmente: %s. Tocá dos veces y mantenelo presionado para cambiar de cuenta",
"dismiss_account_switcher": "Descartar cambio de cuenta",
"add_account": "Agregar cuenta"
},
"wizard": {
"new_in_mastodon": "Novedad en Mastodon",
"multiple_account_switch_intro_description": "Cambiá entre varias cuentas manteniendo presionado el botón del perfil.",
"accessibility_hint": "Tocá dos veces para descartar este asistente"
} }
} }
} }

View File

@ -2,6 +2,22 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>a11y.plural.count.unread.notification</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@notification_count_unread_notification@</string>
<key>notification_count_unread_notification</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 unread notification</string>
<key>other</key>
<string>%ld unread notification</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_exceeds</key> <key>a11y.plural.count.input_limit_exceeds</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>

View File

@ -67,6 +67,7 @@
"done": "Hecho", "done": "Hecho",
"confirm": "Confirmar", "confirm": "Confirmar",
"continue": "Continuar", "continue": "Continuar",
"compose": "Redactar",
"cancel": "Cancelar", "cancel": "Cancelar",
"discard": "Descartar", "discard": "Descartar",
"try_again": "Inténtalo de nuevo", "try_again": "Inténtalo de nuevo",
@ -413,6 +414,12 @@
} }
} }
}, },
"follower": {
"footer": "No se muestran los seguidores de otros servidores."
},
"following": {
"footer": "No se muestran los seguidos de otros servidores."
},
"search": { "search": {
"title": "Buscar", "title": "Buscar",
"search_bar": { "search_bar": {
@ -534,6 +541,16 @@
"show_next": "Mostrar Siguiente", "show_next": "Mostrar Siguiente",
"show_previous": "Mostrar Anterior" "show_previous": "Mostrar Anterior"
} }
},
"account_list": {
"tab_bar_hint": "Current selected profile: %s. Double tap then hold to show account switcher",
"dismiss_account_switcher": "Dismiss Account Switcher",
"add_account": "Add Account"
},
"wizard": {
"new_in_mastodon": "New in Mastodon",
"multiple_account_switch_intro_description": "Switch between multiple accounts by holding the profile button.",
"accessibility_hint": "Double tap to dismiss this wizard"
} }
} }
} }

View File

@ -2,10 +2,26 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>a11y.plural.count.unread.notification</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@notification_count_unread_notification@</string>
<key>notification_count_unread_notification</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 notification non lue</string>
<key>other</key>
<string>%ld notifications non lues</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_exceeds</key> <key>a11y.plural.count.input_limit_exceeds</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>
<string>Input limit exceeds %#@character_count@</string> <string>La limite dentrée dépasse %#@character_count@</string>
<key>character_count</key> <key>character_count</key>
<dict> <dict>
<key>NSStringFormatSpecTypeKey</key> <key>NSStringFormatSpecTypeKey</key>
@ -13,9 +29,9 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>one</key> <key>one</key>
<string>1 character</string> <string>1 caractère</string>
<key>other</key> <key>other</key>
<string>%ld characters</string> <string>%ld caractères</string>
</dict> </dict>
</dict> </dict>
<key>a11y.plural.count.input_limit_remains</key> <key>a11y.plural.count.input_limit_remains</key>
@ -29,9 +45,9 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>one</key> <key>one</key>
<string>1 character</string> <string>1 caractère</string>
<key>other</key> <key>other</key>
<string>%ld characters</string> <string>%ld caractères</string>
</dict> </dict>
</dict> </dict>
<key>plural.count.metric_formatted.post</key> <key>plural.count.metric_formatted.post</key>
@ -61,9 +77,9 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>one</key> <key>one</key>
<string>1 post</string> <string>1 publication</string>
<key>other</key> <key>other</key>
<string>%ld posts</string> <string>%ld publications</string>
</dict> </dict>
</dict> </dict>
<key>plural.count.favorite</key> <key>plural.count.favorite</key>
@ -157,9 +173,9 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>one</key> <key>one</key>
<string>1 following</string> <string>1 abonnement</string>
<key>other</key> <key>other</key>
<string>%ld following</string> <string>%ld abonnements</string>
</dict> </dict>
</dict> </dict>
<key>plural.count.follower</key> <key>plural.count.follower</key>
@ -173,9 +189,9 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>one</key> <key>one</key>
<string>1 follower</string> <string>1 abonné·e</string>
<key>other</key> <key>other</key>
<string>%ld followers</string> <string>%ld abonné·e·s</string>
</dict> </dict>
</dict> </dict>
<key>date.year.left</key> <key>date.year.left</key>
@ -189,9 +205,9 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>one</key> <key>one</key>
<string>1 year left</string> <string>Il reste 1 an</string>
<key>other</key> <key>other</key>
<string>%ld years left</string> <string>%ld ans restants</string>
</dict> </dict>
</dict> </dict>
<key>date.month.left</key> <key>date.month.left</key>
@ -205,9 +221,9 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>one</key> <key>one</key>
<string>1 months left</string> <string>1 mois restant</string>
<key>other</key> <key>other</key>
<string>%ld months left</string> <string>%ld mois restants</string>
</dict> </dict>
</dict> </dict>
<key>date.day.left</key> <key>date.day.left</key>
@ -221,9 +237,9 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>one</key> <key>one</key>
<string>1 day left</string> <string>Il reste 1 jour</string>
<key>other</key> <key>other</key>
<string>%ld days left</string> <string>il reste %ld jours</string>
</dict> </dict>
</dict> </dict>
<key>date.hour.left</key> <key>date.hour.left</key>
@ -237,9 +253,9 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>one</key> <key>one</key>
<string>1 hour left</string> <string>1 heure restante</string>
<key>other</key> <key>other</key>
<string>%ld hours left</string> <string>%ld heures restantes</string>
</dict> </dict>
</dict> </dict>
<key>date.minute.left</key> <key>date.minute.left</key>
@ -253,9 +269,9 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>one</key> <key>one</key>
<string>1 minute left</string> <string>1 minute restante</string>
<key>other</key> <key>other</key>
<string>%ld minutes left</string> <string>%ld minutes restantes</string>
</dict> </dict>
</dict> </dict>
<key>date.second.left</key> <key>date.second.left</key>
@ -269,9 +285,9 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>one</key> <key>one</key>
<string>1 second left</string> <string>Il reste 1 seconde</string>
<key>other</key> <key>other</key>
<string>%ld seconds left</string> <string>%ld secondes restantes</string>
</dict> </dict>
</dict> </dict>
<key>date.year.ago.abbr</key> <key>date.year.ago.abbr</key>
@ -285,9 +301,9 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>one</key> <key>one</key>
<string>1y ago</string> <string>il y a 1 année</string>
<key>other</key> <key>other</key>
<string>%ldy ago</string> <string>il y a %ld ans</string>
</dict> </dict>
</dict> </dict>
<key>date.month.ago.abbr</key> <key>date.month.ago.abbr</key>
@ -301,9 +317,9 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>one</key> <key>one</key>
<string>1M ago</string> <string>il y a 1 mois</string>
<key>other</key> <key>other</key>
<string>%ldM ago</string> <string>il y a %ld mois</string>
</dict> </dict>
</dict> </dict>
<key>date.day.ago.abbr</key> <key>date.day.ago.abbr</key>
@ -317,9 +333,9 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>one</key> <key>one</key>
<string>1d ago</string> <string>il y a 1j</string>
<key>other</key> <key>other</key>
<string>%ldd ago</string> <string>il y a %ldj</string>
</dict> </dict>
</dict> </dict>
<key>date.hour.ago.abbr</key> <key>date.hour.ago.abbr</key>
@ -333,9 +349,9 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>one</key> <key>one</key>
<string>1h ago</string> <string>il y a 1h</string>
<key>other</key> <key>other</key>
<string>%ldh ago</string> <string>il y a %ldh</string>
</dict> </dict>
</dict> </dict>
<key>date.minute.ago.abbr</key> <key>date.minute.ago.abbr</key>
@ -349,9 +365,9 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>one</key> <key>one</key>
<string>1m ago</string> <string>Il y a 1 m</string>
<key>other</key> <key>other</key>
<string>%ldm ago</string> <string>il y a %ld m</string>
</dict> </dict>
</dict> </dict>
<key>date.second.ago.abbr</key> <key>date.second.ago.abbr</key>
@ -365,9 +381,9 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>one</key> <key>one</key>
<string>1s ago</string> <string>Il y a 1 s</string>
<key>other</key> <key>other</key>
<string>%lds ago</string> <string>il y a %ld s</string>
</dict> </dict>
</dict> </dict>
</dict> </dict>

View File

@ -67,6 +67,7 @@
"done": "Terminé", "done": "Terminé",
"confirm": "Confirmer", "confirm": "Confirmer",
"continue": "Continuer", "continue": "Continuer",
"compose": "Compose",
"cancel": "Annuler", "cancel": "Annuler",
"discard": "Abandonner", "discard": "Abandonner",
"try_again": "Réessayer", "try_again": "Réessayer",
@ -105,10 +106,10 @@
"open_settings": "Ouvrir les paramètres" "open_settings": "Ouvrir les paramètres"
}, },
"timeline": { "timeline": {
"previous_status": "Article précédent", "previous_status": "Publication précédente",
"next_status": "Article suivant", "next_status": "Publication suivante",
"open_status": "Ouvrir la publication", "open_status": "Ouvrir la publication",
"open_author_profile": "Ouvrir le profil de l'auteur", "open_author_profile": "Ouvrir le profil de lauteur·rice",
"open_reblogger_profile": "Ouvrir le profil du rebloggeur", "open_reblogger_profile": "Ouvrir le profil du rebloggeur",
"reply_status": "Répondre à la publication", "reply_status": "Répondre à la publication",
"toggle_reblog": "Basculer le reblogue lors de la publication", "toggle_reblog": "Basculer le reblogue lors de la publication",
@ -122,10 +123,10 @@
} }
}, },
"status": { "status": {
"user_reblogged": "%s à reblogué", "user_reblogged": "%s a reblogué",
"user_replied_to": "À répondu à %s", "user_replied_to": "À répondu à %s",
"show_post": "Montrer la publication", "show_post": "Montrer la publication",
"show_user_profile": "Montrer le profil de lutilisateur", "show_user_profile": "Montrer le profil de lutilisateur·rice",
"content_warning": "Avertissement de contenu", "content_warning": "Avertissement de contenu",
"media_content_warning": "Tapotez nimporte où pour révéler la publication", "media_content_warning": "Tapotez nimporte où pour révéler la publication",
"poll": { "poll": {
@ -180,9 +181,9 @@
"header": { "header": {
"no_status_found": "Aucune publication trouvée", "no_status_found": "Aucune publication trouvée",
"blocking_warning": "Vous ne pouvez pas voir le profil de cet utilisateur\n tant que vous ne lavez pas débloqué\nVotre profil ressemble à ça pour lui.", "blocking_warning": "Vous ne pouvez pas voir le profil de cet utilisateur\n tant que vous ne lavez pas débloqué\nVotre profil ressemble à ça pour lui.",
"user_blocking_warning": "Vous ne pouvez pas voir le profil de %s tant que vous ne lavez pas débloqué\nVotre profil ressemble à ça pour lui.", "user_blocking_warning": "Vous ne pouvez pas voir le profil de %s\ntant que vous ne lavez pas débloqué\nVotre profil ressemble à ça pour lui.",
"blocked_warning": "Vous ne pouvez pas voir le profil de cet utilisateur\n tant qu'il ne vous aura pas débloqué.", "blocked_warning": "Vous ne pouvez pas voir le profil de cet utilisateur\n tant qu'il ne vous aura pas débloqué.",
"user_blocked_warning": "Vous ne pouvez pas voir le profil de %s\n tant qu'il ne vous aura pas débloqué.", "user_blocked_warning": "Vous ne pouvez pas voir le profil de %s\ntant quil ne vous aura pas débloqué.",
"suspended_warning": "Cet utilisateur a été suspendu.", "suspended_warning": "Cet utilisateur a été suspendu.",
"user_suspended_warning": "Le compte de %s à été suspendu." "user_suspended_warning": "Le compte de %s à été suspendu."
} }
@ -217,7 +218,7 @@
}, },
"label": { "label": {
"language": "LANGUE", "language": "LANGUE",
"users": "UTILISATEURS", "users": "UTILISATEUR·RICE·S",
"category": "CATÉGORIE" "category": "CATÉGORIE"
}, },
"input": { "input": {
@ -255,7 +256,7 @@
}, },
"error": { "error": {
"item": { "item": {
"username": "Nom d'utilisateur", "username": "Nom dutilisateur",
"email": "Courriel", "email": "Courriel",
"password": "Mot de passe", "password": "Mot de passe",
"agreement": "Accord", "agreement": "Accord",
@ -370,7 +371,7 @@
"append_attachment": "Joindre un document", "append_attachment": "Joindre un document",
"append_poll": "Ajouter un Sondage", "append_poll": "Ajouter un Sondage",
"remove_poll": "Retirer le sondage", "remove_poll": "Retirer le sondage",
"custom_emoji_picker": "Sélecteur démojis personnalisé", "custom_emoji_picker": "Sélecteur démojis personnalisés",
"enable_content_warning": "Basculer lavertissement de contenu", "enable_content_warning": "Basculer lavertissement de contenu",
"disable_content_warning": "Désactiver l'avertissement de contenu", "disable_content_warning": "Désactiver l'avertissement de contenu",
"post_visibility_menu": "Menu de Visibilité de la publication" "post_visibility_menu": "Menu de Visibilité de la publication"
@ -405,7 +406,7 @@
"relationship_action_alert": { "relationship_action_alert": {
"confirm_unmute_user": { "confirm_unmute_user": {
"title": "Ne plus mettre en sourdine ce compte", "title": "Ne plus mettre en sourdine ce compte",
"message": "Êtes-vous sûr de vouloir mettre en sourdine %s" "message": "Êtes-vous sûr de vouloir désactiver la sourdine de %s"
}, },
"confirm_unblock_usre": { "confirm_unblock_usre": {
"title": "Débloquer le compte", "title": "Débloquer le compte",
@ -413,6 +414,12 @@
} }
} }
}, },
"follower": {
"footer": "Les abonné·e·s issus des autres serveurs ne sont pas affiché·e·s."
},
"following": {
"footer": "Follows from other servers are not displayed."
},
"search": { "search": {
"title": "Rechercher", "title": "Rechercher",
"search_bar": { "search_bar": {
@ -454,12 +461,12 @@
"Everything": "Tout", "Everything": "Tout",
"Mentions": "Mentions" "Mentions": "Mentions"
}, },
"user_followed_you": "%s followed you", "user_followed_you": "%s sest abonné à vous",
"user_favorited your post": "%s favorited your post", "user_favorited your post": "%s a mis votre pouet en favori",
"user_reblogged_your_post": "%s reblogged your post", "user_reblogged_your_post": "%s a partagé votre publication",
"user_mentioned_you": "%s mentioned you", "user_mentioned_you": "%s vous a mentionné",
"user_requested_to_follow_you": "%s requested to follow you", "user_requested_to_follow_you": "%s a demandé à vous suivre",
"user_your_poll_has_ended": "%s Your poll has ended", "user_your_poll_has_ended": "%s votre sondage est terminé",
"keyobard": { "keyobard": {
"show_everything": "Tout Afficher", "show_everything": "Tout Afficher",
"show_mentions": "Afficher les mentions" "show_mentions": "Afficher les mentions"
@ -496,7 +503,7 @@
"title": "Préférences", "title": "Préférences",
"true_black_dark_mode": "Vrai mode sombre", "true_black_dark_mode": "Vrai mode sombre",
"disable_avatar_animation": "Désactiver les avatars animés", "disable_avatar_animation": "Désactiver les avatars animés",
"disable_emoji_animation": "Désactiver les émoticônes animées", "disable_emoji_animation": "Désactiver les émojis animées",
"using_default_browser": "Utiliser le navigateur par défaut pour ouvrir les liens" "using_default_browser": "Utiliser le navigateur par défaut pour ouvrir les liens"
}, },
"boring_zone": { "boring_zone": {
@ -534,6 +541,16 @@
"show_next": "Afficher le suivant", "show_next": "Afficher le suivant",
"show_previous": "Afficher le précédent" "show_previous": "Afficher le précédent"
} }
},
"account_list": {
"tab_bar_hint": "Current selected profile: %s. Double tap then hold to show account switcher",
"dismiss_account_switcher": "Dismiss Account Switcher",
"add_account": "Ajouter un compte"
},
"wizard": {
"new_in_mastodon": "Nouveau dans Mastodon",
"multiple_account_switch_intro_description": "Basculez entre plusieurs comptes en appuyant de maniere prolongée sur le bouton profil.",
"accessibility_hint": "Tapotez deux fois pour fermer cet assistant"
} }
} }
} }

View File

@ -2,6 +2,26 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>a11y.plural.count.unread.notification</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@notification_count_unread_notification@</string>
<key>notification_count_unread_notification</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>%ld bhrath nach deach a leughadh</string>
<key>two</key>
<string>%ld bhrath nach deach a leughadh</string>
<key>few</key>
<string>%ld brathan nach deach a leughadh</string>
<key>other</key>
<string>%ld brath nach deach a leughadh</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_exceeds</key> <key>a11y.plural.count.input_limit_exceeds</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>

View File

@ -67,6 +67,7 @@
"done": "Deiseil", "done": "Deiseil",
"confirm": "Dearbh", "confirm": "Dearbh",
"continue": "Lean air adhart", "continue": "Lean air adhart",
"compose": "Sgrìobh",
"cancel": "Sguir dheth", "cancel": "Sguir dheth",
"discard": "Tilg air falbh", "discard": "Tilg air falbh",
"try_again": "Feuch ris a-rithist", "try_again": "Feuch ris a-rithist",
@ -413,6 +414,12 @@
} }
} }
}, },
"follower": {
"footer": "Cha dèid luchd-leantainn o fhrithealaichean eile a shealltainn."
},
"following": {
"footer": "Cha dèid cò air a leanas tu air frithealaichean eile a shealltainn."
},
"search": { "search": {
"title": "Lorg", "title": "Lorg",
"search_bar": { "search_bar": {
@ -534,6 +541,16 @@
"show_next": "Air adhart", "show_next": "Air adhart",
"show_previous": "Air ais" "show_previous": "Air ais"
} }
},
"account_list": {
"tab_bar_hint": "A phròifil air a taghadh: %s. Thoir gnogag dhùbailte is cùm sìos a ghearradh leum gu cunntas eile",
"dismiss_account_switcher": "Leig seachad taghadh a chunntais",
"add_account": "Cuir cunntas ris"
},
"wizard": {
"new_in_mastodon": "Na tha ùr ann am Mastodon",
"multiple_account_switch_intro_description": "Geàrr leum eadar iomadh cunntas le cumail sìos putan na pròifil.",
"accessibility_hint": "Thoir gnogag dhùbailte a leigeil seachad an draoidh seo"
} }
} }
} }

View File

@ -2,6 +2,22 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>a11y.plural.count.unread.notification</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@notification_count_unread_notification@</string>
<key>notification_count_unread_notification</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 unread notification</string>
<key>other</key>
<string>%ld unread notification</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_exceeds</key> <key>a11y.plural.count.input_limit_exceeds</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>

View File

@ -67,6 +67,7 @@
"done": "Done", "done": "Done",
"confirm": "Confirm", "confirm": "Confirm",
"continue": "Continue", "continue": "Continue",
"compose": "Compose",
"cancel": "Cancel", "cancel": "Cancel",
"discard": "Discard", "discard": "Discard",
"try_again": "Try Again", "try_again": "Try Again",
@ -413,6 +414,12 @@
} }
} }
}, },
"follower": {
"footer": "Followers from other servers are not displayed."
},
"following": {
"footer": "Follows from other servers are not displayed."
},
"search": { "search": {
"title": "Search", "title": "Search",
"search_bar": { "search_bar": {
@ -534,6 +541,16 @@
"show_next": "Show Next", "show_next": "Show Next",
"show_previous": "Show Previous" "show_previous": "Show Previous"
} }
},
"account_list": {
"tab_bar_hint": "Current selected profile: %s. Double tap then hold to show account switcher",
"dismiss_account_switcher": "Dismiss Account Switcher",
"add_account": "Add Account"
},
"wizard": {
"new_in_mastodon": "New in Mastodon",
"multiple_account_switch_intro_description": "Switch between multiple accounts by holding the profile button.",
"accessibility_hint": "Double tap to dismiss this wizard"
} }
} }
} }

View File

@ -2,6 +2,20 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>a11y.plural.count.unread.notification</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@notification_count_unread_notification@</string>
<key>notification_count_unread_notification</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>other</key>
<string>%ld unread notification</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_exceeds</key> <key>a11y.plural.count.input_limit_exceeds</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>
@ -69,7 +83,7 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>other</key> <key>other</key>
<string>%ld favorites</string> <string>%ld favorit</string>
</dict> </dict>
</dict> </dict>
<key>plural.count.reblog</key> <key>plural.count.reblog</key>
@ -97,7 +111,7 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>other</key> <key>other</key>
<string>%ld votes</string> <string>%ld suara</string>
</dict> </dict>
</dict> </dict>
<key>plural.count.voter</key> <key>plural.count.voter</key>
@ -111,7 +125,7 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>other</key> <key>other</key>
<string>%ld voters</string> <string>%ld pemilih</string>
</dict> </dict>
</dict> </dict>
<key>plural.people_talking</key> <key>plural.people_talking</key>

View File

@ -67,6 +67,7 @@
"done": "Selesai", "done": "Selesai",
"confirm": "Konfirmasi", "confirm": "Konfirmasi",
"continue": "Lanjut", "continue": "Lanjut",
"compose": "Compose",
"cancel": "Batal", "cancel": "Batal",
"discard": "Discard", "discard": "Discard",
"try_again": "Coba Lagi", "try_again": "Coba Lagi",
@ -267,7 +268,7 @@
"unreachable": "%s sepertinya tidak ada", "unreachable": "%s sepertinya tidak ada",
"taken": "%s sudah digunakan", "taken": "%s sudah digunakan",
"reserved": "%s is a reserved keyword", "reserved": "%s is a reserved keyword",
"accepted": "%s must be accepted", "accepted": "%s harus diterima",
"blank": "%s diperlukan", "blank": "%s diperlukan",
"invalid": "%s tidak valid", "invalid": "%s tidak valid",
"too_long": "%s terlalu panjang", "too_long": "%s terlalu panjang",
@ -355,7 +356,7 @@
"option_number": "Option %ld" "option_number": "Option %ld"
}, },
"content_warning": { "content_warning": {
"placeholder": "Write an accurate warning here..." "placeholder": "Tulis peringatan yang akurat di sini..."
}, },
"visibility": { "visibility": {
"public": "Publik", "public": "Publik",
@ -413,6 +414,12 @@
} }
} }
}, },
"follower": {
"footer": "Followers from other servers are not displayed."
},
"following": {
"footer": "Follows from other servers are not displayed."
},
"search": { "search": {
"title": "Cari", "title": "Cari",
"search_bar": { "search_bar": {
@ -534,6 +541,16 @@
"show_next": "Show Next", "show_next": "Show Next",
"show_previous": "Show Previous" "show_previous": "Show Previous"
} }
},
"account_list": {
"tab_bar_hint": "Current selected profile: %s. Double tap then hold to show account switcher",
"dismiss_account_switcher": "Dismiss Account Switcher",
"add_account": "Add Account"
},
"wizard": {
"new_in_mastodon": "New in Mastodon",
"multiple_account_switch_intro_description": "Switch between multiple accounts by holding the profile button.",
"accessibility_hint": "Double tap to dismiss this wizard"
} }
} }
} }

View File

@ -2,6 +2,20 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>a11y.plural.count.unread.notification</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@notification_count_unread_notification@</string>
<key>notification_count_unread_notification</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>other</key>
<string>%ld 件の未読通知</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_exceeds</key> <key>a11y.plural.count.input_limit_exceeds</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>
@ -13,7 +27,7 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>other</key> <key>other</key>
<string>%ld characters</string> <string>%ld 文字</string>
</dict> </dict>
</dict> </dict>
<key>a11y.plural.count.input_limit_remains</key> <key>a11y.plural.count.input_limit_remains</key>
@ -27,7 +41,7 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>other</key> <key>other</key>
<string>%ld characters</string> <string>%ld 文字</string>
</dict> </dict>
</dict> </dict>
<key>plural.count.metric_formatted.post</key> <key>plural.count.metric_formatted.post</key>
@ -97,7 +111,7 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>other</key> <key>other</key>
<string>%ld votes</string> <string>%ld</string>
</dict> </dict>
</dict> </dict>
<key>plural.count.voter</key> <key>plural.count.voter</key>
@ -181,7 +195,7 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>other</key> <key>other</key>
<string>%ld months left</string> <string>%ldか月前</string>
</dict> </dict>
</dict> </dict>
<key>date.day.left</key> <key>date.day.left</key>
@ -265,7 +279,7 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>other</key> <key>other</key>
<string>%ldM ago</string> <string>%ld分前</string>
</dict> </dict>
</dict> </dict>
<key>date.day.ago.abbr</key> <key>date.day.ago.abbr</key>

View File

@ -67,6 +67,7 @@
"done": "完了", "done": "完了",
"confirm": "確認", "confirm": "確認",
"continue": "続ける", "continue": "続ける",
"compose": "Compose",
"cancel": "キャンセル", "cancel": "キャンセル",
"discard": "破棄", "discard": "破棄",
"try_again": "再実行", "try_again": "再実行",
@ -191,7 +192,7 @@
}, },
"scene": { "scene": {
"welcome": { "welcome": {
"slogan": "Social networking\nback in your hands." "slogan": "ソーシャルネットワーキングを、あなたの手の中に."
}, },
"server_picker": { "server_picker": {
"title": "サーバーを選択", "title": "サーバーを選択",
@ -413,6 +414,12 @@
} }
} }
}, },
"follower": {
"footer": "Followers from other servers are not displayed."
},
"following": {
"footer": "Follows from other servers are not displayed."
},
"search": { "search": {
"title": "検索", "title": "検索",
"search_bar": { "search_bar": {
@ -534,6 +541,16 @@
"show_next": "次を見る", "show_next": "次を見る",
"show_previous": "前を見る" "show_previous": "前を見る"
} }
},
"account_list": {
"tab_bar_hint": "Current selected profile: %s. Double tap then hold to show account switcher",
"dismiss_account_switcher": "Dismiss Account Switcher",
"add_account": "アカウントを追加"
},
"wizard": {
"new_in_mastodon": "Mastodon の新機能",
"multiple_account_switch_intro_description": "プロフィールボタンを押して複数のアカウントを切り替えます。",
"accessibility_hint": "Double tap to dismiss this wizard"
} }
} }
} }

View File

@ -0,0 +1,390 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>a11y.plural.count.unread.notification</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@notification_count_unread_notification@</string>
<key>notification_count_unread_notification</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 agahdariya nexwendî</string>
<key>other</key>
<string>%ld agahdariyên nexwendî</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_exceeds</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>Sînorê têketinê derbas kir %#@character_count@</string>
<key>character_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 tîp</string>
<key>other</key>
<string>%ld tîp</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_remains</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>Sînorê têketinê %#@character_count@ maye</string>
<key>character_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 tîp</string>
<key>other</key>
<string>%ld tîp</string>
</dict>
</dict>
<key>plural.count.metric_formatted.post</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%@ %#@post_count@</string>
<key>post_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>şandî</string>
<key>other</key>
<string>şandî</string>
</dict>
</dict>
<key>plural.count.post</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@post_count@</string>
<key>post_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 şandî</string>
<key>other</key>
<string>%ld şandî</string>
</dict>
</dict>
<key>plural.count.favorite</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@favorite_count@</string>
<key>favorite_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 hezkirin</string>
<key>other</key>
<string>%ld hezkirin</string>
</dict>
</dict>
<key>plural.count.reblog</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@reblog_count@</string>
<key>reblog_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 ji nû ve nivîsandin</string>
<key>other</key>
<string>%ld ji nû ve nivîsandin</string>
</dict>
</dict>
<key>plural.count.vote</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@vote_count@</string>
<key>vote_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 deng</string>
<key>other</key>
<string>%ld deng</string>
</dict>
</dict>
<key>plural.count.voter</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@voter_count@</string>
<key>voter_count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 hilbijêr</string>
<key>other</key>
<string>%ld hilbijêr</string>
</dict>
</dict>
<key>plural.people_talking</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count_people_talking@</string>
<key>count_people_talking</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 mirov diaxive</string>
<key>other</key>
<string>%ld mirov diaxive</string>
</dict>
</dict>
<key>plural.count.following</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count_following@</string>
<key>count_following</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 dişopîne</string>
<key>other</key>
<string>%ld dişopîne</string>
</dict>
</dict>
<key>plural.count.follower</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count_follower@</string>
<key>count_follower</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 şopîner</string>
<key>other</key>
<string>%ld şopîner</string>
</dict>
</dict>
<key>date.year.left</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count_year_left@</string>
<key>count_year_left</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 sal berê</string>
<key>other</key>
<string>%ld sal berê</string>
</dict>
</dict>
<key>date.month.left</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count_month_left@</string>
<key>count_month_left</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 meh berê</string>
<key>other</key>
<string>%ld meh berê</string>
</dict>
</dict>
<key>date.day.left</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count_day_left@</string>
<key>count_day_left</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 roj berê</string>
<key>other</key>
<string>%ld roj berê</string>
</dict>
</dict>
<key>date.hour.left</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count_hour_left@</string>
<key>count_hour_left</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 demjimêr berê</string>
<key>other</key>
<string>%ld demjimêr berê</string>
</dict>
</dict>
<key>date.minute.left</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count_minute_left@</string>
<key>count_minute_left</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 xulek berê</string>
<key>other</key>
<string>%ld xulek berê</string>
</dict>
</dict>
<key>date.second.left</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count_second_left@</string>
<key>count_second_left</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 çirke berê</string>
<key>other</key>
<string>%ld çirke berê</string>
</dict>
</dict>
<key>date.year.ago.abbr</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count_year_ago_abbr@</string>
<key>count_year_ago_abbr</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 sal berê</string>
<key>other</key>
<string>%ld sal berê</string>
</dict>
</dict>
<key>date.month.ago.abbr</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count_month_ago_abbr@</string>
<key>count_month_ago_abbr</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 xulek berê</string>
<key>other</key>
<string>%ld xulek berê</string>
</dict>
</dict>
<key>date.day.ago.abbr</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count_day_ago_abbr@</string>
<key>count_day_ago_abbr</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 roj berê</string>
<key>other</key>
<string>%ld roj berê</string>
</dict>
</dict>
<key>date.hour.ago.abbr</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count_hour_ago_abbr@</string>
<key>count_hour_ago_abbr</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 demjimêr berê</string>
<key>other</key>
<string>%ld demjimêr berê</string>
</dict>
</dict>
<key>date.minute.ago.abbr</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count_minute_ago_abbr@</string>
<key>count_minute_ago_abbr</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 xulek berê</string>
<key>other</key>
<string>%ld xulek berê</string>
</dict>
</dict>
<key>date.second.ago.abbr</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@count_second_ago_abbr@</string>
<key>count_second_ago_abbr</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 çirke berê</string>
<key>other</key>
<string>%ld çirke berê</string>
</dict>
</dict>
</dict>
</plist>

View File

@ -0,0 +1,556 @@
{
"common": {
"alerts": {
"common": {
"please_try_again": "Ji kerema xwe dîsa biceribîne.",
"please_try_again_later": "Ji kerema xwe paşê dîsa biceribîne."
},
"sign_up_failure": {
"title": "Tomarkirin têkçû"
},
"server_error": {
"title": "Çewtiya rajekar"
},
"vote_failure": {
"title": "Dengdayîn têkçû",
"poll_ended": "Rapirsîya qediya"
},
"discard_post_content": {
"title": "Reşnivîsê paşguh bike",
"message": "Bipejrîne ku naveroka şandiyê ya hatiye nivîsandin paşguh bikî."
},
"publish_post_failure": {
"title": "Weşandin têkçû",
"message": "Weşandina şandiyê têkçû.\nJkx girêdana înternetê xwe kontrol bike.",
"attachments_message": {
"video_attach_with_photo": "Nikare vîdyoyekê tevlî şandiyê ku berê wêne tê de heye bike.",
"more_than_one_video": "Nikare ji bêtirî yek vîdyoyekê tevlî şandiyê bike."
}
},
"edit_profile_failure": {
"title": "Di serrastkirina profîlê çewtî",
"message": "Nikare profîlê serrast bike. Jkx dîsa biceribîne."
},
"sign_out": {
"title": "Derkeve",
"message": "Ma tu dixwazî ku derkevî?",
"confirm": "Derkeve"
},
"block_domain": {
"title": "Tu ji xwe bawerî, bi rastî tu dixwazî hemû %s asteng bikî? Di gelek rewşan de asteng kirin an jî bêdeng kirin têrê dike û tê tercîh kirin. Tu nikarî naveroka vê navperê di demnameyê an jî agahdariyên xwe de bibînî. Şopînerên te yê di vê navperê were jêbirin.",
"block_entire_domain": "Navperê asteng bike"
},
"save_photo_failure": {
"title": "Tomarkirina wêneyê têkçû",
"message": "Ji kerema xwe mafê bide gihîştina wênegehê çalak bike da ku wêne werin tomarkirin."
},
"delete_post": {
"title": "Ma tu dixwazî vê şandiyê jê bibî?",
"delete": "Jê bibe"
},
"clean_cache": {
"title": "Pêşbîrê pak bike",
"message": "Pêşbîra %s biserketî hate pakkirin."
}
},
"controls": {
"actions": {
"back": "Vegere",
"next": "Pêş",
"previous": "Paş",
"open": "Veke",
"add": "Tevlî bike",
"remove": "Rake",
"edit": "Serrast bike",
"save": "Tomar bike",
"ok": "BAŞ E",
"done": "Qediya",
"confirm": "Bipejirîne",
"continue": "Bidomîne",
"compose": "Binivîsîne",
"cancel": "Dev jê berde",
"discard": "Biavêje",
"try_again": "Dîsa biceribîne",
"take_photo": "Wêne bikişîne",
"save_photo": "Wêneyê tomar bike",
"copy_photo": "Wêneyê jê bigire",
"sign_in": "Têkeve",
"sign_up": "Tomar bibe",
"see_more": "Bêtir bibîne",
"preview": "Pêşdîtin",
"share": "Parve bike",
"share_user": "%s parve bike",
"share_post": "Şandiyê parve bike",
"open_in_safari": "Di Safariyê de veke",
"find_people": "Mirovan bo şopandinê bibîne",
"manually_search": "Ji devlê bi destan lêgerînê bike",
"skip": "Derbas bike",
"reply": "Bersivê bide",
"report_user": "%s ragihîne",
"block_domain": "%s asteng bike",
"unblock_domain": "%s asteng neke",
"settings": "Sazkarî",
"delete": "Jê bibe"
},
"tabs": {
"home": "Serrûpel",
"search": "Bigere",
"notification": "Agahdarî",
"profile": "Profîl"
},
"keyboard": {
"common": {
"switch_to_tab": "Biguherîne bo %s",
"compose_new_post": "Şandiyeke nû binivsîne",
"show_favorites": "Bijarteyan nîşan bide",
"open_settings": "Sazkariyan Veke"
},
"timeline": {
"previous_status": "Şandeya paş",
"next_status": "Şandiya pêş",
"open_status": "Şandiyê veke",
"open_author_profile": "Profîla nivîskaran veke",
"open_reblogger_profile": "Profîla nivîskaran veke",
"reply_status": "Bersivê bide şandiyê",
"toggle_reblog": "Ji vû nivîsandin di şandiyê de biguherîne",
"toggle_favorite": "Li ser şandiyê bijarte biguherîne",
"toggle_content_warning": "Hişyariya naverokê biguherîne",
"preview_image": "Pêşdîtina wêneyê"
},
"segmented_control": {
"previous_section": "Beşa paş",
"next_section": "Beşa pêş"
}
},
"status": {
"user_reblogged": "%s ji nû ve hate nivîsandin",
"user_replied_to": "Bersiv da %s",
"show_post": "Şandiyê nîşan bide",
"show_user_profile": "Profîla bikarhêner nîşan bide",
"content_warning": "Hişyariya naverokê",
"media_content_warning": "Ji bo eşkerekirinê li derekî bitikîne",
"poll": {
"vote": "Deng bide",
"closed": "Girtî"
},
"actions": {
"reply": "Bersivê bide",
"reblog": "Ji nû ve nivîsandin",
"unreblog": "Ji nû ve nivîsandinê vegere",
"favorite": "Bijarte",
"unfavorite": "Nebijarte",
"menu": "Kulîn"
},
"tag": {
"url": "URL",
"mention": "Qalkirin",
"link": "Girêdan",
"hashtag": "Hashtag",
"email": "E-name",
"emoji": "Emojî"
}
},
"friendship": {
"follow": "Bişopîne",
"following": "Dişopîne",
"request": "Daxwaz bike",
"pending": "Tê nirxandin",
"block": "Asteng bike",
"block_user": "%s asteng bike",
"block_domain": "%s asteng bike",
"unblock": "Astengiyê rake",
"unblock_user": "%s asteng neke",
"blocked": "Astengkirî",
"mute": "Bêdeng bike",
"mute_user": "%s bêdeng bike",
"unmute": "Bêdeng neke",
"unmute_user": "%s bêdeng neke",
"muted": "Bêdengkirî",
"edit_info": "Zanyariyan serrast bike"
},
"timeline": {
"filtered": "Parzûnkirî",
"timestamp": {
"now": "Niha"
},
"loader": {
"load_missing_posts": "Şandiyên wendayî bar bike",
"loading_missing_posts": "Şandiyên wendayî tên barkirin...",
"show_more_replies": "Bêtir bersivan nîşan bide"
},
"header": {
"no_status_found": "Tu şandî nehate dîtin",
"blocking_warning": "Tu nikarî profîla vî/ê bikarhênerî bibînî\nHeya ku tu astengiyê li ser wî/ê ranekî.\nProfîla te ji wan ra wiha xuya dike.",
"user_blocking_warning": "Tu nikarî profîla %s bibînî\nHeya ku tu astengiyê li ser wî/ê ranekî.\nProfîla te ji wan ra wiha xuya dike.",
"blocked_warning": "Tu nikarî profîla vî/ê bikarhênerî bibînî\nheya ku ew astengiyê li ser te rakin.",
"user_blocked_warning": "Tu nikarî profîla %s bibînî\nHeta ku astengîya te rakin.",
"suspended_warning": "Ev bikarhêner hatiye rawestandin.",
"user_suspended_warning": "Ajimêra %s hatiye rawestandin."
}
}
}
},
"scene": {
"welcome": {
"slogan": "Torên civakî\ndi destên te de."
},
"server_picker": {
"title": "Rajekarekê hilbijêre,\nHer kîjan rajekar be.",
"button": {
"category": {
"all": "Hemû",
"all_accessiblity_description": "Beş: Hemû",
"academia": "akademî",
"activism": "çalakî",
"food": "xwarin",
"furry": "furry",
"games": "lîsk",
"general": "giştî",
"journalism": "rojnamevanî",
"lgbt": "lgbt",
"regional": "herêmî",
"art": "huner",
"music": "muzîk",
"tech": "teknolojî"
},
"see_less": "Kêmtir bibîne",
"see_more": "Bêtir bibîne"
},
"label": {
"language": "ZIMAN",
"users": "BIKARHÊNER",
"category": "BEŞ"
},
"input": {
"placeholder": "Rajekarekî bibîne an jî beşdarî ya xwe bibe..."
},
"empty_state": {
"finding_servers": "Peydakirina rajekarên berdest...",
"bad_network": "Di dema barkirina daneyan da çewtî derket. Girêdana xwe ya înternetê kontrol bike.",
"no_results": "Encam tune"
}
},
"register": {
"title": "Ji me re hinekî qala xwe bike.",
"input": {
"avatar": {
"delete": "Jê bibe"
},
"username": {
"placeholder": "navê bikarhêner",
"duplicate_prompt": "Navê vê bikarhêner tê girtin."
},
"display_name": {
"placeholder": "navê nîşanê"
},
"email": {
"placeholder": "e-name"
},
"password": {
"placeholder": "pêborîn",
"hint": "Pêborîna te herî kêm divê ji 8 tîpan pêk bê"
},
"invite": {
"registration_user_invite_request": "Tu çima dixwazî beşdar bibî?"
}
},
"error": {
"item": {
"username": "Navê bikarhêner",
"email": "E-name",
"password": "Pêborîn",
"agreement": "Peyman",
"locale": "Zimanê navrûyê",
"reason": "Sedem"
},
"reason": {
"blocked": "%s peydekerê e-peyamê yê qedexekirî dihewîne",
"unreachable": "%s xuya ye ku tune ye",
"taken": "%s jixwe tê bikaranîn",
"reserved": "%s peyveke parastî ye",
"accepted": "%s divê were pejirandin",
"blank": "%s pêwist e",
"invalid": "%s ne derbasdar e",
"too_long": "%s pir dirêj e",
"too_short": "%s pir kurt e",
"inclusion": "%s ne nirxek piştgirî ye"
},
"special": {
"username_invalid": "Navê bikarhêner divê tenê ji tîpên alfajimarî û binxêz pêk be",
"username_too_long": "Navê bikarhêner pir dirêj e (ji 30 tîpan dirêjtir nabe)",
"email_invalid": "Ev navnîşaneke e-nameyê ne derbasdar e",
"password_too_short": "Pêborîn pir kurt e (divê herî kêm 8 tîp be)"
}
}
},
"server_rules": {
"title": "Hinek rêzikên bingehîn.",
"subtitle": "Ev rêzik ji aliyê rêvebirên %s ve tên sazkirin.",
"prompt": "Bi domandinê, tu ji bo %s di bin mercên bikaranînê û polîtîkaya nepenîtiyê dipejirînî.",
"terms_of_service": "mercên bikaranînê",
"privacy_policy": "polîtikaya nihêniyê",
"button": {
"confirm": "Ez dipejirînim"
}
},
"confirm_email": {
"title": "Tiştekî dawî.",
"subtitle": "Me tenê e-nameyek ji %s re şand,\ngirêdanê bitikne da ku ajimêra xwe bidî piştrastkirin.",
"button": {
"open_email_app": "Sepana e-nameyê veke",
"dont_receive_email": "Min hîç e-nameyeke nesitand"
},
"dont_receive_email": {
"title": "E-nameyê xwe kontrol bike",
"description": "Kontrol bike ka navnîşana e-nameya te rast e û her wiha peldanka xwe ya spam.",
"resend_email": "E-namyê yê dîsa bişîne"
},
"open_email_app": {
"title": "Nameyên xwe yên wergirtî kontrol bike.",
"description": "Me tenê ji te re e-nameyek şand. Heke nehatiye peldanka xwe ya spamê kontrol bike.",
"mail": "E-name",
"open_email_client": "Rajegirê e-nameyê veke"
}
},
"home_timeline": {
"title": "Serrûpel",
"navigation_bar_state": {
"offline": "Derhêl",
"new_posts": "Şandiyên nû bibîne",
"published": "Hate weşandin!",
"Publishing": "Şandî tê weşandin..."
}
},
"suggestion_account": {
"title": "Kesên bo ku bişopînî bibîne",
"follow_explain": "Gava tu kesekî dişopînî, tu yê şandiyê wan di serrûpelê de bibîne."
},
"compose": {
"title": {
"new_post": "Şandiya nû",
"new_reply": "Bersiva nû"
},
"media_selection": {
"camera": "Wêne bikişîne",
"photo_library": "Wênegeh",
"browse": "Bigere"
},
"content_input_placeholder": "Tiştê ku di hişê te de ye binivîsin an jî pêve bike",
"compose_action": "Biweşîne",
"replying_to_user": "bersiv bide %s",
"attachment": {
"photo": "wêne",
"video": "vîdyo",
"attachment_broken": "Ev %s naxebite û nayê barkirin\n li ser Mastodon.",
"description_photo": "Wêneyê ji bo kêmbînên dîtbar bide nasîn...",
"description_video": "Vîdyoyê ji bo kêmbînên dîtbar bide nasîn..."
},
"poll": {
"duration_time": "Dirêjî: %s",
"thirty_minutes": "30 xulek",
"one_hour": "1 Demjimêr",
"six_hours": "6 Demjimêr",
"one_day": "1 Roj",
"three_days": "3 Roj",
"seven_days": "7 Roj",
"option_number": "Vebijêrk %ld"
},
"content_warning": {
"placeholder": "Li vir hişyariyek hûrgilî binivîsine..."
},
"visibility": {
"public": "Gelemperî",
"unlisted": "Nerêzokkirî",
"private": "Tenê şopîneran",
"direct": "Tenê mirovên ku min qalkirî"
},
"auto_complete": {
"space_to_add": "Bicîhkirinê tevlî bike"
},
"accessibility": {
"append_attachment": "Pêvek tevlî bike",
"append_poll": "Rapirsî tevlî bike",
"remove_poll": "Rapirsî rake",
"custom_emoji_picker": "Hilbijêrê emojî yên kesanekirî",
"enable_content_warning": "Hişyariya naverokê çalak bike",
"disable_content_warning": "Hişyariya naverokê neçalak bike",
"post_visibility_menu": "Kulîna xuyabûna şandiyê"
},
"keyboard": {
"discard_post": "Şandî paşguh bike",
"publish_post": "Şandiyê biweşîne",
"toggle_poll": "Rapirsiyê biguherîne",
"toggle_content_warning": "Hişyariya naverokê biguherîne",
"append_attachment_entry": "Pêvek tevlî bike - %s",
"select_visibility_entry": "Xuyabûnê hilbijêre - %s"
}
},
"profile": {
"dashboard": {
"posts": "şandî",
"following": "dişopîne",
"followers": "şopîner"
},
"fields": {
"add_row": "Rêzê tevlî bike",
"placeholder": {
"label": "Nîşan",
"content": "Naverok"
}
},
"segmented_control": {
"posts": "Şandî",
"replies": "Bersiv",
"media": "Medya"
},
"relationship_action_alert": {
"confirm_unmute_user": {
"title": "Ajimêrê bêdeng neke",
"message": "Ji bo vekirina bêdengkirinê bipejirîne %s"
},
"confirm_unblock_usre": {
"title": "Astengiyê li ser ajimêr rake",
"message": "Ji bo rakirina astengkirinê bipejirîne %s"
}
}
},
"follower": {
"footer": "Şopîner ji rajekerên din nayê dîtin."
},
"following": {
"footer": "Şopandin ji rajekerên din nayê dîtin."
},
"search": {
"title": "Bigere",
"search_bar": {
"placeholder": "Li hashtag û bikarhêneran bigere",
"cancel": "Dev jê berde"
},
"recommend": {
"button_text": "Hemûyan bibîne",
"hash_tag": {
"title": "Rojev li ser Mastodon",
"description": "Hashtag ên ku pir balê dikişînin",
"people_talking": "%s kes diaxivin"
},
"accounts": {
"title": "Ajimêrên ku belkî tu jê hez bikî",
"description": "Dibe ku tu bixwazî van ajimêran bişopînî",
"follow": "Bişopîne"
}
},
"searching": {
"segment": {
"all": "Hemû",
"people": "Mirov",
"hashtags": "Hashtag",
"posts": "Şandî"
},
"empty_state": {
"no_results": "Encam tune"
},
"recent_search": "Lêgerînên dawî",
"clear": "Pak bike"
}
},
"favorite": {
"title": "Bijarteyên te"
},
"notification": {
"title": {
"Everything": "Her tişt",
"Mentions": "Qalkirin"
},
"user_followed_you": "%s te şopand",
"user_favorited your post": "%s şandiya te hez kir",
"user_reblogged_your_post": "%s posta we ji nû ve tomar kir",
"user_mentioned_you": "%s qale te kir",
"user_requested_to_follow_you": "%s dixwazê te bişopîne",
"user_your_poll_has_ended": "Rapirsîya te qediya",
"keyobard": {
"show_everything": "Her tiştî nîşan bide",
"show_mentions": "Qalkirinan nîşan bike"
}
},
"thread": {
"back_title": "Şandî",
"title": "Şandî ji %s"
},
"settings": {
"title": "Sazkarî",
"section": {
"appearance": {
"title": "Xuyang",
"automatic": "Xweber",
"light": "Her dem ronî",
"dark": "Her dem tarî"
},
"notifications": {
"title": "Agahdarî",
"favorites": "Şandiyên min hez kir",
"follows": "Min dişopîne",
"boosts": "Şandiya min ji nû ve nivîsand",
"mentions": "Qale min kir",
"trigger": {
"anyone": "her kes",
"follower": "şopînerek",
"follow": "her kesê ku dişopînim",
"noone": "ne yek",
"title": "Min agahdar bike gava"
}
},
"preference": {
"title": "Hilbijarte",
"true_black_dark_mode": "Moda tarî ya reş a rastîn",
"disable_avatar_animation": "Avatarên anîmasyonî neçalak bike",
"disable_emoji_animation": "Emojiyên anîmasyonî neçalak bike",
"using_default_browser": "Ji bo vekirina girêdanan geroka berdest bi kar bîne"
},
"boring_zone": {
"title": "Devera acizker",
"account_settings": "Sazkariyên ajimêr",
"terms": "Mercên bikaranînê",
"privacy": "Polîtikaya nihêniyê"
},
"spicy_zone": {
"title": "Devera germ",
"clear": "Pêşbîra medyayê pak bike",
"signout": "Derkeve"
}
},
"footer": {
"mastodon_description": "Mastodon nermalava çavkaniya vekirî ye. Tu dikarî pirsgirêkan li ser GitHub-ê ragihînî di %s (%s) de"
},
"keyboard": {
"close_settings_window": "Sazkariyên çarçoveyê bigire"
}
},
"report": {
"title": "%s ragihîne",
"step1": "Gav 1 ji 2",
"step2": "Gav 2 ji 2",
"content1": "Şandiyên din hene ku tu dixwazî tevlî ragihandinê bikî?",
"content2": "Derbarê vê ragihandinê de tiştek heye ku divê çavdêr bizanin?",
"send": "Ragihandinê bişîne",
"skip_to_send": "Bêyî şirove bişîne",
"text_placeholder": "Şiroveyên daxwazkirê binivîsine an jî pê ve bike"
},
"preview": {
"keyboard": {
"close_preview": "Pêşdîtin bigire",
"show_next": "A pêş nîşan bide",
"show_previous": "A paş nîşan bide"
}
},
"account_list": {
"tab_bar_hint": "Profîla hilbijartî ya niha: %s. Du caran bitikîne û paşê dest bide ser da ku guhêrbara ajimêr were nîşandan",
"dismiss_account_switcher": "Guherkera ajimêrê paş guh bike",
"add_account": "Ajimêr tevlî bike"
},
"wizard": {
"new_in_mastodon": "Nû di Mastodon de",
"multiple_account_switch_intro_description": "Dest bide ser bişkoja profîlê da ku di navbera gelek ajimêrann de biguherînî.",
"accessibility_hint": "Du caran bitikîne da ku çarçoveyahilpekok ji holê rakî"
}
}
}

View File

@ -0,0 +1,6 @@
{
"NSCameraUsageDescription": "Bo kişandina wêneyê ji bo rewşa şandiyan tê bikaranîn",
"NSPhotoLibraryAddUsageDescription": "Ji bo tomarkirina wêneyê di pirtûkxaneya wêneyan de tê bikaranîn",
"NewPostShortcutItemTitle": "Şandiya nû",
"SearchShortcutItemTitle": "Bigere"
}

View File

@ -2,6 +2,20 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>a11y.plural.count.unread.notification</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@notification_count_unread_notification@</string>
<key>notification_count_unread_notification</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>other</key>
<string>%ld unread notification</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_exceeds</key> <key>a11y.plural.count.input_limit_exceeds</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>

View File

@ -67,6 +67,7 @@
"done": "완료", "done": "완료",
"confirm": "확인", "confirm": "확인",
"continue": "계속", "continue": "계속",
"compose": "Compose",
"cancel": "취소", "cancel": "취소",
"discard": "버리기", "discard": "버리기",
"try_again": "다시 시도", "try_again": "다시 시도",
@ -413,6 +414,12 @@
} }
} }
}, },
"follower": {
"footer": "Followers from other servers are not displayed."
},
"following": {
"footer": "Follows from other servers are not displayed."
},
"search": { "search": {
"title": "검색", "title": "검색",
"search_bar": { "search_bar": {
@ -534,6 +541,16 @@
"show_next": "다음 보기", "show_next": "다음 보기",
"show_previous": "이전 보기" "show_previous": "이전 보기"
} }
},
"account_list": {
"tab_bar_hint": "Current selected profile: %s. Double tap then hold to show account switcher",
"dismiss_account_switcher": "Dismiss Account Switcher",
"add_account": "Add Account"
},
"wizard": {
"new_in_mastodon": "New in Mastodon",
"multiple_account_switch_intro_description": "Switch between multiple accounts by holding the profile button.",
"accessibility_hint": "Double tap to dismiss this wizard"
} }
} }
} }

View File

@ -2,6 +2,22 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>a11y.plural.count.unread.notification</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@notification_count_unread_notification@</string>
<key>notification_count_unread_notification</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 unread notification</string>
<key>other</key>
<string>%ld unread notification</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_exceeds</key> <key>a11y.plural.count.input_limit_exceeds</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>

View File

@ -67,6 +67,7 @@
"done": "Klaar", "done": "Klaar",
"confirm": "Bevestigen", "confirm": "Bevestigen",
"continue": "Doorgaan", "continue": "Doorgaan",
"compose": "Compose",
"cancel": "Annuleren", "cancel": "Annuleren",
"discard": "Weggooien", "discard": "Weggooien",
"try_again": "Probeer Opnieuw", "try_again": "Probeer Opnieuw",
@ -413,6 +414,12 @@
} }
} }
}, },
"follower": {
"footer": "Followers from other servers are not displayed."
},
"following": {
"footer": "Follows from other servers are not displayed."
},
"search": { "search": {
"title": "Zoeken", "title": "Zoeken",
"search_bar": { "search_bar": {
@ -534,6 +541,16 @@
"show_next": "Volgende", "show_next": "Volgende",
"show_previous": "Vorige" "show_previous": "Vorige"
} }
},
"account_list": {
"tab_bar_hint": "Current selected profile: %s. Double tap then hold to show account switcher",
"dismiss_account_switcher": "Dismiss Account Switcher",
"add_account": "Add Account"
},
"wizard": {
"new_in_mastodon": "New in Mastodon",
"multiple_account_switch_intro_description": "Switch between multiple accounts by holding the profile button.",
"accessibility_hint": "Double tap to dismiss this wizard"
} }
} }
} }

View File

@ -2,6 +2,22 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>a11y.plural.count.unread.notification</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@notification_count_unread_notification@</string>
<key>notification_count_unread_notification</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 unread notification</string>
<key>other</key>
<string>%ld unread notification</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_exceeds</key> <key>a11y.plural.count.input_limit_exceeds</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>

View File

@ -67,6 +67,7 @@
"done": "Done", "done": "Done",
"confirm": "Confirm", "confirm": "Confirm",
"continue": "Continue", "continue": "Continue",
"compose": "Compose",
"cancel": "Cancel", "cancel": "Cancel",
"discard": "Discard", "discard": "Discard",
"try_again": "Try Again", "try_again": "Try Again",
@ -413,6 +414,12 @@
} }
} }
}, },
"follower": {
"footer": "Followers from other servers are not displayed."
},
"following": {
"footer": "Follows from other servers are not displayed."
},
"search": { "search": {
"title": "Search", "title": "Search",
"search_bar": { "search_bar": {
@ -534,6 +541,16 @@
"show_next": "Show Next", "show_next": "Show Next",
"show_previous": "Show Previous" "show_previous": "Show Previous"
} }
},
"account_list": {
"tab_bar_hint": "Current selected profile: %s. Double tap then hold to show account switcher",
"dismiss_account_switcher": "Dismiss Account Switcher",
"add_account": "Add Account"
},
"wizard": {
"new_in_mastodon": "New in Mastodon",
"multiple_account_switch_intro_description": "Switch between multiple accounts by holding the profile button.",
"accessibility_hint": "Double tap to dismiss this wizard"
} }
} }
} }

View File

@ -2,6 +2,22 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>a11y.plural.count.unread.notification</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@notification_count_unread_notification@</string>
<key>notification_count_unread_notification</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 unread notification</string>
<key>other</key>
<string>%ld unread notification</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_exceeds</key> <key>a11y.plural.count.input_limit_exceeds</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>

View File

@ -67,6 +67,7 @@
"done": "Done", "done": "Done",
"confirm": "Confirm", "confirm": "Confirm",
"continue": "Continue", "continue": "Continue",
"compose": "Compose",
"cancel": "Cancel", "cancel": "Cancel",
"discard": "Discard", "discard": "Discard",
"try_again": "Try Again", "try_again": "Try Again",
@ -413,6 +414,12 @@
} }
} }
}, },
"follower": {
"footer": "Followers from other servers are not displayed."
},
"following": {
"footer": "Follows from other servers are not displayed."
},
"search": { "search": {
"title": "Search", "title": "Search",
"search_bar": { "search_bar": {
@ -534,6 +541,16 @@
"show_next": "Show Next", "show_next": "Show Next",
"show_previous": "Show Previous" "show_previous": "Show Previous"
} }
},
"account_list": {
"tab_bar_hint": "Current selected profile: %s. Double tap then hold to show account switcher",
"dismiss_account_switcher": "Dismiss Account Switcher",
"add_account": "Add Account"
},
"wizard": {
"new_in_mastodon": "New in Mastodon",
"multiple_account_switch_intro_description": "Switch between multiple accounts by holding the profile button.",
"accessibility_hint": "Double tap to dismiss this wizard"
} }
} }
} }

View File

@ -2,6 +2,24 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>a11y.plural.count.unread.notification</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@notification_count_unread_notification@</string>
<key>notification_count_unread_notification</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 unread notification</string>
<key>few</key>
<string>%ld unread notification</string>
<key>other</key>
<string>%ld unread notification</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_exceeds</key> <key>a11y.plural.count.input_limit_exceeds</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>

View File

@ -67,6 +67,7 @@
"done": "Done", "done": "Done",
"confirm": "Confirm", "confirm": "Confirm",
"continue": "Continue", "continue": "Continue",
"compose": "Compose",
"cancel": "Cancel", "cancel": "Cancel",
"discard": "Discard", "discard": "Discard",
"try_again": "Try Again", "try_again": "Try Again",
@ -413,6 +414,12 @@
} }
} }
}, },
"follower": {
"footer": "Followers from other servers are not displayed."
},
"following": {
"footer": "Follows from other servers are not displayed."
},
"search": { "search": {
"title": "Search", "title": "Search",
"search_bar": { "search_bar": {
@ -534,6 +541,16 @@
"show_next": "Show Next", "show_next": "Show Next",
"show_previous": "Show Previous" "show_previous": "Show Previous"
} }
},
"account_list": {
"tab_bar_hint": "Current selected profile: %s. Double tap then hold to show account switcher",
"dismiss_account_switcher": "Dismiss Account Switcher",
"add_account": "Add Account"
},
"wizard": {
"new_in_mastodon": "New in Mastodon",
"multiple_account_switch_intro_description": "Switch between multiple accounts by holding the profile button.",
"accessibility_hint": "Double tap to dismiss this wizard"
} }
} }
} }

View File

@ -2,10 +2,30 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>a11y.plural.count.unread.notification</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@notification_count_unread_notification@</string>
<key>notification_count_unread_notification</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 unread notification</string>
<key>few</key>
<string>%ld unread notification</string>
<key>many</key>
<string>%ld unread notification</string>
<key>other</key>
<string>%ld unread notification</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_exceeds</key> <key>a11y.plural.count.input_limit_exceeds</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>
<string>Input limit exceeds %#@character_count@</string> <string>Лимит превышен на %#@character_count@</string>
<key>character_count</key> <key>character_count</key>
<dict> <dict>
<key>NSStringFormatSpecTypeKey</key> <key>NSStringFormatSpecTypeKey</key>
@ -13,19 +33,19 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>one</key> <key>one</key>
<string>1 character</string> <string>%ld символ</string>
<key>few</key> <key>few</key>
<string>%ld characters</string> <string>%ld символа</string>
<key>many</key> <key>many</key>
<string>%ld characters</string> <string>%ld символов</string>
<key>other</key> <key>other</key>
<string>%ld characters</string> <string>%ld символа</string>
</dict> </dict>
</dict> </dict>
<key>a11y.plural.count.input_limit_remains</key> <key>a11y.plural.count.input_limit_remains</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>
<string>Input limit remains %#@character_count@</string> <string>%#@character_count@</string>
<key>character_count</key> <key>character_count</key>
<dict> <dict>
<key>NSStringFormatSpecTypeKey</key> <key>NSStringFormatSpecTypeKey</key>
@ -33,13 +53,13 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>one</key> <key>one</key>
<string>1 character</string> <string>%ld символ остался</string>
<key>few</key> <key>few</key>
<string>%ld characters</string> <string>%ld символа осталось</string>
<key>many</key> <key>many</key>
<string>%ld characters</string> <string>%ld символов осталось</string>
<key>other</key> <key>other</key>
<string>%ld characters</string> <string>%ld символа осталось</string>
</dict> </dict>
</dict> </dict>
<key>plural.count.metric_formatted.post</key> <key>plural.count.metric_formatted.post</key>
@ -53,13 +73,13 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>one</key> <key>one</key>
<string>post</string> <string>пост</string>
<key>few</key> <key>few</key>
<string>posts</string> <string>поста</string>
<key>many</key> <key>many</key>
<string>posts</string> <string>постов</string>
<key>other</key> <key>other</key>
<string>posts</string> <string>поста</string>
</dict> </dict>
</dict> </dict>
<key>plural.count.post</key> <key>plural.count.post</key>
@ -133,13 +153,13 @@
<key>NSStringFormatValueTypeKey</key> <key>NSStringFormatValueTypeKey</key>
<string>ld</string> <string>ld</string>
<key>one</key> <key>one</key>
<string>1 vote</string> <string>%ld голос</string>
<key>few</key> <key>few</key>
<string>%ld votes</string> <string>%ld голоса</string>
<key>many</key> <key>many</key>
<string>%ld votes</string> <string>%ld голосов</string>
<key>other</key> <key>other</key>
<string>%ld votes</string> <string>%ld голоса</string>
</dict> </dict>
</dict> </dict>
<key>plural.count.voter</key> <key>plural.count.voter</key>

View File

@ -67,6 +67,7 @@
"done": "Готово", "done": "Готово",
"confirm": "Подтвердить", "confirm": "Подтвердить",
"continue": "Продолжить", "continue": "Продолжить",
"compose": "Compose",
"cancel": "Отмена", "cancel": "Отмена",
"discard": "Отмена", "discard": "Отмена",
"try_again": "Попробовать снова", "try_again": "Попробовать снова",
@ -413,6 +414,12 @@
} }
} }
}, },
"follower": {
"footer": "Followers from other servers are not displayed."
},
"following": {
"footer": "Follows from other servers are not displayed."
},
"search": { "search": {
"title": "Поиск", "title": "Поиск",
"search_bar": { "search_bar": {
@ -534,6 +541,16 @@
"show_next": "Следующее изображение", "show_next": "Следующее изображение",
"show_previous": "Предыдущее изображение" "show_previous": "Предыдущее изображение"
} }
},
"account_list": {
"tab_bar_hint": "Current selected profile: %s. Double tap then hold to show account switcher",
"dismiss_account_switcher": "Dismiss Account Switcher",
"add_account": "Add Account"
},
"wizard": {
"new_in_mastodon": "New in Mastodon",
"multiple_account_switch_intro_description": "Switch between multiple accounts by holding the profile button.",
"accessibility_hint": "Double tap to dismiss this wizard"
} }
} }
} }

View File

@ -2,5 +2,5 @@
"NSCameraUsageDescription": "Used to take photo for post status", "NSCameraUsageDescription": "Used to take photo for post status",
"NSPhotoLibraryAddUsageDescription": "Used to save photo into the Photo Library", "NSPhotoLibraryAddUsageDescription": "Used to save photo into the Photo Library",
"NewPostShortcutItemTitle": "New Post", "NewPostShortcutItemTitle": "New Post",
"SearchShortcutItemTitle": "Search" "SearchShortcutItemTitle": "Поиск"
} }

View File

@ -2,6 +2,22 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>a11y.plural.count.unread.notification</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@notification_count_unread_notification@</string>
<key>notification_count_unread_notification</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 unread notification</string>
<key>other</key>
<string>%ld unread notification</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_exceeds</key> <key>a11y.plural.count.input_limit_exceeds</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>

View File

@ -67,6 +67,7 @@
"done": "Done", "done": "Done",
"confirm": "Confirm", "confirm": "Confirm",
"continue": "Fortsätt", "continue": "Fortsätt",
"compose": "Compose",
"cancel": "Avbryt", "cancel": "Avbryt",
"discard": "Discard", "discard": "Discard",
"try_again": "Försök igen", "try_again": "Försök igen",
@ -413,6 +414,12 @@
} }
} }
}, },
"follower": {
"footer": "Followers from other servers are not displayed."
},
"following": {
"footer": "Follows from other servers are not displayed."
},
"search": { "search": {
"title": "Search", "title": "Search",
"search_bar": { "search_bar": {
@ -454,12 +461,12 @@
"Everything": "Everything", "Everything": "Everything",
"Mentions": "Mentions" "Mentions": "Mentions"
}, },
"user_followed_you": "%s followed you", "user_followed_you": "%s följde dig",
"user_favorited your post": "%s favorited your post", "user_favorited your post": "%s favorited your post",
"user_reblogged_your_post": "%s reblogged your post", "user_reblogged_your_post": "%s reblogged your post",
"user_mentioned_you": "%s mentioned you", "user_mentioned_you": "%s nämnde dig",
"user_requested_to_follow_you": "%s requested to follow you", "user_requested_to_follow_you": "%s har begärt att följa dig",
"user_your_poll_has_ended": "%s Your poll has ended", "user_your_poll_has_ended": "%s Omröstningen har avslutats",
"keyobard": { "keyobard": {
"show_everything": "Show Everything", "show_everything": "Show Everything",
"show_mentions": "Show Mentions" "show_mentions": "Show Mentions"
@ -534,6 +541,16 @@
"show_next": "Show Next", "show_next": "Show Next",
"show_previous": "Show Previous" "show_previous": "Show Previous"
} }
},
"account_list": {
"tab_bar_hint": "Current selected profile: %s. Double tap then hold to show account switcher",
"dismiss_account_switcher": "Dismiss Account Switcher",
"add_account": "Lägg till konto"
},
"wizard": {
"new_in_mastodon": "New in Mastodon",
"multiple_account_switch_intro_description": "Switch between multiple accounts by holding the profile button.",
"accessibility_hint": "Double tap to dismiss this wizard"
} }
} }
} }

View File

@ -2,6 +2,22 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>a11y.plural.count.unread.notification</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@notification_count_unread_notification@</string>
<key>notification_count_unread_notification</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
<string>1 unread notification</string>
<key>other</key>
<string>%ld unread notification</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_exceeds</key> <key>a11y.plural.count.input_limit_exceeds</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>

View File

@ -67,6 +67,7 @@
"done": "Done", "done": "Done",
"confirm": "Confirm", "confirm": "Confirm",
"continue": "Fortsätt", "continue": "Fortsätt",
"compose": "Compose",
"cancel": "Avbryt", "cancel": "Avbryt",
"discard": "Discard", "discard": "Discard",
"try_again": "Försök igen", "try_again": "Försök igen",
@ -413,6 +414,12 @@
} }
} }
}, },
"follower": {
"footer": "Followers from other servers are not displayed."
},
"following": {
"footer": "Follows from other servers are not displayed."
},
"search": { "search": {
"title": "Search", "title": "Search",
"search_bar": { "search_bar": {
@ -534,6 +541,16 @@
"show_next": "Show Next", "show_next": "Show Next",
"show_previous": "Show Previous" "show_previous": "Show Previous"
} }
},
"account_list": {
"tab_bar_hint": "Current selected profile: %s. Double tap then hold to show account switcher",
"dismiss_account_switcher": "Dismiss Account Switcher",
"add_account": "Lägg till konto"
},
"wizard": {
"new_in_mastodon": "New in Mastodon",
"multiple_account_switch_intro_description": "Switch between multiple accounts by holding the profile button.",
"accessibility_hint": "Double tap to dismiss this wizard"
} }
} }
} }

View File

@ -2,6 +2,20 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>a11y.plural.count.unread.notification</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@notification_count_unread_notification@</string>
<key>notification_count_unread_notification</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>other</key>
<string>%ld การแจ้งเตือนที่ยังไม่ได้อ่าน</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_exceeds</key> <key>a11y.plural.count.input_limit_exceeds</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>

View File

@ -67,6 +67,7 @@
"done": "เสร็จสิ้น", "done": "เสร็จสิ้น",
"confirm": "ยืนยัน", "confirm": "ยืนยัน",
"continue": "ดำเนินการต่อ", "continue": "ดำเนินการต่อ",
"compose": "เขียน",
"cancel": "ยกเลิก", "cancel": "ยกเลิก",
"discard": "ละทิ้ง", "discard": "ละทิ้ง",
"try_again": "ลองอีกครั้ง", "try_again": "ลองอีกครั้ง",
@ -179,10 +180,10 @@
}, },
"header": { "header": {
"no_status_found": "ไม่พบโพสต์", "no_status_found": "ไม่พบโพสต์",
"blocking_warning": "You cant view this user's profile\nuntil you unblock them.\nYour profile looks like this to them.", "blocking_warning": "คุณไม่สามารถดูโปรไฟล์ของผู้ใช้นี้\nจนกว่าคุณจะเลิกปิดกั้นผู้ใช้นี้\nผู้ใช้นี้เห็นโปรไฟล์ของคุณเหมือนกับที่คุณเห็น",
"user_blocking_warning": "You cant view %ss profile\nuntil you unblock them.\nYour profile looks like this to them.", "user_blocking_warning": "คุณไม่สามารถดูโปรไฟล์ของ %s\nจนกว่าคุณจะเลิกปิดกั้นผู้ใช้นี้\nผู้ใช้นี้เห็นโปรไฟล์ของคุณเหมือนกับที่คุณเห็น",
"blocked_warning": "You cant view this users profile\nuntil they unblock you.", "blocked_warning": "คุณไม่สามารถดูโปรไฟล์ของผู้ใช้นี้\nจนกว่าผู้ใช้นี้จะเลิกปิดกั้นคุณ",
"user_blocked_warning": "You cant view %ss profile\nuntil they unblock you.", "user_blocked_warning": "คุณไม่สามารถดูโปรไฟล์ของ %s\nจนกว่าผู้ใช้นี้จะเลิกปิดกั้นคุณ",
"suspended_warning": "ผู้ใช้นี้ถูกระงับการใช้งาน", "suspended_warning": "ผู้ใช้นี้ถูกระงับการใช้งาน",
"user_suspended_warning": "บัญชีของ %s ถูกระงับการใช้งาน" "user_suspended_warning": "บัญชีของ %s ถูกระงับการใช้งาน"
} }
@ -210,7 +211,7 @@
"regional": "ภูมิภาค", "regional": "ภูมิภาค",
"art": "ศิลปะ", "art": "ศิลปะ",
"music": "ดนตรี", "music": "ดนตรี",
"tech": "tech" "tech": "เทคโนโลยี"
}, },
"see_less": "ดูน้อยลง", "see_less": "ดูน้อยลง",
"see_more": "ดูเพิ่มเติม" "see_more": "ดูเพิ่มเติม"
@ -285,7 +286,7 @@
"server_rules": { "server_rules": {
"title": "กฎพื้นฐานบางประการ", "title": "กฎพื้นฐานบางประการ",
"subtitle": "กฎเหล่านี้ถูกตั้งโดยผู้ดูแลของ %s", "subtitle": "กฎเหล่านี้ถูกตั้งโดยผู้ดูแลของ %s",
"prompt": "By continuing, youre subject to the terms of service and privacy policy for %s.", "prompt": "เมื่อคุณดำเนินการต่อ คุณอยู่ภายใต้เงื่อนไขการให้บริการและนโยบายความเป็นส่วนตัวสำหรับ %s",
"terms_of_service": "เงื่อนไขการให้บริการ", "terms_of_service": "เงื่อนไขการให้บริการ",
"privacy_policy": "นโยบายความเป็นส่วนตัว", "privacy_policy": "นโยบายความเป็นส่วนตัว",
"button": { "button": {
@ -413,6 +414,12 @@
} }
} }
}, },
"follower": {
"footer": "ไม่ได้แสดงผู้ติดตามจากเซิร์ฟเวอร์อื่น ๆ"
},
"following": {
"footer": "ไม่ได้แสดงการติดตามจากเซิร์ฟเวอร์อื่น ๆ"
},
"search": { "search": {
"title": "ค้นหา", "title": "ค้นหา",
"search_bar": { "search_bar": {
@ -534,6 +541,16 @@
"show_next": "แสดงถัดไป", "show_next": "แสดงถัดไป",
"show_previous": "แสดงก่อนหน้า" "show_previous": "แสดงก่อนหน้า"
} }
},
"account_list": {
"tab_bar_hint": "โปรไฟล์ที่เลือกในปัจจุบัน: %s แตะสองครั้งแล้วกดค้างไว้เพื่อแสดงตัวสลับบัญชี",
"dismiss_account_switcher": "ปิดตัวสลับบัญชี",
"add_account": "เพิ่มบัญชี"
},
"wizard": {
"new_in_mastodon": "มาใหม่ใน Mastodon",
"multiple_account_switch_intro_description": "สลับระหว่างหลายบัญชีโดยกดปุ่มโปรไฟล์ค้างไว้",
"accessibility_hint": "แตะสองครั้งเพื่อปิดตัวช่วยสร้างนี้"
} }
} }
} }

View File

@ -2,6 +2,20 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>a11y.plural.count.unread.notification</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@notification_count_unread_notification@</string>
<key>notification_count_unread_notification</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>other</key>
<string>%ld 条未读通知</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_exceeds</key> <key>a11y.plural.count.input_limit_exceeds</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>

View File

@ -67,6 +67,7 @@
"done": "完成", "done": "完成",
"confirm": "确认", "confirm": "确认",
"continue": "继续", "continue": "继续",
"compose": "撰写",
"cancel": "取消", "cancel": "取消",
"discard": "放弃", "discard": "放弃",
"try_again": "再试一次", "try_again": "再试一次",
@ -413,6 +414,12 @@
} }
} }
}, },
"follower": {
"footer": "不会显示来自其它服务器的关注者"
},
"following": {
"footer": "不会显示来自其它服务器的关注"
},
"search": { "search": {
"title": "搜索", "title": "搜索",
"search_bar": { "search_bar": {
@ -534,6 +541,16 @@
"show_next": "显示下一个", "show_next": "显示下一个",
"show_previous": "显示前一个" "show_previous": "显示前一个"
} }
},
"account_list": {
"tab_bar_hint": "当前账户:%s。 双击并按住来打开账户切换页面",
"dismiss_account_switcher": "关闭账户切换页面",
"add_account": "添加账户"
},
"wizard": {
"new_in_mastodon": "新功能",
"multiple_account_switch_intro_description": "按住个人资料标签按钮,即可在多个账户之间进行切换。",
"accessibility_hint": "双击关闭此向导"
} }
} }
} }

View File

@ -2,6 +2,20 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>a11y.plural.count.unread.notification</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
<string>%#@notification_count_unread_notification@</string>
<key>notification_count_unread_notification</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>other</key>
<string>%ld unread notification</string>
</dict>
</dict>
<key>a11y.plural.count.input_limit_exceeds</key> <key>a11y.plural.count.input_limit_exceeds</key>
<dict> <dict>
<key>NSStringLocalizedFormatKey</key> <key>NSStringLocalizedFormatKey</key>

View File

@ -67,6 +67,7 @@
"done": "Done", "done": "Done",
"confirm": "Confirm", "confirm": "Confirm",
"continue": "Continue", "continue": "Continue",
"compose": "Compose",
"cancel": "Cancel", "cancel": "Cancel",
"discard": "Discard", "discard": "Discard",
"try_again": "Try Again", "try_again": "Try Again",
@ -413,6 +414,12 @@
} }
} }
}, },
"follower": {
"footer": "Followers from other servers are not displayed."
},
"following": {
"footer": "Follows from other servers are not displayed."
},
"search": { "search": {
"title": "Search", "title": "Search",
"search_bar": { "search_bar": {
@ -534,6 +541,16 @@
"show_next": "Show Next", "show_next": "Show Next",
"show_previous": "Show Previous" "show_previous": "Show Previous"
} }
},
"account_list": {
"tab_bar_hint": "Current selected profile: %s. Double tap then hold to show account switcher",
"dismiss_account_switcher": "Dismiss Account Switcher",
"add_account": "Add Account"
},
"wizard": {
"new_in_mastodon": "New in Mastodon",
"multiple_account_switch_intro_description": "Switch between multiple accounts by holding the profile button.",
"accessibility_hint": "Double tap to dismiss this wizard"
} }
} }
} }

View File

@ -67,6 +67,7 @@
"done": "Done", "done": "Done",
"confirm": "Confirm", "confirm": "Confirm",
"continue": "Continue", "continue": "Continue",
"compose": "Compose",
"cancel": "Cancel", "cancel": "Cancel",
"discard": "Discard", "discard": "Discard",
"try_again": "Try Again", "try_again": "Try Again",
@ -81,6 +82,7 @@
"share_user": "Share %s", "share_user": "Share %s",
"share_post": "Share Post", "share_post": "Share Post",
"open_in_safari": "Open in Safari", "open_in_safari": "Open in Safari",
"open_in_browser": "Open in Browser",
"find_people": "Find people to follow", "find_people": "Find people to follow",
"manually_search": "Manually search instead", "manually_search": "Manually search instead",
"skip": "Skip", "skip": "Skip",
@ -413,6 +415,12 @@
} }
} }
}, },
"follower": {
"footer": "Followers from other servers are not displayed."
},
"following": {
"footer": "Follows from other servers are not displayed."
},
"search": { "search": {
"title": "Search", "title": "Search",
"search_bar": { "search_bar": {
@ -534,6 +542,16 @@
"show_next": "Show Next", "show_next": "Show Next",
"show_previous": "Show Previous" "show_previous": "Show Previous"
} }
},
"account_list": {
"tab_bar_hint": "Current selected profile: %s. Double tap then hold to show account switcher",
"dismiss_account_switcher": "Dismiss Account Switcher",
"add_account": "Add Account"
},
"wizard": {
"new_in_mastodon": "New in Mastodon",
"multiple_account_switch_intro_description": "Switch between multiple accounts by holding the profile button.",
"accessibility_hint": "Double tap to dismiss this wizard"
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -7,87 +7,92 @@
<key>AppShared.xcscheme_^#shared#^_</key> <key>AppShared.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>60</integer> <integer>44</integer>
</dict> </dict>
<key>CoreDataStack.xcscheme_^#shared#^_</key> <key>CoreDataStack.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>62</integer> <integer>45</integer>
</dict> </dict>
<key>Mastodon - ASDK.xcscheme_^#shared#^_</key> <key>Mastodon - ASDK.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>11</integer> <integer>4</integer>
</dict> </dict>
<key>Mastodon - RTL.xcscheme_^#shared#^_</key> <key>Mastodon - RTL.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>12</integer> <integer>17</integer>
</dict> </dict>
<key>Mastodon - Release.xcscheme_^#shared#^_</key> <key>Mastodon - Release.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>10</integer> <integer>3</integer>
</dict> </dict>
<key>Mastodon - ar.xcscheme_^#shared#^_</key> <key>Mastodon - ar.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>7</integer> <integer>11</integer>
</dict> </dict>
<key>Mastodon - ca.xcscheme_^#shared#^_</key> <key>Mastodon - ca.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>32</integer> <integer>23</integer>
</dict> </dict>
<key>Mastodon - de.xcscheme_^#shared#^_</key> <key>Mastodon - de.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>8</integer> <integer>13</integer>
</dict> </dict>
<key>Mastodon - en.xcscheme_^#shared#^_</key> <key>Mastodon - double length.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>1</integer> <integer>1</integer>
</dict> </dict>
<key>Mastodon - es-419.xcscheme_^#shared#^_</key> <key>Mastodon - en.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>5</integer>
</dict>
<key>Mastodon - es.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>4</integer>
</dict>
<key>Mastodon - fr.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>6</integer>
</dict>
<key>Mastodon - jp.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>27</integer>
</dict>
<key>Mastodon - nl.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>9</integer>
</dict>
<key>Mastodon - ru.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>2</integer> <integer>2</integer>
</dict> </dict>
<key>Mastodon - es-419.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>9</integer>
</dict>
<key>Mastodon - es.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>8</integer>
</dict>
<key>Mastodon - fr.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>10</integer>
</dict>
<key>Mastodon - jp.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>19</integer>
</dict>
<key>Mastodon - nl.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>15</integer>
</dict>
<key>Mastodon - ru.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>5</integer>
</dict>
<key>Mastodon - th.xcscheme_^#shared#^_</key> <key>Mastodon - th.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>3</integer> <integer>6</integer>
</dict> </dict>
<key>Mastodon - zh_Hans.xcscheme_^#shared#^_</key> <key>Mastodon - zh_Hans.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>30</integer> <integer>21</integer>
</dict> </dict>
<key>Mastodon.xcscheme_^#shared#^_</key> <key>Mastodon.xcscheme_^#shared#^_</key>
<dict> <dict>
@ -97,7 +102,7 @@
<key>MastodonIntent.xcscheme_^#shared#^_</key> <key>MastodonIntent.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>56</integer> <integer>43</integer>
</dict> </dict>
<key>MastodonIntents.xcscheme_^#shared#^_</key> <key>MastodonIntents.xcscheme_^#shared#^_</key>
<dict> <dict>
@ -112,12 +117,12 @@
<key>NotificationService.xcscheme_^#shared#^_</key> <key>NotificationService.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>13</integer> <integer>7</integer>
</dict> </dict>
<key>ShareActionExtension.xcscheme_^#shared#^_</key> <key>ShareActionExtension.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>58</integer> <integer>42</integer>
</dict> </dict>
</dict> </dict>
<key>SuppressBuildableAutocreation</key> <key>SuppressBuildableAutocreation</key>

View File

@ -6,8 +6,8 @@
"repositoryURL": "https://github.com/Alamofire/Alamofire.git", "repositoryURL": "https://github.com/Alamofire/Alamofire.git",
"state": { "state": {
"branch": null, "branch": null,
"revision": "f96b619bcb2383b43d898402283924b80e2c4bae", "revision": "d120af1e8638c7da36c8481fd61a66c0c08dc4fc",
"version": "5.4.3" "version": "5.4.4"
} }
}, },
{ {
@ -69,8 +69,8 @@
"repositoryURL": "https://github.com/MainasuK/FPSIndicator.git", "repositoryURL": "https://github.com/MainasuK/FPSIndicator.git",
"state": { "state": {
"branch": null, "branch": null,
"revision": "b2a002d689c400485f2ba41f9e71e15f7b99764a", "revision": "e4a5067ccd5293b024c767f09e51056afd4a4796",
"version": "1.0.1" "version": "1.1.0"
} }
}, },
{ {
@ -96,8 +96,8 @@
"repositoryURL": "https://github.com/TwidereProject/MetaTextKit.git", "repositoryURL": "https://github.com/TwidereProject/MetaTextKit.git",
"state": { "state": {
"branch": null, "branch": null,
"revision": "a5f412b72fc08cd1348e2388fc7ec326365e1823", "revision": "7af4182f64329440a4656f2cba307cb5848e496a",
"version": "2.1.1" "version": "2.1.2"
} }
}, },
{ {
@ -105,8 +105,8 @@
"repositoryURL": "https://github.com/kean/Nuke.git", "repositoryURL": "https://github.com/kean/Nuke.git",
"state": { "state": {
"branch": null, "branch": null,
"revision": "3bd3a1765bdf62d561d4c2e10e1c4fc7a010f44e", "revision": "0db18dd34998cca18e9a28bcee136f84518007a0",
"version": "10.3.2" "version": "10.4.1"
} }
}, },
{ {
@ -127,13 +127,22 @@
"version": "3.6.2" "version": "3.6.2"
} }
}, },
{
"package": "PanModal",
"repositoryURL": "https://github.com/slackhq/PanModal.git",
"state": {
"branch": null,
"revision": "b012aecb6b67a8e46369227f893c12544846613f",
"version": "1.2.7"
}
},
{ {
"package": "SDWebImage", "package": "SDWebImage",
"repositoryURL": "https://github.com/SDWebImage/SDWebImage.git", "repositoryURL": "https://github.com/SDWebImage/SDWebImage.git",
"state": { "state": {
"branch": null, "branch": null,
"revision": "76dd4b49110b8624317fc128e7fa0d8a252018bc", "revision": "a72df4849408da7e5d3c1b586797b7c601c41d1b",
"version": "5.11.1" "version": "5.12.1"
} }
}, },
{ {
@ -141,8 +150,8 @@
"repositoryURL": "https://github.com/apple/swift-collections.git", "repositoryURL": "https://github.com/apple/swift-collections.git",
"state": { "state": {
"branch": null, "branch": null,
"revision": "0959ba76a1d4a98fd11163aa83fd49c25b93bfae", "revision": "9d8719c8bebdc79740b6969c912ac706eb721d7a",
"version": "0.0.5" "version": "0.0.7"
} }
}, },
{ {
@ -150,8 +159,8 @@
"repositoryURL": "https://github.com/apple/swift-nio.git", "repositoryURL": "https://github.com/apple/swift-nio.git",
"state": { "state": {
"branch": null, "branch": null,
"revision": "8da5c5a4e6c5084c296b9f39dc54f00be146e0fa", "revision": "546610d52b19be3e19935e0880bb06b9c03f5cef",
"version": "1.14.2" "version": "1.14.4"
} }
}, },
{ {
@ -207,15 +216,6 @@
"revision": "dad97167bf1be16aeecd109130900995dd01c515", "revision": "dad97167bf1be16aeecd109130900995dd01c515",
"version": "2.6.0" "version": "2.6.0"
} }
},
{
"package": "UITextView+Placeholder",
"repositoryURL": "https://github.com/MainasuK/UITextView-Placeholder",
"state": {
"branch": null,
"revision": "20f513ded04a040cdf5467f0891849b1763ede3b",
"version": "1.4.1"
}
} }
] ]
}, },

View File

@ -5,24 +5,132 @@
// Created by Cirno MainasuK on 2021-1-27. // Created by Cirno MainasuK on 2021-1-27.
import UIKit import UIKit
import Combine
import SafariServices import SafariServices
import CoreDataStack import CoreDataStack
import MastodonSDK
import PanModal
final public class SceneCoordinator { final public class SceneCoordinator {
private var disposeBag = Set<AnyCancellable>()
private weak var scene: UIScene! private weak var scene: UIScene!
private weak var sceneDelegate: SceneDelegate! private weak var sceneDelegate: SceneDelegate!
private weak var appContext: AppContext! private weak var appContext: AppContext!
private(set) weak var tabBarController: MainTabBarController!
let id = UUID().uuidString let id = UUID().uuidString
private(set) weak var tabBarController: MainTabBarController!
private(set) weak var splitViewController: RootSplitViewController?
private(set) var wizardViewController: WizardViewController?
private(set) var secondaryStackHashValues = Set<Int>()
init(scene: UIScene, sceneDelegate: SceneDelegate, appContext: AppContext) { init(scene: UIScene, sceneDelegate: SceneDelegate, appContext: AppContext) {
self.scene = scene self.scene = scene
self.sceneDelegate = sceneDelegate self.sceneDelegate = sceneDelegate
self.appContext = appContext self.appContext = appContext
scene.session.sceneCoordinator = self scene.session.sceneCoordinator = self
appContext.notificationService.requestRevealNotificationPublisher
.receive(on: DispatchQueue.main)
.compactMap { [weak self] pushNotification -> AnyPublisher<MastodonPushNotification?, Never> in
guard let self = self else { return Just(nil).eraseToAnyPublisher() }
// skip if no available account
guard let currentActiveAuthenticationBox = appContext.authenticationService.activeMastodonAuthenticationBox.value else {
return Just(nil).eraseToAnyPublisher()
}
let accessToken = pushNotification._accessToken // use raw accessToken value without normalize
if currentActiveAuthenticationBox.userAuthorization.accessToken == accessToken {
// do nothing if notification for current account
return Just(pushNotification).eraseToAnyPublisher()
} else {
// switch to notification's account
let request = MastodonAuthentication.sortedFetchRequest
request.predicate = MastodonAuthentication.predicate(userAccessToken: accessToken)
request.returnsObjectsAsFaults = false
request.fetchLimit = 1
do {
guard let authentication = try appContext.managedObjectContext.fetch(request).first else {
return Just(nil).eraseToAnyPublisher()
}
let domain = authentication.domain
let userID = authentication.userID
return appContext.authenticationService.activeMastodonUser(domain: domain, userID: userID)
.receive(on: DispatchQueue.main)
.map { [weak self] result -> MastodonPushNotification? in
guard let self = self else { return nil }
switch result {
case .success:
// reset view hierarchy
self.setup()
return pushNotification
case .failure:
return nil
}
}
.delay(for: 1, scheduler: DispatchQueue.main) // set delay to slow transition (not must)
.eraseToAnyPublisher()
} catch {
assertionFailure(error.localizedDescription)
return Just(nil).eraseToAnyPublisher()
}
}
}
.switchToLatest()
.receive(on: DispatchQueue.main)
.sink { [weak self] pushNotification in
guard let self = self else { return }
guard let pushNotification = pushNotification else { return }
// redirect to notification tab
self.switchToTabBar(tab: .notification)
// Delay in next run loop
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
// Note:
// show (push) on phone and pad
let from: UIViewController? = {
if let splitViewController = self.splitViewController {
if splitViewController.compactMainTabBarViewController.topMost?.view.window != nil {
// compact
return splitViewController.compactMainTabBarViewController.topMost
} else {
// expand
return splitViewController.contentSplitViewController.mainTabBarController.topMost
}
} else {
return self.tabBarController.topMost
}
}()
// show notification related content
guard let type = Mastodon.Entity.Notification.NotificationType(rawValue: pushNotification.notificationType) else { return }
let notificationID = String(pushNotification.notificationID)
switch type {
case .follow:
let profileViewModel = RemoteProfileViewModel(context: appContext, notificationID: notificationID)
self.present(scene: .profile(viewModel: profileViewModel), from: from, transition: .show)
case .followRequest:
// do nothing
break
case .mention, .reblog, .favourite, .poll, .status:
let threadViewModel = RemoteThreadViewModel(context: appContext, notificationID: notificationID)
self.present(scene: .thread(viewModel: threadViewModel), from: from, transition: .show)
case ._other:
assertionFailure()
break
}
} // end DispatchQueue.main.async
}
.store(in: &disposeBag)
} }
} }
@ -31,6 +139,8 @@ extension SceneCoordinator {
case show // push case show // push
case showDetail // replace case showDetail // replace
case modal(animated: Bool, completion: (() -> Void)? = nil) case modal(animated: Bool, completion: (() -> Void)? = nil)
case popover(sourceView: UIView)
case panModal
case custom(transitioningDelegate: UIViewControllerTransitioningDelegate) case custom(transitioningDelegate: UIViewControllerTransitioningDelegate)
case customPush case customPush
case safariPresent(animated: Bool, completion: (() -> Void)? = nil) case safariPresent(animated: Bool, completion: (() -> Void)? = nil)
@ -66,9 +176,12 @@ extension SceneCoordinator {
case hashtagTimeline(viewModel: HashtagTimelineViewModel) case hashtagTimeline(viewModel: HashtagTimelineViewModel)
// profile // profile
case accountList
case profile(viewModel: ProfileViewModel) case profile(viewModel: ProfileViewModel)
case favorite(viewModel: FavoriteViewModel) case favorite(viewModel: FavoriteViewModel)
case follower(viewModel: FollowerListViewModel)
case following(viewModel: FollowingListViewModel)
// setting // setting
case settings(viewModel: SettingsViewModel) case settings(viewModel: SettingsViewModel)
@ -109,9 +222,34 @@ extension SceneCoordinator {
extension SceneCoordinator { extension SceneCoordinator {
func setup() { func setup() {
let viewController = MainTabBarController(context: appContext, coordinator: self) let rootViewController: UIViewController
sceneDelegate.window?.rootViewController = viewController switch UIDevice.current.userInterfaceIdiom {
tabBarController = viewController case .phone:
let viewController = MainTabBarController(context: appContext, coordinator: self)
self.splitViewController = nil
self.tabBarController = viewController
rootViewController = viewController
default:
let splitViewController = RootSplitViewController(context: appContext, coordinator: self)
self.splitViewController = splitViewController
self.tabBarController = splitViewController.contentSplitViewController.mainTabBarController
rootViewController = splitViewController
}
let wizardViewController = WizardViewController()
if !wizardViewController.items.isEmpty,
let delegate = rootViewController as? WizardViewControllerDelegate
{
// do not add as child view controller.
// otherwise, the tab bar controller will add as a new tab
wizardViewController.delegate = delegate
wizardViewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
wizardViewController.view.frame = rootViewController.view.bounds
rootViewController.view.addSubview(wizardViewController.view)
self.wizardViewController = wizardViewController
}
sceneDelegate.window?.rootViewController = rootViewController
} }
func setupOnboardingIfNeeds(animated: Bool) { func setupOnboardingIfNeeds(animated: Bool) {
@ -165,8 +303,8 @@ extension SceneCoordinator {
switch transition { switch transition {
case .show: case .show:
presentingViewController.show(viewController, sender: sender) presentingViewController.show(viewController, sender: sender)
case .showDetail: case .showDetail:
secondaryStackHashValues.insert(viewController.hashValue)
let navigationController = AdaptiveStatusBarStyleNavigationController(rootViewController: viewController) let navigationController = AdaptiveStatusBarStyleNavigationController(rootViewController: viewController)
presentingViewController.showDetailViewController(navigationController, sender: sender) presentingViewController.showDetailViewController(navigationController, sender: sender)
@ -183,11 +321,27 @@ extension SceneCoordinator {
modalNavigationController.presentationController?.delegate = adaptivePresentationControllerDelegate modalNavigationController.presentationController?.delegate = adaptivePresentationControllerDelegate
} }
presentingViewController.present(modalNavigationController, animated: animated, completion: completion) presentingViewController.present(modalNavigationController, animated: animated, completion: completion)
case .panModal:
guard let panModalPresentable = viewController as? PanModalPresentable & UIViewController else {
assertionFailure()
return nil
}
// https://github.com/slackhq/PanModal/issues/74#issuecomment-572426441
panModalPresentable.modalPresentationStyle = .custom
panModalPresentable.modalPresentationCapturesStatusBarAppearance = true
panModalPresentable.transitioningDelegate = PanModalPresentationDelegate.default
presentingViewController.present(panModalPresentable, animated: true, completion: nil)
//presentingViewController.presentPanModal(panModalPresentable)
case .popover(let sourceView):
viewController.modalPresentationStyle = .popover
viewController.popoverPresentationController?.sourceView = sourceView
(splitViewController ?? presentingViewController)?.present(viewController, animated: true, completion: nil)
case .custom(let transitioningDelegate): case .custom(let transitioningDelegate):
viewController.modalPresentationStyle = .custom viewController.modalPresentationStyle = .custom
viewController.transitioningDelegate = transitioningDelegate viewController.transitioningDelegate = transitioningDelegate
sender?.present(viewController, animated: true, completion: nil) (splitViewController ?? presentingViewController)?.present(viewController, animated: true, completion: nil)
case .customPush: case .customPush:
// set delegate in view controller // set delegate in view controller
@ -215,7 +369,13 @@ extension SceneCoordinator {
} }
func switchToTabBar(tab: MainTabBarController.Tab) { func switchToTabBar(tab: MainTabBarController.Tab) {
splitViewController?.contentSplitViewController.currentSupplementaryTab = tab
splitViewController?.compactMainTabBarViewController.selectedIndex = tab.rawValue
splitViewController?.compactMainTabBarViewController.currentTab.value = tab
tabBarController.selectedIndex = tab.rawValue tabBarController.selectedIndex = tab.rawValue
tabBarController.currentTab.value = tab
} }
} }
@ -273,6 +433,9 @@ private extension SceneCoordinator {
let _viewController = HashtagTimelineViewController() let _viewController = HashtagTimelineViewController()
_viewController.viewModel = viewModel _viewController.viewModel = viewModel
viewController = _viewController viewController = _viewController
case .accountList:
let _viewController = AccountListViewController()
viewController = _viewController
case .profile(let viewModel): case .profile(let viewModel):
let _viewController = ProfileViewController() let _viewController = ProfileViewController()
_viewController.viewModel = viewModel _viewController.viewModel = viewModel
@ -281,6 +444,14 @@ private extension SceneCoordinator {
let _viewController = FavoriteViewController() let _viewController = FavoriteViewController()
_viewController.viewModel = viewModel _viewController.viewModel = viewModel
viewController = _viewController viewController = _viewController
case .follower(let viewModel):
let _viewController = FollowerListViewController()
_viewController.viewModel = viewModel
viewController = _viewController
case .following(let viewModel):
let _viewController = FollowingListViewController()
_viewController.viewModel = viewModel
viewController = _viewController
case .suggestionAccount(let viewModel): case .suggestionAccount(let viewModel):
let _viewController = SuggestionAccountViewController() let _viewController = SuggestionAccountViewController()
_viewController.viewModel = viewModel _viewController.viewModel = viewModel

View File

@ -32,7 +32,7 @@ open class TableNodeDiffableDataSource<SectionIdentifierType: Hashable, ItemIden
self.cellProvider = cellProvider self.cellProvider = cellProvider
super.init() super.init()
tableNode.dataSource = self tableNode.delegate = self
} }
/// Applies given snapshot to perform automatic diffing update. /// Applies given snapshot to perform automatic diffing update.

View File

@ -10,7 +10,7 @@ import Foundation
enum NotificationItem { enum NotificationItem {
case notification(objectID: NSManagedObjectID, attribute: Item.StatusAttribute) case notification(objectID: NSManagedObjectID, attribute: Item.StatusAttribute)
case notificationStatus(objectID: NSManagedObjectID, attribute: Item.StatusAttribute) // display notification status without card wrapper
case bottomLoader case bottomLoader
} }
@ -19,6 +19,8 @@ extension NotificationItem: Equatable {
switch (lhs, rhs) { switch (lhs, rhs) {
case (.notification(let idLeft, _), .notification(let idRight, _)): case (.notification(let idLeft, _), .notification(let idRight, _)):
return idLeft == idRight return idLeft == idRight
case (.notificationStatus(let idLeft, _), .notificationStatus(let idRight, _)):
return idLeft == idRight
case (.bottomLoader, .bottomLoader): case (.bottomLoader, .bottomLoader):
return true return true
default: default:
@ -32,6 +34,8 @@ extension NotificationItem: Hashable {
switch self { switch self {
case .notification(let id, _): case .notification(let id, _):
hasher.combine(id) hasher.combine(id)
case .notificationStatus(let id, _):
hasher.combine(id)
case .bottomLoader: case .bottomLoader:
hasher.combine(String(describing: NotificationItem.bottomLoader.self)) hasher.combine(String(describing: NotificationItem.bottomLoader.self))
} }
@ -43,6 +47,8 @@ extension NotificationItem {
switch self { switch self {
case .notification(let objectID, _): case .notification(let objectID, _):
return .mastodonNotification(objectID: objectID) return .mastodonNotification(objectID: objectID)
case .notificationStatus(let objectID, _):
return .mastodonNotification(objectID: objectID)
case .bottomLoader: case .bottomLoader:
return nil return nil
} }

View File

@ -0,0 +1,16 @@
//
// UserItem.swift
// Mastodon
//
// Created by Cirno MainasuK on 2021-11-1.
//
import Foundation
import CoreData
enum UserItem: Hashable {
case follower(objectID: NSManagedObjectID)
case following(objectID: NSManagedObjectID)
case bottomLoader
case bottomHeader(text: String)
}

View File

@ -32,24 +32,8 @@ extension SearchHistorySection {
} }
return cell return cell
case .status: case .status:
// Should not show status in the history list
return UITableViewCell() return UITableViewCell()
// let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: StatusTableViewCell.self), for: indexPath) as! StatusTableViewCell
// if let status = try? dependency.context.managedObjectContext.existingObject(with: statusObjectID) as? Status {
// let activeMastodonAuthenticationBox = dependency.context.authenticationService.activeMastodonAuthenticationBox.value
// let requestUserID = activeMastodonAuthenticationBox?.userID ?? ""
// StatusSection.configure(
// cell: cell,
// tableView: tableView,
// timelineContext: .search,
// dependency: dependency,
// readableLayoutFrame: tableView.readableContentGuide.layoutFrame,
// status: status,
// requestUserID: requestUserID,
// statusItemAttribute: attribute
// )
// }
// cell.delegate = statusTableViewCellDelegate
// return cell
} // end switch } // end switch
} // end UITableViewDiffableDataSource } // end UITableViewDiffableDataSource
} // end func } // end func

View File

@ -41,21 +41,17 @@ extension SettingsSection {
switch item { switch item {
case .appearance(let objectID): case .appearance(let objectID):
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: SettingsAppearanceTableViewCell.self), for: indexPath) as! SettingsAppearanceTableViewCell let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: SettingsAppearanceTableViewCell.self), for: indexPath) as! SettingsAppearanceTableViewCell
managedObjectContext.performAndWait { UserDefaults.shared.observe(\.customUserInterfaceStyle, options: [.initial, .new]) { [weak cell] defaults, _ in
let setting = managedObjectContext.object(with: objectID) as! Setting guard let cell = cell else { return }
cell.update(with: setting.appearance) switch defaults.customUserInterfaceStyle {
ManagedObjectObserver.observe(object: setting) case .unspecified: cell.update(with: .automatic)
.receive(on: DispatchQueue.main) case .dark: cell.update(with: .dark)
.sink(receiveCompletion: { _ in case .light: cell.update(with: .light)
// do nothing @unknown default:
}, receiveValue: { [weak cell] change in assertionFailure()
guard let cell = cell else { return } }
guard case .update(let object) = change.changeType,
let setting = object as? Setting else { return }
cell.update(with: setting.appearance)
})
.store(in: &cell.disposeBag)
} }
.store(in: &cell.observations)
cell.delegate = settingsAppearanceTableViewCellDelegate cell.delegate = settingsAppearanceTableViewCellDelegate
return cell return cell
case .notification(let objectID, let switchMode): case .notification(let objectID, let switchMode):

View File

@ -21,9 +21,10 @@ enum NotificationSection: Equatable, Hashable {
extension NotificationSection { extension NotificationSection {
static func tableViewDiffableDataSource( static func tableViewDiffableDataSource(
for tableView: UITableView, for tableView: UITableView,
dependency: NeedsDependency,
managedObjectContext: NSManagedObjectContext, managedObjectContext: NSManagedObjectContext,
delegate: NotificationTableViewCellDelegate, delegate: NotificationTableViewCellDelegate,
dependency: NeedsDependency statusTableViewCellDelegate: StatusTableViewCellDelegate
) -> UITableViewDiffableDataSource<NotificationSection, NotificationItem> { ) -> UITableViewDiffableDataSource<NotificationSection, NotificationItem> {
UITableViewDiffableDataSource(tableView: tableView) { UITableViewDiffableDataSource(tableView: tableView) {
[weak delegate, weak dependency] [weak delegate, weak dependency]
@ -32,137 +33,47 @@ extension NotificationSection {
switch notificationItem { switch notificationItem {
case .notification(let objectID, let attribute): case .notification(let objectID, let attribute):
guard let notification = try? managedObjectContext.existingObject(with: objectID) as? MastodonNotification, guard let notification = try? managedObjectContext.existingObject(with: objectID) as? MastodonNotification,
!notification.isDeleted else { !notification.isDeleted
return UITableViewCell() else { return UITableViewCell() }
}
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: NotificationStatusTableViewCell.self), for: indexPath) as! NotificationStatusTableViewCell let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: NotificationStatusTableViewCell.self), for: indexPath) as! NotificationStatusTableViewCell
cell.delegate = delegate configure(
tableView: tableView,
// configure author cell: cell,
cell.configure( notification: notification,
with: AvatarConfigurableViewConfiguration( dependency: dependency,
avatarImageURL: notification.account.avatarImageURL() attribute: attribute
)
) )
cell.delegate = delegate
cell.isAccessibilityElement = true
NotificationSection.configureStatusAccessibilityLabel(cell: cell)
return cell
func createActionImage() -> UIImage? { case .notificationStatus(objectID: let objectID, attribute: let attribute):
return UIImage( guard let notification = try? managedObjectContext.existingObject(with: objectID) as? MastodonNotification,
systemName: notification.notificationType.actionImageName, !notification.isDeleted,
withConfiguration: UIImage.SymbolConfiguration( let status = notification.status,
pointSize: 12, weight: .semibold let requestUserID = dependency.context.authenticationService.activeMastodonAuthenticationBox.value?.userID
) else { return UITableViewCell() }
)? let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: StatusTableViewCell.self), for: indexPath) as! StatusTableViewCell
.withTintColor(.systemBackground)
.af.imageAspectScaled(toFit: CGSize(width: 14, height: 14))
}
cell.avatarButton.badgeImageView.backgroundColor = notification.notificationType.color // configure cell
cell.avatarButton.badgeImageView.image = createActionImage() StatusSection.configureStatusTableViewCell(
cell.traitCollectionDidChange cell: cell,
.receive(on: DispatchQueue.main) tableView: tableView,
.sink { [weak cell] in timelineContext: .notifications,
guard let cell = cell else { return } dependency: dependency,
cell.avatarButton.badgeImageView.image = createActionImage() readableLayoutFrame: tableView.readableContentGuide.layoutFrame,
} status: status,
.store(in: &cell.disposeBag) requestUserID: requestUserID,
statusItemAttribute: attribute
// configure author name, notification description, timestamp )
let nameText = notification.account.displayNameWithFallback cell.statusView.headerContainerView.isHidden = true // set header hide
let titleLabelText: String = { cell.statusView.actionToolbarContainer.isHidden = true // set toolbar hide
switch notification.notificationType { cell.statusView.actionToolbarPlaceholderPaddingView.isHidden = false
case .favourite: return L10n.Scene.Notification.userFavoritedYourPost(nameText) cell.delegate = statusTableViewCellDelegate
case .follow: return L10n.Scene.Notification.userFollowedYou(nameText) cell.isAccessibilityElement = true
case .followRequest: return L10n.Scene.Notification.userRequestedToFollowYou(nameText) StatusSection.configureStatusAccessibilityLabel(cell: cell)
case .mention: return L10n.Scene.Notification.userMentionedYou(nameText)
case .poll: return L10n.Scene.Notification.userYourPollHasEnded(nameText)
case .reblog: return L10n.Scene.Notification.userRebloggedYourPost(nameText)
default: return ""
}
}()
do {
let nameContent = MastodonContent(content: nameText, emojis: notification.account.emojiMeta)
let nameMetaContent = try MastodonMetaContent.convert(document: nameContent)
let mastodonContent = MastodonContent(content: titleLabelText, emojis: notification.account.emojiMeta)
let metaContent = try MastodonMetaContent.convert(document: mastodonContent)
cell.titleLabel.configure(content: metaContent)
if let nameRange = metaContent.string.range(of: nameMetaContent.string) {
let nsRange = NSRange(nameRange, in: metaContent.string)
cell.titleLabel.textStorage.addAttributes([
.font: UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 15, weight: .semibold), maximumPointSize: 20),
.foregroundColor: Asset.Colors.brandBlue.color,
], range: nsRange)
}
} catch {
let metaContent = PlaintextMetaContent(string: titleLabelText)
cell.titleLabel.configure(content: metaContent)
}
let createAt = notification.createAt
cell.timestampLabel.text = createAt.localizedSlowedTimeAgoSinceNow
AppContext.shared.timestampUpdatePublisher
.receive(on: DispatchQueue.main)
.sink { [weak cell] _ in
guard let cell = cell else { return }
cell.timestampLabel.text = createAt.localizedSlowedTimeAgoSinceNow
}
.store(in: &cell.disposeBag)
// configure follow request (if exist)
if case .followRequest = notification.notificationType {
cell.acceptButton.publisher(for: .touchUpInside)
.sink { [weak cell] _ in
guard let cell = cell else { return }
cell.delegate?.notificationTableViewCell(cell, notification: notification, acceptButtonDidPressed: cell.acceptButton)
}
.store(in: &cell.disposeBag)
cell.rejectButton.publisher(for: .touchUpInside)
.sink { [weak cell] _ in
guard let cell = cell else { return }
cell.delegate?.notificationTableViewCell(cell, notification: notification, rejectButtonDidPressed: cell.rejectButton)
}
.store(in: &cell.disposeBag)
cell.buttonStackView.isHidden = false
} else {
cell.buttonStackView.isHidden = true
}
// configure status (if exist)
if let status = notification.status {
let frame = CGRect(
x: 0,
y: 0,
width: tableView.readableContentGuide.layoutFrame.width - NotificationStatusTableViewCell.statusPadding.left - NotificationStatusTableViewCell.statusPadding.right,
height: tableView.readableContentGuide.layoutFrame.height
)
StatusSection.configure(
cell: cell,
tableView: tableView,
timelineContext: .notifications,
dependency: dependency,
readableLayoutFrame: frame,
status: status,
requestUserID: notification.userID,
statusItemAttribute: attribute
)
cell.statusContainerView.isHidden = false
cell.containerStackView.alignment = .top
cell.containerStackViewBottomLayoutConstraint.constant = 0
} else {
if case .followRequest = notification.notificationType {
cell.containerStackView.alignment = .top
} else {
cell.containerStackView.alignment = .center
}
cell.statusContainerView.isHidden = true
cell.containerStackViewBottomLayoutConstraint.constant = 5 // 5pt margin when no status view
}
return cell return cell
case .bottomLoader: case .bottomLoader:
@ -174,3 +85,162 @@ extension NotificationSection {
} }
} }
extension NotificationSection {
static func configure(
tableView: UITableView,
cell: NotificationStatusTableViewCell,
notification: MastodonNotification,
dependency: NeedsDependency,
attribute: Item.StatusAttribute
) {
// configure author
cell.configure(
with: AvatarConfigurableViewConfiguration(
avatarImageURL: notification.account.avatarImageURL()
)
)
func createActionImage() -> UIImage? {
return UIImage(
systemName: notification.notificationType.actionImageName,
withConfiguration: UIImage.SymbolConfiguration(
pointSize: 12, weight: .semibold
)
)?
.withTintColor(.systemBackground)
.af.imageAspectScaled(toFit: CGSize(width: 14, height: 14))
}
cell.avatarButton.badgeImageView.backgroundColor = notification.notificationType.color
cell.avatarButton.badgeImageView.image = createActionImage()
cell.traitCollectionDidChange
.receive(on: DispatchQueue.main)
.sink { [weak cell] in
guard let cell = cell else { return }
cell.avatarButton.badgeImageView.image = createActionImage()
}
.store(in: &cell.disposeBag)
// configure author name, notification description, timestamp
let nameText = notification.account.displayNameWithFallback
let titleLabelText: String = {
switch notification.notificationType {
case .favourite: return L10n.Scene.Notification.userFavoritedYourPost(nameText)
case .follow: return L10n.Scene.Notification.userFollowedYou(nameText)
case .followRequest: return L10n.Scene.Notification.userRequestedToFollowYou(nameText)
case .mention: return L10n.Scene.Notification.userMentionedYou(nameText)
case .poll: return L10n.Scene.Notification.userYourPollHasEnded(nameText)
case .reblog: return L10n.Scene.Notification.userRebloggedYourPost(nameText)
default: return ""
}
}()
do {
let nameContent = MastodonContent(content: nameText, emojis: notification.account.emojiMeta)
let nameMetaContent = try MastodonMetaContent.convert(document: nameContent)
let mastodonContent = MastodonContent(content: titleLabelText, emojis: notification.account.emojiMeta)
let metaContent = try MastodonMetaContent.convert(document: mastodonContent)
cell.titleLabel.configure(content: metaContent)
if let nameRange = metaContent.string.range(of: nameMetaContent.string) {
let nsRange = NSRange(nameRange, in: metaContent.string)
cell.titleLabel.textStorage.addAttributes([
.font: UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 15, weight: .semibold), maximumPointSize: 20),
.foregroundColor: Asset.Colors.brandBlue.color,
], range: nsRange)
}
} catch {
let metaContent = PlaintextMetaContent(string: titleLabelText)
cell.titleLabel.configure(content: metaContent)
}
let createAt = notification.createAt
cell.timestampLabel.text = createAt.localizedSlowedTimeAgoSinceNow
AppContext.shared.timestampUpdatePublisher
.receive(on: DispatchQueue.main)
.sink { [weak cell] _ in
guard let cell = cell else { return }
cell.timestampLabel.text = createAt.localizedSlowedTimeAgoSinceNow
}
.store(in: &cell.disposeBag)
// configure follow request (if exist)
if case .followRequest = notification.notificationType {
cell.acceptButton.publisher(for: .touchUpInside)
.sink { [weak cell] _ in
guard let cell = cell else { return }
cell.delegate?.notificationTableViewCell(cell, notification: notification, acceptButtonDidPressed: cell.acceptButton)
}
.store(in: &cell.disposeBag)
cell.rejectButton.publisher(for: .touchUpInside)
.sink { [weak cell] _ in
guard let cell = cell else { return }
cell.delegate?.notificationTableViewCell(cell, notification: notification, rejectButtonDidPressed: cell.rejectButton)
}
.store(in: &cell.disposeBag)
cell.buttonStackView.isHidden = false
} else {
cell.buttonStackView.isHidden = true
}
// configure status (if exist)
if let status = notification.status {
let frame = CGRect(
x: 0,
y: 0,
width: tableView.readableContentGuide.layoutFrame.width - NotificationStatusTableViewCell.statusPadding.left - NotificationStatusTableViewCell.statusPadding.right,
height: tableView.readableContentGuide.layoutFrame.height
)
StatusSection.configure(
cell: cell,
tableView: tableView,
timelineContext: .notifications,
dependency: dependency,
readableLayoutFrame: frame,
status: status,
requestUserID: notification.userID,
statusItemAttribute: attribute
)
cell.statusContainerView.isHidden = false
cell.containerStackView.alignment = .top
cell.containerStackViewBottomLayoutConstraint.constant = 0
} else {
if case .followRequest = notification.notificationType {
cell.containerStackView.alignment = .top
} else {
cell.containerStackView.alignment = .center
}
cell.statusContainerView.isHidden = true
cell.containerStackViewBottomLayoutConstraint.constant = 5 // 5pt margin when no status view
}
}
static func configureStatusAccessibilityLabel(cell: NotificationStatusTableViewCell) {
// FIXME:
cell.accessibilityLabel = {
var accessibilityViews: [UIView?] = []
accessibilityViews.append(contentsOf: [
cell.titleLabel,
cell.timestampLabel,
cell.statusView
])
if !cell.statusContainerView.isHidden {
if !cell.statusView.headerContainerView.isHidden {
accessibilityViews.append(cell.statusView.headerInfoLabel)
}
accessibilityViews.append(contentsOf: [
cell.statusView.nameMetaLabel,
cell.statusView.dateLabel,
cell.statusView.contentMetaText.textView,
])
}
return accessibilityViews
.compactMap { $0?.accessibilityLabel }
.joined(separator: " ")
}()
}
}

View File

@ -37,6 +37,15 @@ extension PollSection {
managedObjectContext.performAndWait { managedObjectContext.performAndWait {
let option = managedObjectContext.object(with: objectID) as! PollOption let option = managedObjectContext.object(with: objectID) as! PollOption
PollSection.configure(cell: cell, pollOption: option, pollItemAttribute: attribute) PollSection.configure(cell: cell, pollOption: option, pollItemAttribute: attribute)
cell.isAccessibilityElement = true
cell.accessibilityLabel = {
var labels: [String] = [option.title]
if let percentage = cell.pollOptionView.optionPercentageLabel.text {
labels.append(percentage)
}
return labels.joined(separator: ",")
}()
} }
return cell return cell
} }

View File

@ -67,7 +67,6 @@ extension StatusSection {
timelineContext: TimelineContext, timelineContext: TimelineContext,
dependency: NeedsDependency, dependency: NeedsDependency,
managedObjectContext: NSManagedObjectContext, managedObjectContext: NSManagedObjectContext,
timestampUpdatePublisher: AnyPublisher<Date, Never>,
statusTableViewCellDelegate: StatusTableViewCellDelegate, statusTableViewCellDelegate: StatusTableViewCellDelegate,
timelineMiddleLoaderTableViewCellDelegate: TimelineMiddleLoaderTableViewCellDelegate?, timelineMiddleLoaderTableViewCellDelegate: TimelineMiddleLoaderTableViewCellDelegate?,
threadReplyLoaderTableViewCellDelegate: ThreadReplyLoaderTableViewCellDelegate? threadReplyLoaderTableViewCellDelegate: ThreadReplyLoaderTableViewCellDelegate?
@ -159,6 +158,11 @@ extension StatusSection {
accessibilityElements.append(cell.statusView.avatarView) accessibilityElements.append(cell.statusView.avatarView)
accessibilityElements.append(cell.statusView.nameMetaLabel) accessibilityElements.append(cell.statusView.nameMetaLabel)
accessibilityElements.append(cell.statusView.dateLabel) accessibilityElements.append(cell.statusView.dateLabel)
// poll
accessibilityElements.append(cell.statusView.pollTableView)
accessibilityElements.append(cell.statusView.pollVoteCountLabel)
accessibilityElements.append(cell.statusView.pollCountdownLabel)
accessibilityElements.append(cell.statusView.pollVoteButton)
// TODO: a11y // TODO: a11y
accessibilityElements.append(cell.statusView.contentMetaText.textView) accessibilityElements.append(cell.statusView.contentMetaText.textView)
accessibilityElements.append(contentsOf: cell.statusView.statusMosaicImageViewContainer.imageViews) accessibilityElements.append(contentsOf: cell.statusView.statusMosaicImageViewContainer.imageViews)
@ -363,7 +367,6 @@ extension StatusSection {
} }
}() }()
if status.author.id == requestUserID || status.reblog?.author.id == requestUserID { if status.author.id == requestUserID || status.reblog?.author.id == requestUserID {
// do not filter myself // do not filter myself
} else { } else {
@ -391,7 +394,7 @@ extension StatusSection {
// set timestamp // set timestamp
let createdAt = (status.reblog ?? status).createdAt let createdAt = (status.reblog ?? status).createdAt
cell.statusView.dateLabel.text = createdAt.localizedSlowedTimeAgoSinceNow cell.statusView.dateLabel.text = createdAt.localizedSlowedTimeAgoSinceNow
cell.statusView.dateLabel.accessibilityValue = createdAt.timeAgoSinceNow cell.statusView.dateLabel.accessibilityLabel = createdAt.timeAgoSinceNow
AppContext.shared.timestampUpdatePublisher AppContext.shared.timestampUpdatePublisher
.receive(on: RunLoop.main) // will be paused when scrolling (on purpose) .receive(on: RunLoop.main) // will be paused when scrolling (on purpose)
.sink { [weak cell] _ in .sink { [weak cell] _ in
@ -473,9 +476,10 @@ extension StatusSection {
.receive(on: RunLoop.main) .receive(on: RunLoop.main)
.sink { _ in .sink { _ in
// do nothing // do nothing
} receiveValue: { [weak cell, weak tableView] change in } receiveValue: { [weak cell, weak tableView, weak dependency] change in
guard let cell = cell else { return } guard let cell = cell else { return }
guard let tableView = tableView else { return } guard let tableView = tableView else { return }
guard let dependency = dependency else { return }
guard case .update(let object) = change.changeType, guard case .update(let object) = change.changeType,
let status = object as? Status, !status.isDeleted else { let status = object as? Status, !status.isDeleted else {
return return
@ -640,7 +644,7 @@ extension StatusSection {
) { ) {
if status.reblog != nil { if status.reblog != nil {
cell.statusView.headerContainerView.isHidden = false cell.statusView.headerContainerView.isHidden = false
cell.statusView.headerIconLabel.attributedText = StatusView.iconAttributedString(image: StatusView.reblogIconImage) cell.statusView.headerIconLabel.configure(attributedString: StatusView.iconAttributedString(image: StatusView.reblogIconImage))
let headerText: String = { let headerText: String = {
let author = status.author let author = status.author
let name = author.displayName.isEmpty ? author.username : author.displayName let name = author.displayName.isEmpty ? author.username : author.displayName
@ -658,7 +662,7 @@ extension StatusSection {
cell.statusView.headerInfoLabel.isAccessibilityElement = true cell.statusView.headerInfoLabel.isAccessibilityElement = true
} else if status.inReplyToID != nil { } else if status.inReplyToID != nil {
cell.statusView.headerContainerView.isHidden = false cell.statusView.headerContainerView.isHidden = false
cell.statusView.headerIconLabel.attributedText = StatusView.iconAttributedString(image: StatusView.replyIconImage) cell.statusView.headerIconLabel.configure(attributedString: StatusView.iconAttributedString(image: StatusView.replyIconImage))
let headerText: String = { let headerText: String = {
guard let replyTo = status.replyTo else { guard let replyTo = status.replyTo else {
return L10n.Common.Controls.Status.userRepliedTo("-") return L10n.Common.Controls.Status.userRepliedTo("-")
@ -721,6 +725,15 @@ extension StatusSection {
statusItemAttribute: Item.StatusAttribute statusItemAttribute: Item.StatusAttribute
) { ) {
// set content // set content
let paragraphStyle = cell.statusView.contentMetaText.paragraphStyle
if let language = (status.reblog ?? status).language {
let direction = Locale.characterDirection(forLanguage: language)
paragraphStyle.alignment = direction == .rightToLeft ? .right : .left
} else {
paragraphStyle.alignment = .natural
}
cell.statusView.contentMetaText.paragraphStyle = paragraphStyle
if let content = content { if let content = content {
cell.statusView.contentMetaText.configure(content: content) cell.statusView.contentMetaText.configure(content: content)
cell.statusView.contentMetaText.textView.accessibilityLabel = content.trimmed cell.statusView.contentMetaText.textView.accessibilityLabel = content.trimmed
@ -970,6 +983,7 @@ extension StatusSection {
cell.statusView.pollCountdownLabel.text = "-" cell.statusView.pollCountdownLabel.text = "-"
} }
cell.statusView.isUserInteractionEnabled = !poll.expired // make voice over touch passthroughable
cell.statusView.pollTableView.allowsSelection = !poll.expired cell.statusView.pollTableView.allowsSelection = !poll.expired
let votedOptions = poll.options.filter { option in let votedOptions = poll.options.filter { option in
@ -1072,7 +1086,7 @@ extension StatusSection {
cell.statusView.actionToolbarContainer.reblogButton.isEnabled = false cell.statusView.actionToolbarContainer.reblogButton.isEnabled = false
} }
} }
// set like // set like
let isLike = status.favouritedBy.flatMap { $0.contains(where: { $0.id == requestUserID }) } ?? false let isLike = status.favouritedBy.flatMap { $0.contains(where: { $0.id == requestUserID }) } ?? false
let favoriteCountTitle: String = { let favoriteCountTitle: String = {
@ -1107,7 +1121,7 @@ extension StatusSection {
StatusSection.setupStatusMoreButtonMenu(cell: cell, dependency: dependency, status: status) StatusSection.setupStatusMoreButtonMenu(cell: cell, dependency: dependency, status: status)
}) })
.store(in: &cell.disposeBag) .store(in: &cell.disposeBag)
self.setupStatusMoreButtonMenu(cell: cell, dependency: dependency, status: status) setupStatusMoreButtonMenu(cell: cell, dependency: dependency, status: status)
} }
static func configureStatusAccessibilityLabel(cell: StatusTableViewCell) { static func configureStatusAccessibilityLabel(cell: StatusTableViewCell) {

View File

@ -0,0 +1,64 @@
//
// UserSection.swift
// Mastodon
//
// Created by Cirno MainasuK on 2021-11-1.
//
import os.log
import UIKit
import CoreData
import CoreDataStack
import MetaTextKit
import MastodonMeta
enum UserSection: Hashable {
case main
}
extension UserSection {
static let logger = Logger(subsystem: "StatusSection", category: "logic")
static func tableViewDiffableDataSource(
for tableView: UITableView,
dependency: NeedsDependency,
managedObjectContext: NSManagedObjectContext
) -> UITableViewDiffableDataSource<UserSection, UserItem> {
UITableViewDiffableDataSource(tableView: tableView) { [
weak dependency
] tableView, indexPath, item -> UITableViewCell? in
guard let dependency = dependency else { return UITableViewCell() }
switch item {
case .follower(let objectID),
.following(let objectID):
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: UserTableViewCell.self), for: indexPath) as! UserTableViewCell
managedObjectContext.performAndWait {
let user = managedObjectContext.object(with: objectID) as! MastodonUser
configure(cell: cell, user: user)
}
return cell
case .bottomLoader:
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self), for: indexPath) as! TimelineBottomLoaderTableViewCell
cell.startAnimating()
return cell
case .bottomHeader(let text):
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: TimelineFooterTableViewCell.self), for: indexPath) as! TimelineFooterTableViewCell
cell.messageLabel.text = text
return cell
} // end switch
} // end UITableViewDiffableDataSource
} // end static func tableViewDiffableDataSource { }
}
extension UserSection {
static func configure(
cell: UserTableViewCell,
user: MastodonUser
) {
cell.configure(user: user)
}
}

View File

@ -0,0 +1,25 @@
//
// Instance.swift
// Mastodon
//
// Created by Cirno MainasuK on 2021-10-9.
//
import UIKit
import CoreDataStack
import MastodonSDK
extension Instance {
var configuration: Mastodon.Entity.Instance.Configuration? {
guard let configurationRaw = configurationRaw else { return nil }
guard let configuration = try? JSONDecoder().decode(Mastodon.Entity.Instance.Configuration.self, from: configurationRaw) else {
return nil
}
return configuration
}
static func encode(configuration: Mastodon.Entity.Instance.Configuration) -> Data? {
return try? JSONEncoder().encode(configuration)
}
}

View File

@ -11,9 +11,9 @@ import MastodonSDK
extension Setting { extension Setting {
var appearance: SettingsItem.AppearanceMode { // var appearance: SettingsItem.AppearanceMode {
return SettingsItem.AppearanceMode(rawValue: appearanceRaw) ?? .automatic // return SettingsItem.AppearanceMode(rawValue: appearanceRaw) ?? .automatic
} // }
var activeSubscription: Subscription? { var activeSubscription: Subscription? {
return (subscriptions ?? Set()) return (subscriptions ?? Set())

View File

@ -20,6 +20,10 @@ extension MetaLabel {
case titleView case titleView
case settingTableFooter case settingTableFooter
case autoCompletion case autoCompletion
case accountListName
case accountListUsername
case sidebarHeadline(isSelected: Bool)
case sidebarSubheadline(isSelected: Bool)
} }
convenience init(style: Style) { convenience init(style: Style) {
@ -30,41 +34,45 @@ extension MetaLabel {
textContainer.lineBreakMode = .byTruncatingTail textContainer.lineBreakMode = .byTruncatingTail
textContainer.lineFragmentPadding = 0 textContainer.lineFragmentPadding = 0
setup(style: style)
}
func setup(style: Style) {
let font: UIFont let font: UIFont
let textColor: UIColor let textColor: UIColor
switch style { switch style {
case .statusHeader: case .statusHeader:
font = UIFontMetrics(forTextStyle: .footnote).scaledFont(for: .systemFont(ofSize: 13, weight: .medium), maximumPointSize: 17) font = UIFontMetrics(forTextStyle: .footnote).scaledFont(for: .systemFont(ofSize: 13, weight: .medium), maximumPointSize: 17)
textColor = Asset.Colors.Label.secondary.color textColor = Asset.Colors.Label.secondary.color
case .statusName: case .statusName:
font = .systemFont(ofSize: 17, weight: .semibold) font = .systemFont(ofSize: 17, weight: .semibold)
textColor = Asset.Colors.Label.primary.color textColor = Asset.Colors.Label.primary.color
case .notificationTitle: case .notificationTitle:
font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 15, weight: .regular), maximumPointSize: 20) font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 15, weight: .regular), maximumPointSize: 20)
textColor = Asset.Colors.Label.secondary.color textColor = Asset.Colors.Label.secondary.color
case .profileFieldName: case .profileFieldName:
font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 17, weight: .semibold), maximumPointSize: 20) font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 17, weight: .semibold), maximumPointSize: 20)
textColor = Asset.Colors.Label.primary.color textColor = Asset.Colors.Label.primary.color
case .profileFieldValue: case .profileFieldValue:
font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 17, weight: .regular), maximumPointSize: 20) font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 17, weight: .regular), maximumPointSize: 20)
textColor = Asset.Colors.Label.primary.color textColor = Asset.Colors.Label.primary.color
textAlignment = .right textAlignment = .right
case .titleView: case .titleView:
font = .systemFont(ofSize: 17, weight: .semibold) font = .systemFont(ofSize: 17, weight: .semibold)
textColor = Asset.Colors.Label.primary.color textColor = Asset.Colors.Label.primary.color
textAlignment = .center textAlignment = .center
paragraphStyle.alignment = .center paragraphStyle.alignment = .center
case .recommendAccountName: case .recommendAccountName:
font = .systemFont(ofSize: 18, weight: .semibold) font = .systemFont(ofSize: 18, weight: .semibold)
textColor = .white textColor = .white
case .settingTableFooter: case .settingTableFooter:
font = .preferredFont(forTextStyle: .footnote) font = .preferredFont(forTextStyle: .footnote)
textColor = Asset.Colors.Label.secondary.color textColor = Asset.Colors.Label.secondary.color
@ -74,8 +82,20 @@ extension MetaLabel {
case .autoCompletion: case .autoCompletion:
font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 17, weight: .semibold), maximumPointSize: 22) font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 17, weight: .semibold), maximumPointSize: 22)
textColor = Asset.Colors.brandBlue.color textColor = Asset.Colors.brandBlue.color
case .accountListName:
font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 17, weight: .regular), maximumPointSize: 22)
textColor = Asset.Colors.Label.primary.color
case .accountListUsername:
font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 15, weight: .regular), maximumPointSize: 20)
textColor = Asset.Colors.Label.secondary.color
case .sidebarHeadline(let isSelected):
font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 22, weight: .regular), maximumPointSize: 20)
textColor = isSelected ? .white : Asset.Colors.Label.primary.color
case .sidebarSubheadline(let isSelected):
font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 13, weight: .regular), maximumPointSize: 18)
textColor = isSelected ? .white : Asset.Colors.Label.secondary.color
} }
self.font = font self.font = font
self.textColor = textColor self.textColor = textColor
@ -91,6 +111,24 @@ extension MetaLabel {
} }
extension MetaLabel {
func configure(attributedString: NSAttributedString) {
let attributedString = NSMutableAttributedString(attributedString: attributedString)
MetaText.setAttributes(
for: attributedString,
textAttributes: textAttributes,
linkAttributes: linkAttributes,
paragraphStyle: paragraphStyle,
content: PlaintextMetaContent(string: "")
)
textStorage.setAttributedString(attributedString)
self.attributedText = attributedString
setNeedsDisplay()
}
}
struct PlaintextMetaContent: MetaContent { struct PlaintextMetaContent: MetaContent {
let string: String let string: String
let entities: [Meta.Entity] = [] let entities: [Meta.Entity] = []

View File

@ -1,24 +0,0 @@
//
// NSDiffableDataSourceSnapshot.swift
// Mastodon
//
// Created by Cirno MainasuK on 2021-6-19.
//
import UIKit
//extension NSDiffableDataSourceSnapshot {
// func itemIdentifier(for indexPath: IndexPath) -> ItemIdentifierType? {
// guard 0..<numberOfSections ~= indexPath.section else {
// return nil
// }
//
// let items = itemIdentifiers(inSection: sectionIdentifiers[indexPath.section])
//
// guard 0..<items.endIndex ~= indexPath.item else {
// return nil
// }
//
// return items[indexPath.item]
// }
//}

View File

@ -0,0 +1,40 @@
//
// UICollectionViewDiffableDataSource.swift
// Mastodon
//
// Created by Cirno MainasuK on 2021-10-11.
//
import UIKit
// ref: https://www.jessesquires.com/blog/2021/07/08/diffable-data-source-behavior-changes-and-reconfiguring-cells-in-ios-15/
extension UICollectionViewDiffableDataSource {
func reloadData(
snapshot: NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>,
completion: (() -> Void)? = nil
) {
if #available(iOS 15.0, *) {
self.applySnapshotUsingReloadData(snapshot, completion: completion)
} else {
self.apply(snapshot, animatingDifferences: false, completion: completion)
}
}
func applySnapshot(
_ snapshot: NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>,
animated: Bool,
completion: (() -> Void)? = nil) {
if #available(iOS 15.0, *) {
self.apply(snapshot, animatingDifferences: animated, completion: completion)
} else {
if animated {
self.apply(snapshot, animatingDifferences: true, completion: completion)
} else {
UIView.performWithoutAnimation {
self.apply(snapshot, animatingDifferences: true, completion: completion)
}
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More