diff --git a/.github/ISSUE_TEMPLATE/bug.yaml b/.github/ISSUE_TEMPLATE/bug.yaml new file mode 100644 index 00000000..c4a1f491 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug.yaml @@ -0,0 +1,62 @@ +name: 🐞 Bug +description: File a bug/issue +title: "[BUG] " +labels: [Bug, Needs Triage] +body: +- type: checkboxes + attributes: + label: Is there an existing issue for this? + description: Please search to see if an issue already exists for the bug you encountered. + options: + - label: I have searched the existing issues + required: true +- type: textarea + attributes: + label: Current Behavior + description: A concise description of what you're experiencing. + validations: + required: false +- type: textarea + attributes: + label: Expected Behavior + description: A concise description of what you expected to happen. + validations: + required: false +- type: textarea + attributes: + label: Steps To Reproduce + description: Steps to reproduce the behavior. + placeholder: | + 1. In this environment... + 2. With this config... + 3. Tap '...' + 4. See error... + validations: + required: false +- type: textarea + attributes: + label: Environment + description: | + You can check the version and build number in the bottom of in-app settings. + examples: + - **Device**: iPhone X + - **OS**: iOS 15.3 + - **Version**: v1.3.0 + - **Build**: 103 + value: | + - Device: + - OS: + - Version: + - Build: + render: markdown + validations: + required: false +- type: textarea + attributes: + label: Anything else? + description: | + The server domain? Post links? Anything that will give us more context about the issue you are encountering! + + Tip: You can attach images or video or log files by clicking this area to highlight it and then dragging files in. + validations: + required: false \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/issue.md b/.github/ISSUE_TEMPLATE/issue.md deleted file mode 100644 index cc2855ed..00000000 --- a/.github/ISSUE_TEMPLATE/issue.md +++ /dev/null @@ -1,32 +0,0 @@ -## Description -<!--Brief description for bug--> - - -## App version -> You can check the version and build number in app setting footer. - -<!--Version Code here--> -- Version: v0.0.0 -- Build: 0 - -## Detail - -### Steps to reproduce - -<!--How to reproduce this bug?--> - -1. Tap … -2. … - -### Actual Behavior - -<!--What happened?--> - -The app … - -### Expected behavior - -<!--What is the expected behavior--> - -The app … - diff --git a/AppShared/Info.plist b/AppShared/Info.plist index 1c2f9cec..73f11cd2 100644 --- a/AppShared/Info.plist +++ b/AppShared/Info.plist @@ -17,6 +17,6 @@ <key>CFBundleShortVersionString</key> <string>1.3.0</string> <key>CFBundleVersion</key> - <string>96</string> + <string>109</string> </dict> </plist> diff --git a/AppStoreSnapshotTestPlan.xctestplan b/AppStoreSnapshotTestPlan.xctestplan new file mode 100644 index 00000000..8761c4c0 --- /dev/null +++ b/AppStoreSnapshotTestPlan.xctestplan @@ -0,0 +1,34 @@ +{ + "configurations" : [ + { + "id" : "E27ADCCD-D2DF-4255-81D1-21CFC3C33254", + "name" : "Configuration 1", + "options" : { + + } + } + ], + "defaultOptions" : { + "defaultTestExecutionTimeAllowance" : 1800, + "testTimeoutsEnabled" : true + }, + "testTargets" : [ + { + "selectedTests" : [ + "MastodonUISnapshotTests\/testSmoke()", + "MastodonUISnapshotTests\/testSnapshotCompose()", + "MastodonUISnapshotTests\/testSnapshotHome()", + "MastodonUISnapshotTests\/testSnapshotProfile()", + "MastodonUISnapshotTests\/testSnapshotSearch()", + "MastodonUISnapshotTests\/testSnapshotServerRules()", + "MastodonUISnapshotTests\/testSnapshotThread()" + ], + "target" : { + "containerPath" : "container:Mastodon.xcodeproj", + "identifier" : "DB427DF225BAA00100D1B89D", + "name" : "MastodonUITests" + } + } + ], + "version" : 1 +} diff --git a/Documentation/Acknowledgments.md b/Documentation/Acknowledgments.md new file mode 100644 index 00000000..eab4b93f --- /dev/null +++ b/Documentation/Acknowledgments.md @@ -0,0 +1,34 @@ +# Acknowledgments + +- [AlamofireImage](https://github.com/Alamofire/AlamofireImage) +- [AlamofireNetworkActivityIndicator](https://github.com/Alamofire/AlamofireNetworkActivityIndicator) +- [Alamofire](https://github.com/Alamofire/Alamofire) +- [CommonOSLog](https://github.com/mainasuk/CommonOSLog) +- [CryptoSwift](https://github.com/krzyzanowskim/CryptoSwift) +- [DateToolSwift](https://github.com/MatthewYork/DateTools) +- [DiffableDataSources](https://github.com/ra1028/DiffableDataSources) +- [DifferenceKit](https://github.com/ra1028/DifferenceKit) +- [FLAnimatedImage](https://github.com/Flipboard/FLAnimatedImage) +- [FLEX](https://github.com/FLEXTool/FLEX) +- [FPSIndicator](https://github.com/MainasuK/FPSIndicator) +- [Fuzi](https://github.com/cezheng/Fuzi) +- [Kanna](https://github.com/tid-kijyun/Kanna) +- [KeychainAccess](https://github.com/kishikawakatsumi/KeychainAccess.git) +- [Kingfisher](https://github.com/onevcat/Kingfisher) +- [MetaTextKit](https://github.com/TwidereProject/MetaTextKit) +- [Nuke-FLAnimatedImage-Plugin](https://github.com/kean/Nuke-FLAnimatedImage-Plugin) +- [Nuke](https://github.com/kean/Nuke) +- [Pageboy](https://github.com/uias/Pageboy#the-basics) +- [PanModal](https://github.com/slackhq/PanModal.git) +- [SDWebImage](https://github.com/SDWebImage/SDWebImage) +- [swift-collections](https://github.com/apple/swift-collections) +- [swift-nio](https://github.com/apple/swift-nio) +- [SwiftGen](https://github.com/SwiftGen/SwiftGen) +- [SwiftUI-Introspect](https://github.com/siteline/SwiftUI-Introspect) +- [SwiftyJSON](https://github.com/SwiftyJSON/SwiftyJSON) +- [Tabman](https://github.com/uias/Tabman) +- [TwidereX-iOS](https://github.com/TwidereProject/TwidereX-iOS) +- [ThirdPartyMailer](https://github.com/vtourraine/ThirdPartyMailer) +- [TOCropViewController](https://github.com/TimOliver/TOCropViewController) +- [TwitterProfile](https://github.com/OfTheWolf/TwitterProfile) +- [UITextView-Placeholder](https://github.com/devxoul/UITextView-Placeholder) \ No newline at end of file diff --git a/Documentation/CONTRIBUTING.md b/Documentation/CONTRIBUTING.md new file mode 100644 index 00000000..cc018445 --- /dev/null +++ b/Documentation/CONTRIBUTING.md @@ -0,0 +1,30 @@ +# Contributing + +- File the issue for bug report and feature request +- Translate the project in our [Crowdin](https://crowdin.com/project/mastodon-for-ios) project +- Make the Pull Request to contribute + +## Bug Report +File the issue about the bug. Make sure you are installing the latest version app from TestFlight or App Store. + +## Translation +[![Crowdin](https://badges.crowdin.net/mastodon-for-ios/localized.svg)](https://crowdin.com/project/mastodon-for-ios) + +The translation will update regularly. Please request language if not listed via issue. + +## Pull Request + +You can make a pull request directly with small block code changes for bugfix or feature implementations. Before making a pull request with hundred lines of changes to this repository, please first discuss the change you wish to make via issue. + +Also, there are lots of existing feature request issues that could be a good-first-issue discussing place. + +Follow the git-flow pattern to make your pull request. + +1. Ensure you are checkout on the `develop` branch. +2. Write your codes and test them on **iPad and iPhone**. +3. Merge the `develop` into your branch then make a Pull Request. Please merge the branch and resolve any conflicts when the `develop` updates. **Do not force push your codes.** +4. Make sure the permission for your folk is open to the reviewer. Code style fix, conflict resolution, and other changes may be committed by the reviewer directly. +5. Request a code review and wait for approval. The PR will be merged when it is approved. + +## Documentation +The documents for this app is list under the [Documentation](../Documentation/) folder. We are also welcome contributions for documentation. \ No newline at end of file diff --git a/Documentation/Setup.md b/Documentation/Setup.md new file mode 100644 index 00000000..ede9d486 --- /dev/null +++ b/Documentation/Setup.md @@ -0,0 +1,83 @@ +# Setup + +## Requirements + +- Xcode 13+ +- Swift 5.5+ +- iOS 14.0+ + + +Intell the latest version of Xcode from the App Store or Apple Developer Download website. Also, we assert you have the [Homebrew](https://brew.sh) package manager. + +This guide may not suit your machine and actually setup procedure may change in the future. Please file the issue or Pull Request if there are any problems. + +## CocoaPods +The app use [CocoaPods]() and [CocoaPods-Keys](https://github.com/orta/cocoapods-keys). The M1 Mac needs virtual ruby env to workaround compatibility issues. + +#### Intel Mac + +```zsh +sudo gem install cocoapods cocoapods-keys +``` + +#### M1 Mac + +```zsh +# install the rbenv +brew install rbenv +which ruby +# > /usr/bin/ruby +echo 'eval "$(rbenv init -)"' >> ~/.zprofile +source ~/.zprofile +which ruby +# > /Users/mainasuk/.rbenv/shims/ruby + +# select ruby +rbenv install --list +# here we use the latest 3.0.x version +rbenv install 3.0.3 +rbenv global 3.0.3 +ruby --version +# > ruby 3.0.3p157 (2021-11-24 revision 3fb7d2cadc) [arm64-darwin21] + +sudo gem install cocoapods cocoapods-keys +``` + +## Bootstrap + +```zsh +# make a clean build +sudo gem install cocoapods-clean +pod clean + +# make install +pod install --repo-update + +# open workspace +open Mastodon.xcworkspace +``` + +The CocoaPods-Key plugin will request the push notification endpoint. You can fufill the empty string and set it later. To setup the push notification. Please check section `Push Notification` below. + +The app requires the `App Group` capability. To make sure it works for your developer membership. Please check [AppSecret.swift](../AppShared/AppSecret.swift) file and set another unique `groupID` and update `App Group` settings. + +#### Push Notification (Optional) +The app is compatible with [toot-relay](https://github.com/DagAgren/toot-relay) APNs. You can set your push notification endpoint via Cocoapod-Keys. There are two endpoints: +- notification_endpoint: for `RELEASE` usage +- notification_endpoint_debug: for `DEBUG` usage + +Please check the [Establishing a Certificate-Based Connection to APNs +](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/establishing_a_certificate-based_connection_to_apns) document to generate the certificate and exports the p12 file. + +Note: +Please check and set the `notification.Topic` to the app BundleID in [toot-relay.go](https://github.com/DagAgren/toot-relay/blob/f9d6894040509881fee845972cd38ec6cd8f5a11/toot-relay.go#L112). The server needs use a reverse proxy to port this relay on 443 port with valid domain and HTTPS certificate. + +## Start +1. Open `Mastodon.xcworkspace` +2. Wait for the Swift Package Dependencies resolved. +2. Check the signing settings make sure to choose a team. [More info…](https://help.apple.com/xcode/mac/current/#/dev23aab79b4) +3. Select `Mastodon` scheme and device then run it. (Command + R) + +## What's next + +We welcome contributions! And if you have an interest to contribute codes. Here is a document that describes the app architecture and what's tech stack it uses. \ No newline at end of file diff --git a/Documentation/Snapshot.md b/Documentation/Snapshot.md new file mode 100644 index 00000000..7140f7a0 --- /dev/null +++ b/Documentation/Snapshot.md @@ -0,0 +1,137 @@ +# Mastodon App Store Snapshot Guide +This documentation is a guide to create snapshots for App Store. The outer contributor could ignore this. + +## Prepare toolkit +The app use the Xcode UITest generate snapshots attachments. Then use the `xcparse` tool extract the snapshots. + +```zsh +# install xcparse from Homebrew +brew install chargepoint/xcparse/xcparse +``` +## How it works +We use `xcodebuild` CLI tool to trigger UITest. + +Set the `name` in `-destination` option to add device for snapshot. For example: +`-destination 'platform=iOS Simulator,name=iPad Pro (12.9-inch) (5th generation)' \` + +You can list the avaiable simulator: +```zsh +# list the destinations +xcodebuild \ + test \ + -showdestinations \ + -derivedDataPath '~/Downloads/MastodonBuild/Derived' \ + -workspace Mastodon.xcworkspace \ + -scheme 'Mastodon - Snapshot' + +# output +Available destinations for the "Mastodon - Snapshot" scheme: + { platform:iOS Simulator, id:7F6D7727-AD49-4B79-B6F5-AEC538925576, OS:15.2, name:iPad (9th generation) } + { platform:iOS Simulator, id:BEB9533C-F786-40E6-8C38-248F6A11FC37, OS:15.2, name:iPad Air (4th generation) } + … +``` + +#### Note: +Multiple lines for destination will dispatches the parallel snapshot jobs. + + +## Login before make snapshots +This script trigger the `MastodonUITests/MastodonUISnapshotTests/testSignInAccount` test case to sign-in the account. The test case may wait for 2FA code or email code. Please input it if needed. Also, you can skip this and sign-in the test account manually. + +Replace the `<Email>` and `<Password>` for test account. +```zsh +# build and run test case for auto sign-in +TEST_RUNNER_login_domain='<Domain>' \ + TEST_RUNNER_login_email='<Email>' \ + TEST_RUNNER_login_password='<Password>' \ + xcodebuild \ + test \ + -derivedDataPath '~/Downloads/MastodonBuild/Derived' \ + -workspace Mastodon.xcworkspace \ + -scheme 'Mastodon - Snapshot' \ + -sdk iphonesimulator \ + -destination 'platform=iOS Simulator,name=iPhone 13 Pro Max' \ + -destination 'platform=iOS Simulator,name=iPhone 8 Plus' \ + -destination 'platform=iOS Simulator,name=iPad Pro (12.9-inch) (5th generation)' \ + -testPlan 'AppStoreSnapshotTestPlan' \ + -only-testing:MastodonUITests/MastodonUISnapshotTests/testSignInAccount +``` + +Note: +UITest may running silent. Open the Simulator.app to make the device display. + +## Take and extract snapshots + +### 1. Setup status bar +```zsh +# boot devices +xcrun simctl boot 'iPhone 8 Plus' +xcrun simctl boot 'iPhone 13 Pro Max' +xcrun simctl boot 'iPad Pro (12.9-inch) (5th generation)' + +# setup magic status bar +xcrun simctl status_bar 'iPhone 13 Pro Max' override --time "9:41" --batteryState charged --batteryLevel 100 +xcrun simctl status_bar 'iPhone 8 Plus' override --time "9:41" --batteryState charged --batteryLevel 100 +xcrun simctl status_bar 'iPad Pro (12.9-inch) (5th generation)' override --time "9:41" --batteryState charged --batteryLevel 100 +``` + +### 2. Take snapshots +The `TEST_RUNNER_` prefix will sets env value into test runner. + +```zsh +# take snapshots +TEST_RUNNER_login_domain='<domain.com>' \ + TEST_RUNNER_login_email='<email>' \ + TEST_RUNNER_login_password='<email>' \ + TEST_RUNNER_thread_id='<thread_id>' \ + TEST_RUNNER_profile_id='<profile_id>' \ + xcodebuild \ + test \ + -derivedDataPath '~/Downloads/MastodonBuild/Derived' \ + -workspace Mastodon.xcworkspace \ + -scheme 'Mastodon - Snapshot' \ + -sdk iphonesimulator \ + -destination 'platform=iOS Simulator,name=iPhone 13 Pro Max' \ + -destination 'platform=iOS Simulator,name=iPhone 8 Plus' \ + -destination 'platform=iOS Simulator,name=iPad Pro (12.9-inch) (5th generation)' \ + -test-iterations 3 \ + -retry-tests-on-failure \ + -testPlan 'AppStoreSnapshotTestPlan' + +# output: +Test session results, code coverage, and logs: + /Users/Me/Downloads/MastodonBuild/Derived/Logs/Test/Test-Mastodon - Snapshot-2022.03.03_18-00-38-+0800.xcresult + +** TEST SUCCEEDED ** +``` + +#### Note: +Add `-only-testing:MastodonUITests/MastodonUISnapshotTests/testSnapshot…` to run specific test case. + +| Task | key | value | +| ------------------- | -------------- | ----------------------------------------------------- | +| testSignInAccount | login_domain | The server domain for user login | +| testSignInAccount | login_email | The user email for login | +| testSignInAccount | login_password | The user password for login | +| testSnapshotThread | thread_id | The ID for post which used for thread scene snapshot | +| testSnapshotProfile | profile_id | The ID for user which used for profile scene snapshot | + +### 3. Extract snapshots +Use `xcparse screenshots <path_for_xcresult> <path_for_destination>` extracts snapshots. + +```zsh +# scresult path for previous test case +xcparse screenshots '<path_for_xcresult>' ~/Downloads/MastodonBuild/Screenshots/ + +# output +100% [============] +🎊 Export complete! 🎊 + +# group +cd ~/Downloads/MastodonBuild/Screenshots/ +mkdir 'iPhone 8 Plus' 'iPhone 13 Pro Max' 'iPad Pro (12.9-inch) (5th generation)' +find . -name "*iPad*" -type file -print0 | xargs -0 -I {} mv {} './iPad Pro (12.9-inch) (5th generation)' +find . -name "*iPhone 8*" -type file -print0 | xargs -0 -I {} mv {} './iPhone 8 Plus' +find . -name "*iPhone 13*" -type file -print0 | xargs -0 -I {} mv {} './iPhone 13 Pro Max' + +``` diff --git a/Localization/Localizable.stringsdict b/Localization/Localizable.stringsdict index ce358b43..4b9a1276 100644 --- a/Localization/Localizable.stringsdict +++ b/Localization/Localizable.stringsdict @@ -156,6 +156,28 @@ <string>%ld reblogs</string> </dict> </dict> + <key>plural.count.reply</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>%#@reply_count@</string> + <key>reply_count</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>ld</string> + <key>zero</key> + <string>0 replies</string> + <key>one</key> + <string>1 reply</string> + <key>few</key> + <string>%ld replies</string> + <key>many</key> + <string>%ld replies</string> + <key>other</key> + <string>%ld replies</string> + </dict> + </dict> <key>plural.count.vote</key> <dict> <key>NSStringLocalizedFormatKey</key> diff --git a/Localization/StringsConvertor/Intents/input/eu_ES/Intents.strings b/Localization/StringsConvertor/Intents/input/eu_ES/Intents.strings new file mode 100644 index 00000000..dbc27c1c --- /dev/null +++ b/Localization/StringsConvertor/Intents/input/eu_ES/Intents.strings @@ -0,0 +1,51 @@ +"16wxgf" = "Argitaratu Mastodonen"; + +"751xkl" = "Testu-edukia"; + +"CsR7G2" = "Argitaratu Mastodonen"; + +"HZSGTr" = "Ze eduki argitaratu?"; + +"HdGikU" = "Argitaratzeak huts egin du"; + +"KDNTJ4" = "Hutsegitearen arrazoia"; + +"RHxKOw" = "Argitaratu bidalketa testu-edukiarekin"; + +"RxSqsb" = "Bidali"; + +"WCIR3D" = "Argitaratu ${content} Mastodonen"; + +"ZKJSNu" = "Bidali"; + +"ZS1XaK" = "${content}"; + +"ZbSjzC" = "Ikusgaitasuna"; + +"Zo4jgJ" = "Bidalketaren ikusgaitasuna"; + +"apSxMG-dYQ5NN" = "'Publikoa'-rekin bat datozen ${count} aukera daude."; + +"apSxMG-ehFLjY" = "'Jarraitzaileak soilik'-ekin bat datozen ${count} aukera daude."; + +"ayoYEb-dYQ5NN" = "${content}, publikoa"; + +"ayoYEb-ehFLjY" = "${content}, jarraitzaileak besterik ez"; + +"dUyuGg" = "Argitaratu Mastodonen"; + +"dYQ5NN" = "Publikoa"; + +"ehFLjY" = "Jarraitzaileak soilik"; + +"gfePDu" = "Argitaratzeak huts egin du. ${failureReason}"; + +"k7dbKQ" = "Bidalketa behar bezala bidali da."; + +"oGiqmY-dYQ5NN" = "Berresteagatik, 'Publikoa' izatea nahi duzu?"; + +"oGiqmY-ehFLjY" = "Berresteagatik, 'Jarraitzaileak soilik' izatea nahi duzu?"; + +"rM6dvp" = "URLa"; + +"ryJLwG" = "Bidalketa behar bezala bidali da. "; diff --git a/Localization/StringsConvertor/Intents/input/eu_ES/Intents.stringsdict b/Localization/StringsConvertor/Intents/input/eu_ES/Intents.stringsdict new file mode 100644 index 00000000..9246c347 --- /dev/null +++ b/Localization/StringsConvertor/Intents/input/eu_ES/Intents.stringsdict @@ -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>${content}(e)kin bat datozen %#@count_option@ daude.</string> + <key>count_option</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>%ld</string> + <key>one</key> + <string>Aukera 1</string> + <key>other</key> + <string>%ld aukera</string> + </dict> + </dict> + <key>There are ${count} options matching ‘${visibility}’.</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>${visibility}(e)kin bat datozen %#@count_option@ daude.</string> + <key>count_option</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>%ld</string> + <key>one</key> + <string>Aukera 1</string> + <key>other</key> + <string>%ld aukera</string> + </dict> + </dict> + </dict> +</plist> diff --git a/Localization/StringsConvertor/Intents/input/fr_FR/Intents.strings b/Localization/StringsConvertor/Intents/input/fr_FR/Intents.strings index f4fec300..2703edd4 100644 --- a/Localization/StringsConvertor/Intents/input/fr_FR/Intents.strings +++ b/Localization/StringsConvertor/Intents/input/fr_FR/Intents.strings @@ -12,7 +12,7 @@ "RHxKOw" = "Envoyer une publication avec du contenu texte"; -"RxSqsb" = "Post"; +"RxSqsb" = "Publication"; "WCIR3D" = "Publier du ${content} sur Mastodon"; @@ -24,9 +24,9 @@ "Zo4jgJ" = "Visibilité de la publication"; -"apSxMG-dYQ5NN" = "There are ${count} options matching ‘Public’."; +"apSxMG-dYQ5NN" = "Il y a ${count} options correspondant à « Public »."; -"apSxMG-ehFLjY" = "There are ${count} options matching ‘Followers Only’."; +"apSxMG-ehFLjY" = "Il y a ${count} options correspondant à « Abonnés uniquement »."; "ayoYEb-dYQ5NN" = "${content}, Public"; diff --git a/Localization/StringsConvertor/Intents/input/it_IT/Intents.strings b/Localization/StringsConvertor/Intents/input/it_IT/Intents.strings new file mode 100644 index 00000000..6877490b --- /dev/null +++ b/Localization/StringsConvertor/Intents/input/it_IT/Intents.strings @@ -0,0 +1,51 @@ +"16wxgf" = "Post on Mastodon"; + +"751xkl" = "Text Content"; + +"CsR7G2" = "Post on Mastodon"; + +"HZSGTr" = "What content to post?"; + +"HdGikU" = "Posting failed"; + +"KDNTJ4" = "Failure Reason"; + +"RHxKOw" = "Send Post with text content"; + +"RxSqsb" = "Post"; + +"WCIR3D" = "Post ${content} on Mastodon"; + +"ZKJSNu" = "Post"; + +"ZS1XaK" = "${content}"; + +"ZbSjzC" = "Visibility"; + +"Zo4jgJ" = "Post Visibility"; + +"apSxMG-dYQ5NN" = "There are ${count} options matching ‘Public’."; + +"apSxMG-ehFLjY" = "There are ${count} options matching ‘Followers Only’."; + +"ayoYEb-dYQ5NN" = "${content}, Public"; + +"ayoYEb-ehFLjY" = "${content}, Followers Only"; + +"dUyuGg" = "Post on Mastodon"; + +"dYQ5NN" = "Public"; + +"ehFLjY" = "Followers Only"; + +"gfePDu" = "Posting failed. ${failureReason}"; + +"k7dbKQ" = "Post was sent successfully."; + +"oGiqmY-dYQ5NN" = "Just to confirm, you wanted ‘Public’?"; + +"oGiqmY-ehFLjY" = "Just to confirm, you wanted ‘Followers Only’?"; + +"rM6dvp" = "URL"; + +"ryJLwG" = "Post was sent successfully. "; diff --git a/Localization/StringsConvertor/Intents/input/it_IT/Intents.stringsdict b/Localization/StringsConvertor/Intents/input/it_IT/Intents.stringsdict new file mode 100644 index 00000000..18422c77 --- /dev/null +++ b/Localization/StringsConvertor/Intents/input/it_IT/Intents.stringsdict @@ -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>There are %#@count_option@ matching ‘${content}’.</string> + <key>count_option</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>%ld</string> + <key>one</key> + <string>1 option</string> + <key>other</key> + <string>%ld options</string> + </dict> + </dict> + <key>There are ${count} options matching ‘${visibility}’.</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>There are %#@count_option@ matching ‘${visibility}’.</string> + <key>count_option</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>%ld</string> + <key>one</key> + <string>1 option</string> + <key>other</key> + <string>%ld options</string> + </dict> + </dict> + </dict> +</plist> diff --git a/Localization/StringsConvertor/Intents/input/ja_JP/Intents.strings b/Localization/StringsConvertor/Intents/input/ja_JP/Intents.strings index 6877490b..411b35c2 100644 --- a/Localization/StringsConvertor/Intents/input/ja_JP/Intents.strings +++ b/Localization/StringsConvertor/Intents/input/ja_JP/Intents.strings @@ -1,51 +1,51 @@ -"16wxgf" = "Post on Mastodon"; +"16wxgf" = "Mastodonに投稿"; -"751xkl" = "Text Content"; +"751xkl" = "テキストコンテンツ"; -"CsR7G2" = "Post on Mastodon"; +"CsR7G2" = "Mastodonに投稿"; "HZSGTr" = "What content to post?"; -"HdGikU" = "Posting failed"; +"HdGikU" = "投稿に失敗しました"; -"KDNTJ4" = "Failure Reason"; +"KDNTJ4" = "失敗の理由"; "RHxKOw" = "Send Post with text content"; -"RxSqsb" = "Post"; +"RxSqsb" = "投稿"; -"WCIR3D" = "Post ${content} on Mastodon"; +"WCIR3D" = "Mastodonに ${content} を投稿"; -"ZKJSNu" = "Post"; +"ZKJSNu" = "投稿"; "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" = "Mastodonに投稿"; -"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"; -"ryJLwG" = "Post was sent successfully. "; +"ryJLwG" = "投稿に成功しました。 "; diff --git a/Localization/StringsConvertor/Intents/input/kab_KAB/Intents.strings b/Localization/StringsConvertor/Intents/input/kab_KAB/Intents.strings new file mode 100644 index 00000000..532c822f --- /dev/null +++ b/Localization/StringsConvertor/Intents/input/kab_KAB/Intents.strings @@ -0,0 +1,51 @@ +"16wxgf" = "Asuffeɣ deg Matodon"; + +"751xkl" = "Agbur n uḍris"; + +"CsR7G2" = "Asuffeɣ deg Matodon"; + +"HZSGTr" = "Anwa agbur ara d-yettwasuffɣen?"; + +"HdGikU" = "Yecceḍ usuffeɣ"; + +"KDNTJ4" = "Ssebba n tuccḍa"; + +"RHxKOw" = "Azen tasuffeɣt s ugbur n uḍris"; + +"RxSqsb" = "Tasuffeɣt"; + +"WCIR3D" = "Suffeɣ ${content} deg Mastodon"; + +"ZKJSNu" = "Tasuffeɣt"; + +"ZS1XaK" = "${content}"; + +"ZbSjzC" = "Abani"; + +"Zo4jgJ" = "Abani n tsuffeɣt"; + +"apSxMG-dYQ5NN" = "Yella ${count} n textiṛiyin yemṣadan d 'Uzayaz'."; + +"apSxMG-ehFLjY" = "Yella ${count} n textiṛiyin yemṣadan d 'Yineḍfaren kan'."; + +"ayoYEb-dYQ5NN" = "${content}, azayaz"; + +"ayoYEb-ehFLjY" = "${content}, ineḍfaren kan"; + +"dUyuGg" = "Asuffeɣ deg Maṣṭudun"; + +"dYQ5NN" = "Azayez"; + +"ehFLjY" = "Imeḍfaṛen kan"; + +"gfePDu" = "Asuffeɣ yecceḍ. ${failureReason}"; + +"k7dbKQ" = "Tasuffeɣt tettwazen akken iwata."; + +"oGiqmY-dYQ5NN" = "I usentem kan, tebɣiḍ 'Azayaz'?"; + +"oGiqmY-ehFLjY" = "I usentem kan, tebɣiḍ 'Ineḍfaren kan'?"; + +"rM6dvp" = "URL"; + +"ryJLwG" = "Tasuffeɣt tettwazen akken iwata. "; diff --git a/Localization/StringsConvertor/Intents/input/kab_KAB/Intents.stringsdict b/Localization/StringsConvertor/Intents/input/kab_KAB/Intents.stringsdict new file mode 100644 index 00000000..a8aeeaaf --- /dev/null +++ b/Localization/StringsConvertor/Intents/input/kab_KAB/Intents.stringsdict @@ -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>Llan %#@count_option@ i yemṣaḍan d '${content}'.</string> + <key>count_option</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>%ld</string> + <key>one</key> + <string>1 textiṛt</string> + <key>other</key> + <string>%ld textiṛiyin</string> + </dict> + </dict> + <key>There are ${count} options matching ‘${visibility}’.</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>Llan %#@count_option@ i yemṣaḍa, d '${visibility}'.</string> + <key>count_option</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>%ld</string> + <key>one</key> + <string>1 uɣewwaṛ</string> + <key>other</key> + <string>%ld iɣewwaṛen</string> + </dict> + </dict> + </dict> +</plist> diff --git a/Localization/StringsConvertor/Intents/input/sv_FI/Intents.strings b/Localization/StringsConvertor/Intents/input/sv_FI/Intents.strings index d4531ed6..1be213d4 100644 --- a/Localization/StringsConvertor/Intents/input/sv_FI/Intents.strings +++ b/Localization/StringsConvertor/Intents/input/sv_FI/Intents.strings @@ -1,51 +1,51 @@ -"16wxgf" = "Post on Mastodon"; +"16wxgf" = "Julkaise Mastodonissa"; -"751xkl" = "Text Content"; +"751xkl" = "Tekstisisältö"; -"CsR7G2" = "Post on Mastodon"; +"CsR7G2" = "Julkaise Mastodonissa"; -"HZSGTr" = "What content to post?"; +"HZSGTr" = "Mitä sisältöä julkaista?"; -"HdGikU" = "Posting failed"; +"HdGikU" = "Julkaiseminen epäonnistui"; -"KDNTJ4" = "Failure Reason"; +"KDNTJ4" = "Epäonnistumisen syy"; -"RHxKOw" = "Send Post with text content"; +"RHxKOw" = "Lähetä julkaisu teksisisällöllä"; -"RxSqsb" = "Post"; +"RxSqsb" = "Julkaisu"; -"WCIR3D" = "Posta ${content} på Mastodon"; +"WCIR3D" = "Julkaise ${content} Mastodonissa"; -"ZKJSNu" = "Post"; +"ZKJSNu" = "Julkaisu"; "ZS1XaK" = "${content}"; -"ZbSjzC" = "Visibility"; +"ZbSjzC" = "Näkyvyys"; -"Zo4jgJ" = "Post Visibility"; +"Zo4jgJ" = "Julkaisun näkyvyys"; -"apSxMG-dYQ5NN" = "There are ${count} options matching ‘Public’."; +"apSxMG-dYQ5NN" = "On ${count} vaihtoehtoa, jotka vastaavat ‘Julkinen’."; -"apSxMG-ehFLjY" = "There are ${count} options matching ‘Followers Only’."; +"apSxMG-ehFLjY" = "On ${count} vaihtoehtoa, jotka vastaavat ‘Vain seuraajat’."; -"ayoYEb-dYQ5NN" = "${content}, Public"; +"ayoYEb-dYQ5NN" = "${content}, julkinen"; -"ayoYEb-ehFLjY" = "${content}, Followers Only"; +"ayoYEb-ehFLjY" = "${content}, vain seuraajat"; -"dUyuGg" = "Post on Mastodon"; +"dUyuGg" = "Julkaise Mastodonissa"; -"dYQ5NN" = "Public"; +"dYQ5NN" = "Julkinen"; -"ehFLjY" = "Followers Only"; +"ehFLjY" = "Vain seuraajat"; -"gfePDu" = "Posting failed. ${failureReason}"; +"gfePDu" = "Julkaiseminen epäonnistui. ${failureReason}"; -"k7dbKQ" = "Post was sent successfully."; +"k7dbKQ" = "Julkaisu lähetettiin onnistuneesti."; -"oGiqmY-dYQ5NN" = "Just to confirm, you wanted ‘Public’?"; +"oGiqmY-dYQ5NN" = "Vahvitukseksi, halusit ‘Julkinen’?"; -"oGiqmY-ehFLjY" = "Just to confirm, you wanted ‘Followers Only’?"; +"oGiqmY-ehFLjY" = "Vahvitstukseksi, halusit ‘Vain seuraajat’?"; "rM6dvp" = "URL"; -"ryJLwG" = "Post was sent successfully. "; +"ryJLwG" = "Julkaisu lähetettiin onnistuneesti. "; diff --git a/Localization/StringsConvertor/Intents/input/sv_FI/Intents.stringsdict b/Localization/StringsConvertor/Intents/input/sv_FI/Intents.stringsdict index 18422c77..7825b778 100644 --- a/Localization/StringsConvertor/Intents/input/sv_FI/Intents.stringsdict +++ b/Localization/StringsConvertor/Intents/input/sv_FI/Intents.stringsdict @@ -5,7 +5,7 @@ <key>There are ${count} options matching ‘${content}’. - 2</key> <dict> <key>NSStringLocalizedFormatKey</key> - <string>There are %#@count_option@ matching ‘${content}’.</string> + <string>On %#@count_option@, joka/jotka vastaavat sisältöön ‘${content}’.</string> <key>count_option</key> <dict> <key>NSStringFormatSpecTypeKey</key> @@ -13,15 +13,15 @@ <key>NSStringFormatValueTypeKey</key> <string>%ld</string> <key>one</key> - <string>1 option</string> + <string>1 vaihtoehto</string> <key>other</key> - <string>%ld options</string> + <string>%ld vaihtoehtoa</string> </dict> </dict> <key>There are ${count} options matching ‘${visibility}’.</key> <dict> <key>NSStringLocalizedFormatKey</key> - <string>There are %#@count_option@ matching ‘${visibility}’.</string> + <string>On vaihtoehtoa %#@count_option@, joka/jotka vastaavat näkyvyyteen ‘${visibility}’.</string> <key>count_option</key> <dict> <key>NSStringFormatSpecTypeKey</key> @@ -29,9 +29,9 @@ <key>NSStringFormatValueTypeKey</key> <string>%ld</string> <key>one</key> - <string>1 option</string> + <string>1 vaihtoehto</string> <key>other</key> - <string>%ld options</string> + <string>%ld vaihtoehtoa</string> </dict> </dict> </dict> diff --git a/Localization/StringsConvertor/Intents/input/sv_SE/Intents.strings b/Localization/StringsConvertor/Intents/input/sv_SE/Intents.strings index d4531ed6..e81116ee 100644 --- a/Localization/StringsConvertor/Intents/input/sv_SE/Intents.strings +++ b/Localization/StringsConvertor/Intents/input/sv_SE/Intents.strings @@ -34,9 +34,9 @@ "dUyuGg" = "Post on Mastodon"; -"dYQ5NN" = "Public"; +"dYQ5NN" = "Publikt"; -"ehFLjY" = "Followers Only"; +"ehFLjY" = "Endast följare"; "gfePDu" = "Posting failed. ${failureReason}"; diff --git a/Localization/StringsConvertor/Sources/StringsConvertor/main.swift b/Localization/StringsConvertor/Sources/StringsConvertor/main.swift index 79ee6b49..14266a45 100644 --- a/Localization/StringsConvertor/Sources/StringsConvertor/main.swift +++ b/Localization/StringsConvertor/Sources/StringsConvertor/main.swift @@ -56,7 +56,7 @@ private func map(language: String) -> String? { case "fr_FR": return "fr" // French case "de_DE": return "de" // German case "ja_JP": return "ja" // Japanese - case "kmr_TR": return "ku-TR" // Kurmanji (Kurdish) + case "kmr_TR": return "ku" // Kurmanji (Kurdish) case "ru_RU": return "ru" // Russian case "gd_GB": return "gd-GB" // Scottish Gaelic case "es_ES": return "es" // Spanish diff --git a/Localization/StringsConvertor/input/ar_SA/app.json b/Localization/StringsConvertor/input/ar_SA/app.json index 71e0f538..51b33472 100644 --- a/Localization/StringsConvertor/input/ar_SA/app.json +++ b/Localization/StringsConvertor/input/ar_SA/app.json @@ -2,8 +2,8 @@ "common": { "alerts": { "common": { - "please_try_again": "يُرجى المحاولة مرة أُخرى.", - "please_try_again_later": "يُرجى المحاولة مرة أُخرى لاحقاً." + "please_try_again": "يُرجى المُحاولة مرة أُخرى.", + "please_try_again_later": "يُرجى المُحاولة مرة أُخرى لاحقًا." }, "sign_up_failure": { "title": "إخفاق في التسجيل" @@ -28,17 +28,17 @@ } }, "edit_profile_failure": { - "title": "خطأ في تَحرير الملف الشخصي", - "message": "لا يمكن تعديل الملف الشخصي. يُرجى المحاولة مرة أُخرى." + "title": "خطأ في تَحرير الملف التعريفي", + "message": "يتعذَّر تعديل الملف التعريفي. يُرجى المُحاولة مرة أُخرى." }, "sign_out": { "title": "تسجيل الخروج", - "message": "هل أنت متأكد من رغبتك في تسجيل الخروج؟", + "message": "هل أنت متأكد من رغبتك في تسجيل الخُروج؟", "confirm": "تسجيل الخروج" }, "block_domain": { - "title": "هل أنتَ مُتأكِّدٌ حقًا مِن رغبتك في حظر %s بالكامل؟ في معظم الحالات، يكون مِنَ الكافي والمُفَضَّل استهداف عدد محدود للحظر أو الكتم. لن ترى محتوى من هذا النطاق وسوف يتم إزالة جميع متابعيك المتواجدين فيه.", - "block_entire_domain": "حظر النِطاق" + "title": "هل أنتَ مُتأكِّدٌ حقًا مِن رغبتك في حظر %s بالكامل؟ في معظم الحالات، يكون مِنَ الكافي والمُفَضَّل استهداف عدد محدود للحظر أو الكتم. لن ترى محتوى من هذا النطاق وسوف يُزال جميع متابعيك المتواجدين فيه.", + "block_entire_domain": "حظر النِّطاق" }, "save_photo_failure": { "title": "إخفاق في حفظ الصورة", @@ -46,11 +46,11 @@ }, "delete_post": { "title": "هل أنت متأكد من رغبتك في حذف هذا المنشور؟", - "delete": "احذف" + "message": "هَل أنتَ مُتأكِدٌ مِن رَغبتِكَ فِي حَذفِ هَذَا المَنشُور؟" }, "clean_cache": { "title": "مَحو ذاكرة التخزين المؤقت", - "message": "تمَّ مَحو ذاكرة التخزين المؤقت %s بنجاح." + "message": "تمَّ مَحو %s مِن ذاكرة التخزين المؤقت بنجاح." } }, "controls": { @@ -58,9 +58,9 @@ "back": "العودة", "next": "التالي", "previous": "السابق", - "open": "افتح", + "open": "فتح", "add": "إضافة", - "remove": "احذف", + "remove": "حذف", "edit": "تحرير", "save": "حفظ", "ok": "حسنًا", @@ -69,7 +69,7 @@ "continue": "واصل", "compose": "تأليف", "cancel": "إلغاء", - "discard": "تجاهل", + "discard": "تجاهُل", "try_again": "المُحاولة مرة أُخرى", "take_photo": "التقاط صورة", "save_photo": "حفظ الصورة", @@ -81,20 +81,21 @@ "share": "المُشارك", "share_user": "مُشاركة %s", "share_post": "مشارك المنشور", - "open_in_safari": "الفتح في Safari", - "find_people": "ابحث عن أشخاص لمتابعتهم", - "manually_search": "البحث يدوياً بدلاً من ذلك", + "open_in_safari": "الفَتحُ في Safari", + "open_in_browser": "الفَتحُ في المُتَصَفِّح", + "find_people": "ابحث عن أشخاص لِمُتابعتهم", + "manually_search": "البحث يدويًا بدلًا من ذلك", "skip": "تخطي", - "reply": "الرَد", - "report_user": "ابلغ عن %s", + "reply": "الرَّد", + "report_user": "الإبلاغ عن %s", "block_domain": "حظر %s", - "unblock_domain": "إلغاء حظر %s", + "unblock_domain": "رفع الحظر عن %s", "settings": "الإعدادات", - "delete": "احذف" + "delete": "حذف" }, "tabs": { - "home": "الخيط الرئيسي", - "search": "بحث", + "home": "الرَّئِيسَة", + "search": "البَحث", "notification": "الإشعارات", "profile": "الملف التعريفي" }, @@ -102,17 +103,17 @@ "common": { "switch_to_tab": "التبديل إلى %s", "compose_new_post": "تأليف منشور جديد", - "show_favorites": "إظهار المفضلة", - "open_settings": "أفتح الإعدادات" + "show_favorites": "إظهار المُفضَّلة", + "open_settings": "فَتحُ الإعدادات" }, "timeline": { "previous_status": "المنشور السابق", "next_status": "المنشور التالي", - "open_status": "افتح المنشور", - "open_author_profile": "افتح الملف التعريفي للمؤلف", - "open_reblogger_profile": "افتح الملف التعريفي لمشارِك المنشور", - "reply_status": "رد على المنشور", - "toggle_reblog": "تبديل إعادة تدوين منشور", + "open_status": "فتح المنشور", + "open_author_profile": "فتح الملف التعريفي للمؤلف", + "open_reblogger_profile": "فتح الملف التعريفي لمُعيد تدوين المنشور", + "reply_status": "الرَّد على مَنشور", + "toggle_reblog": "تبديل إعادة تدوين مَنشور", "toggle_favorite": "تبديل المفضلة لِمنشور", "toggle_content_warning": "تبديل تحذير المُحتَوى", "preview_image": "معاينة الصورة" @@ -124,131 +125,148 @@ }, "status": { "user_reblogged": "أعادَ %s تدوينها", - "user_replied_to": "رد على %s", - "show_post": "اظهر المنشور", - "show_user_profile": "اظهر الملف التعريفي للمستخدم", - "content_warning": "تحذير عن المحتوى", - "media_content_warning": "انقر على أي مكان للكشف", + "user_replied_to": "رَدًا على %s", + "show_post": "إظهار منشور", + "show_user_profile": "إظهار الملف التعريفي للمُستخدِم", + "content_warning": "تحذير المُحتوى", + "media_content_warning": "انقر للكشف", "poll": { "vote": "صَوِّت", "closed": "انتهى" }, "actions": { - "reply": "رد", + "reply": "الرَّد", "reblog": "إعادة النشر", - "unreblog": "تراجع عن إعادة النشر", - "favorite": "إضافة إلى المفضلة", - "unfavorite": "إزالة من المفضلة", - "menu": "القائمة" + "unreblog": "التراجُع عن إعادة النشر", + "favorite": "التفضيل", + "unfavorite": "إزالة التفضيل", + "menu": "القائمة", + "hide": "إخفاء" }, "tag": { "url": "عنوان URL", - "mention": "أشر إلى", - "link": "الرابط", - "hashtag": "الوسم", - "email": "البريد الإلكتروني", - "emoji": "إيموجي" + "mention": "إشارة", + "link": "رابط", + "hashtag": "وسم", + "email": "بريد إلكتروني", + "emoji": "رمز تعبيري" + }, + "visibility": { + "unlisted": "يُمكِنُ لِلجَميعِ رُؤيَةُ هَذَا المَنشورِ وَلكِنَّهُ لَا يُعرَضُ فِي الخَطِّ الزَمنيّ العام.", + "private": "فَقَطْ مُتابِعينَهُم مَن يُمكِنُهُم رُؤيَةُ هَذَا المَنشُور.", + "private_from_me": "فَقَطْ مُتابِعيني أنَا مَن يُمكِنُهُم رُؤيَةُ هَذَا المَنشُور.", + "direct": "المُستخدمِونَ المُشارِ إليهم فَقَطْ مَن يُمكِنُهُم رُؤيَةُ هَذَا المَنشُور." } }, "friendship": { - "follow": "اتبع", + "follow": "مُتابَعَة", "following": "مُتابَع", "request": "إرسال طَلَب", "pending": "قيد المُراجعة", "block": "حظر", "block_user": "حظر %s", "block_domain": "حظر %s", - "unblock": "إلغاء الحَظر", - "unblock_user": "إلغاء حظر %s", + "unblock": "رفع الحَظر", + "unblock_user": "رفع الحَظر عن %s", "blocked": "محظور", - "mute": "أكتم", - "mute_user": "أكتم %s", - "unmute": "إلغاء الكتم", - "unmute_user": "إلغاء كتم %s", + "mute": "كَتم", + "mute_user": "كَتم %s", + "unmute": "رفع الكتم", + "unmute_user": "رفع الكتم عن %s", "muted": "مكتوم", "edit_info": "تعديل المعلومات" }, "timeline": { "filtered": "مُصفَّى", "timestamp": { - "now": "الأن" + "now": "الآن" }, "loader": { - "load_missing_posts": "تحميل المنشورات المَفقودة", - "loading_missing_posts": "تحميل المزيد من المنشورات...", - "show_more_replies": "إظهار المزيد من الردود" + "load_missing_posts": "تحميل المَنشورات المَفقودَة", + "loading_missing_posts": "يَجري تحميل المَنشورات المَفقودَة...", + "show_more_replies": "إظهار مَزيد مِنَ الرُّدود" }, "header": { - "no_status_found": "لا توجد هناك منشورات", - "blocking_warning": "لا يُمكنك الاطلاع على الملف الشخصي لهذا المُستخدِم\nحتَّى تَرفعَ الحَظر عنه.\nملفًّكَ الشخصي يَظهَرُ بِمثل هذِهِ الحالة بالنسبةِ لَهُ أيضًا.", - "user_blocking_warning": "لا يُمكنك الاطلاع على ملف %s الشخصي\nحتَّى تَرفعَ الحَظر عنه.\nملفًّكَ الشخصي يَظهَرُ بِمثل هذِهِ الحالة بالنسبةِ لَهُ أيضًا.", - "blocked_warning": "لا يُمكِنُكَ عَرض الملف الشخصي لهذا المُستخدِم\nحتَّى يَرفَعَ الحَظر عَنك.", - "user_blocked_warning": "لا يُمكِنُكَ عَرض ملف %s الشخصي\nحتَّى يَرفَعَ الحَظر عَنك.", + "no_status_found": "لَم يُعْثَر على مَنشورات", + "blocking_warning": "لا يُمكِنُكَ الاِطلاع على الملف التَعريفي لهذا المُستخدِم\nحتَّى تَرفعَ الحَظر عنه.\nملفُّكَ التَعريفي يَظهَرُ بِمثل هذِهِ الحالة بالنسبةِ لَهُ أيضًا.", + "user_blocking_warning": "لا يُمكنك الاطلاع على ملف %s التَعريفي\nحتَّى تَرفعَ الحَظر عنه.\nملفُّكَ التَعريفي يَظهَرُ بِمثل هذِهِ الحالة بالنسبةِ لَهُ أيضًا.", + "blocked_warning": "لا يُمكِنُكَ عَرض الملف التَعريفي لهذا المُستخدِم\nحتَّى يَرفَعَ الحَظرَ عَنك.", + "user_blocked_warning": "لا يُمكِنُكَ عَرض ملف %s التَعريفي\nحتَّى يَرفَعَ الحَظر عَنك.", "suspended_warning": "تمَّ إيقاف هذا المُستخدِم.", - "user_suspended_warning": "لقد أوقِفَ حِساب %s." + "user_suspended_warning": "لقد أُوقِفَ حِساب %s." } } } }, "scene": { "welcome": { - "slogan": "شبكات التواصل الاجتماعي\nمرة أُخرى بين يديك." + "slogan": "شبكات التواصل الاجتماعي\nمرة أُخرى بين يديك.", + "get_started": "ابدأ الآن", + "log_in": "تسجيلُ الدخول" }, "server_picker": { - "title": "اِختر خادِم،\nأي خادِم.", + "title": "اِختر خادِم،\nأيًّا مِنهُم.", + "subtitle": "اختر مجتمعًا بناءً على اهتماماتك، منطقتك أو يمكنك حتى اختيارُ مجتمعٍ ذي غرضٍ عام.", + "subtitle_extend": "اختر مجتمعًا بناءً على اهتماماتك، منطقتك أو يمكنك حتى اختيارُ مجتمعٍ ذي غرضٍ عام. تُشغَّل جميعُ المجتمعِ مِن قِبَلِ مُنظمَةٍ أو فردٍ مُستقلٍ تمامًا.", "button": { "category": { "all": "الكل", "all_accessiblity_description": "الفئة: الكل", "academia": "أكاديمي", - "activism": "للنشطاء", + "activism": "النشطاء", "food": "الطعام", - "furry": "فروي", + "furry": "مكسو بالفرو", "games": "ألعاب", "general": "عام", "journalism": "صحافة", "lgbt": "مجتمع الشواذ", - "regional": "اقليمي", - "art": "فن", + "regional": "إقليمي", + "art": "فنون", "music": "موسيقى", - "tech": "تكنولوجيا" + "tech": "تقنية" }, - "see_less": "اعرض أقل", - "see_more": "اعرض المزيد" + "see_less": "عرض عناصر أقل", + "see_more": "عرض عناصر أكثر" }, "label": { - "language": "اللغة", - "users": "مستخدمون·ات", + "language": "اللُّغة", + "users": "مُستَخدِم", "category": "الفئة" }, "input": { - "placeholder": "ابحث عن خادم أو انضم إلى سيرفر خاص بك..." + "placeholder": "اِبحَث عن خادِم أو انضم إلى آخر خاص بك..." }, "empty_state": { - "finding_servers": "البحث عن خوادم متوفرة...", + "finding_servers": "يجري إيجاد خوادم متوفِّرَة...", "bad_network": "حدث خطأٌ ما أثناء تحميل البيانات. تحقَّق من اتصالك بالإنترنت.", "no_results": "لا توجد نتائج" } }, "register": { - "title": "أخبرنا عنك.", + "title": "أخبرنا عن نفسك.", "input": { "avatar": { - "delete": "احذف" + "delete": "حذف" }, "username": { - "placeholder": "اسم المستخدم", - "duplicate_prompt": "اسم المستخدم هذا غير متوفر." + "placeholder": "اِسم مُستَخدِم", + "duplicate_prompt": "اِسم المُستَخدِم هذا مأخوذٌ بالفعل." }, "display_name": { - "placeholder": "الاسم المعروض" + "placeholder": "اِسم العَرض" }, "email": { - "placeholder": "البريد الإلكتروني" + "placeholder": "بريد إلكتروني" }, "password": { - "placeholder": "الكلمة السرية", - "hint": "يجب أن تكون كلمتك السرية متكونة من ثمانية أحرف على الأقل" + "placeholder": "رمز سري", + "require": "رمز المرور الخاص بك يجب أن يحتوي على الأقل:", + "character_limit": "ثمانيةُ خانات", + "accessibility": { + "checked": "مُتَحَققٌ مِنه", + "unchecked": "غيرُ مُتَحَققٍ مِنه" + }, + "hint": "يجب أن يكون رمزك السري مكوَّن من ثمان خانات على الأقل" }, "invite": { "registration_user_invite_request": "لماذا ترغب في الانضمام؟" @@ -256,10 +274,10 @@ }, "error": { "item": { - "username": "اسم المستخدم", + "username": "اِسم المُستَخدِم", "email": "البريد الإلكتروني", - "password": "الكلمة السرية", - "agreement": "الاتفاقية", + "password": "الرمز السري", + "agreement": "الاِتِّفاقيَّة", "locale": "اللغة المحلية", "reason": "السبب" }, @@ -269,40 +287,40 @@ "taken": "إنَّ %s مُستخدَمٌ بالفعل", "reserved": "إنَّ %s عبارة عن كلمة مفتاحيَّة محجوزة", "accepted": "يجب أن يُقبل %s", - "blank": "%s مطلوب", + "blank": "%s مَطلوب", "invalid": "%s غير صالح", "too_long": "%s طويل جداً", - "too_short": "%s قصير جدا", + "too_short": "%s قصير جدًا", "inclusion": "إنَّ %s قيمة غير مدعومة" }, "special": { "username_invalid": "يُمكِن أن يحتوي اسم المستخدم على أحرف أبجدية، أرقام وشرطات سفلية فقط", - "username_too_long": "اسم المستخدم طويل جداً (يجب ألّا يكون أطول من 30 رمز)", + "username_too_long": "اِسم المُستَخدِم طويل جداً (يَجِبُ ألّا يكون أطول من ثلاثين خانة)", "email_invalid": "هذا عنوان بريد إلكتروني غير صالح", - "password_too_short": "كلمة المرور قصيرة جداً (يجب أن تكون 8 أحرف على الأقل)" + "password_too_short": "رمز السر قصير جدًا (يجب أن يتكون من ثمان خانات على الأقل)" } } }, "server_rules": { "title": "بعض القواعد الأساسية.", - "subtitle": "تم سنّ هذه القواعد من قبل مشرفي %s.", - "prompt": "إن اخترت المواصلة، فإنك تخضع لشروط الخدمة وسياسة الخصوصية لـ %s.", - "terms_of_service": "شروط الخدمة", - "privacy_policy": "سياسة الخصوصية", + "subtitle": "سُنَّت هذه القواعد من قِبل مشرفي %s.", + "prompt": "في حال إختيارك للمواصلة، أنت تخضع لشروط الخدمة وسياسة الخصوصية لِـ%s.", + "terms_of_service": "شُرُوط الخِدمَة", + "privacy_policy": "سِياسَة الخُصُوصيَّة", "button": { - "confirm": "انا أوافق" + "confirm": "أنا مُوافِق" } }, "confirm_email": { - "title": "شيء واحد أخير.", - "subtitle": "لقد أرسلنا للتو رسالة بريد إلكتروني إلى %s،\nاضغط على الرابط لتأكيد حسابك.", + "title": "شيءٌ أخير.", + "subtitle": "لقد أرسلنا للتو بريد إلكتروني إلى %s،\nانقر على الرابط لتأكيد حسابك.", "button": { - "open_email_app": "افتح تطبيق البريد الإلكتروني", - "dont_receive_email": "لم أستلم أبدًا بريدا إلكترونيا" + "open_email_app": "فتح تطبيق البريد الإلكتروني", + "resend": "إعادَةُ الإرسال" }, "dont_receive_email": { "title": "تحقق من بريدك الإلكتروني", - "description": "تحقق ممَّ إذا كان عنوان بريدك الإلكتروني صحيحًا وكذلك تأكد مِن مجلد البريد غير الهام إذا لم تكن قد فعلت ذلك.", + "description": "تحقق ممَّ إذا كان عنوان بريدك الإلكتروني صحيحًا، وكذلك تأكد مِن مجلد البريد غير الهام إذا لم تكن قد فعلت ذلك.", "resend_email": "إعادة إرسال البريد الإلكتروني" }, "open_email_app": { @@ -313,12 +331,12 @@ } }, "home_timeline": { - "title": "الخيط الرئيسي", + "title": "الرَّئِيسَة", "navigation_bar_state": { - "offline": "غير متصل", + "offline": "غَير مُتَّصِل", "new_posts": "إظهار منشورات جديدة", - "published": "تم نشره!", - "Publishing": "جارٍ نشر المشاركة…" + "published": "تمَّ النَّشر!", + "Publishing": "يَجري نَشر المُشارَكَة..." } }, "suggestion_account": { @@ -328,31 +346,31 @@ "compose": { "title": { "new_post": "منشور جديد", - "new_reply": "رد جديد" + "new_reply": "رَدٌّ جديد" }, "media_selection": { - "camera": "التقط صورة", + "camera": "إلتقاط صورة", "photo_library": "مكتبة الصور", "browse": "تصفح" }, "content_input_placeholder": "أخبِرنا بِما يَجُولُ فِي ذِهنَك", - "compose_action": "انشر", - "replying_to_user": "رد على %s", + "compose_action": "نَشر", + "replying_to_user": "رَدًا على %s", "attachment": { "photo": "صورة", - "video": "فيديو", - "attachment_broken": "هذا ال%s مُعطَّل ويتعذَّر رفعه إلى ماستودون.", - "description_photo": "صِف الصورة للمكفوفين...", - "description_video": "صِف المقطع المرئي للمكفوفين..." + "video": "مقطع مرئي", + "attachment_broken": "هذا ال%s مُعطَّل\nويتعذَّرُ رفعُه إلى ماستودون.", + "description_photo": "صِف الصورة للمَكفوفين...", + "description_video": "صِف المقطع المرئي للمَكفوفين..." }, "poll": { - "duration_time": "المدة: %s", - "thirty_minutes": "30 دقيقة", - "one_hour": "ساعة واحدة", - "six_hours": "6 ساعات", - "one_day": "يوم واحد", - "three_days": "3 أيام", - "seven_days": "7 أيام", + "duration_time": "المُدَّة: %s", + "thirty_minutes": "ثلاثون دقيقة", + "one_hour": "ساعةٌ واحدة", + "six_hours": "سِتُّ ساعات", + "one_day": "يومٌ واحِد", + "three_days": "ثلاثةُ أيام", + "seven_days": "سبعةُ أيام", "option_number": "الخيار %ld" }, "content_warning": { @@ -361,33 +379,33 @@ "visibility": { "public": "للعامة", "unlisted": "غير مُدرَج", - "private": "لمتابعيك فقط", - "direct": "ففط للأشخاص المشار إليهم" + "private": "للمُتابِعينَ فقط", + "direct": "للأشخاص المُشار إليهم فقط" }, "auto_complete": { - "space_to_add": "انقر مساحة لإضافتِها" + "space_to_add": "انقر على مساحة لإضافتِها" }, "accessibility": { "append_attachment": "إضافة مُرفَق", "append_poll": "اضافة استطلاع رأي", "remove_poll": "إزالة الاستطلاع", - "custom_emoji_picker": "منتقي مخصص للإيموجي", - "enable_content_warning": "تنشيط تحذير المحتوى", - "disable_content_warning": "تعطيل تحذير الحتوى", + "custom_emoji_picker": "منتقي الرموز التعبيرية المُخصَّص", + "enable_content_warning": "تفعيل تحذير المُحتَوى", + "disable_content_warning": "تعطيل تحذير المُحتَوى", "post_visibility_menu": "قائمة ظهور المنشور" }, "keyboard": { "discard_post": "تجاهُل المنشور", "publish_post": "نَشر المَنشُور", "toggle_poll": "تبديل الاستطلاع", - "toggle_content_warning": "تبديل تحذير المُحتوى", + "toggle_content_warning": "تبديل تحذير المُحتَوى", "append_attachment_entry": "إضافة مُرفَق - %s", "select_visibility_entry": "اختر مدى الظهور - %s" } }, "profile": { "dashboard": { - "posts": "منشورات", + "posts": "مَنشورات", "following": "مُتابَع", "followers": "متابِع" }, @@ -395,22 +413,32 @@ "add_row": "إضافة صف", "placeholder": { "label": "التسمية", - "content": "المحتوى" + "content": "المُحتَوى" } }, "segmented_control": { - "posts": "منشورات", - "replies": "ردود", - "media": "وسائط" + "posts": "مَنشورات", + "replies": "رُدُود", + "posts_and_replies": "المَنشوراتُ وَالرُدود", + "media": "وَسائِط", + "about": "حَول" }, "relationship_action_alert": { - "confirm_unmute_user": { - "title": "إلغاء كتم الحساب", - "message": "أكِّد لرفع كتمْ %s" + "confirm_mute_user": { + "title": "كَتمُ الحِساب", + "message": "تأكيدُ كَتم %s" }, - "confirm_unblock_usre": { - "title": "إلغاء حظر الحساب", - "message": "أكِّد لرفع حظر %s" + "confirm_unmute_user": { + "title": "رفع الكتم عن الحساب", + "message": "أكِّد لرفع الكتمْ عن %s" + }, + "confirm_block_user": { + "title": "حَظرُ الحِساب", + "message": "تأكيدُ حَظر %s" + }, + "confirm_unblock_user": { + "title": "رَفعُ الحَظرِ عَنِ الحِساب", + "message": "تأكيدُ رَفع الحَظرِ عَن %s" } } }, @@ -421,52 +449,54 @@ "footer": "لا يُمكِن عَرض المُتابَعات مِنَ الخوادم الأُخرى." }, "search": { - "title": "بحث", + "title": "البحث", "search_bar": { - "placeholder": "البحث عن وسوم أو مستخدمين·ات", + "placeholder": "البحث عن وسوم أو مستخدمين", "cancel": "إلغاء" }, "recommend": { - "button_text": "طالع الكل", + "button_text": "إظهار الكُل", "hash_tag": { - "title": "ذات شعبية على ماستدون", - "description": "الوسوم التي تحظى بقدر كبير من الاهتمام", + "title": "ذُو شعبيَّة على ماستودون", + "description": "الوُسُومُ الَّتي تَحظى بقدرٍ كبيرٍ مِنَ الاِهتمام", "people_talking": "%s أشخاص يتحدَّثوا" }, "accounts": { - "title": "حسابات قد تعجبك", - "description": "قد ترغب في متابعة هذه الحسابات", - "follow": "تابع" + "title": "حِساباتٍ قَد تُعجِبُك", + "description": "قَد تَرغَب في مُتابَعَةِ هَذِهِ الحِسابات", + "follow": "مُتابَعَة" } }, "searching": { "segment": { - "all": "الكل", + "all": "الكُل", "people": "الأشخاص", - "hashtags": "الوسوم", - "posts": "المنشورات" + "hashtags": "الوُسُوم", + "posts": "المَنشورات" }, "empty_state": { - "no_results": "ليس هناك أية نتيجة" + "no_results": "لا تُوجَدُ نتائِج" }, - "recent_search": "عمليات البحث الأخيرة", + "recent_search": "عَمَليَّاُت البَحثِ الأخيرَة", "clear": "مَحو" } }, "favorite": { - "title": "مفضلتك" + "title": "مُفضَّلَتُك" }, "notification": { "title": { - "Everything": "الكل", + "Everything": "كُلُّ شيء", "Mentions": "الإشارات" }, - "user_followed_you": "يتابعك %s", - "user_favorited your post": "أضاف %s منشورك إلى مفضلته", - "user_reblogged_your_post": "أعاد %s تدوين مشاركتك", - "user_mentioned_you": "أشار إليك %s", - "user_requested_to_follow_you": "طلب %s متابعتك", - "user_your_poll_has_ended": "%s اِنتهى استطلاعُكَ للرأي", + "notification_description": { + "followed_you": "بَدَأ بِمُتابَعَتِك", + "favorited_your_post": "فَضَّلَ مَنشُورَك", + "reblogged_your_post": "أعادَ تَدوينَ مَنشُورَك", + "mentioned_you": "أشارَ إليك", + "request_to_follow_you": "طَلَبَ مُتابَعتَك", + "poll_has_ended": "انتهى استطلاعُ الرأي" + }, "keyobard": { "show_everything": "إظهار كل شيء", "show_mentions": "إظهار الإشارات" @@ -480,60 +510,70 @@ "title": "الإعدادات", "section": { "appearance": { - "title": "المظهر", + "title": "المَظهر", "automatic": "تلقائي", "light": "مضيءٌ دائمًا", "dark": "مظلمٌ دائِمًا" }, + "look_and_feel": { + "title": "المَظهَرُ وَالشُّعُور", + "use_system": "استخدم النِظام", + "really_dark": "مُظلمٌ حَقًّا", + "sorta_dark": "مُظلمٌ نوعًا ما", + "light": "مُضيء" + }, "notifications": { "title": "الإشعارات", - "favorites": "الإعجاب بِمنشوراتي", - "follows": "يتابعني", - "boosts": "إعادة تدوين منشوراتي", - "mentions": "الإشارة لي", + "favorites": "بِالإعْجاب بِمَنشوري", + "follows": "بِمُتابَعَتي", + "boosts": "بِإعادَةِ تدوينِ مَنشوري", + "mentions": "بِالإشارَةِ إليّ", "trigger": { - "anyone": "أي شخص", - "follower": "مشترِك", + "anyone": "أيُّ شخصٍ", + "follower": "مُتابِعٌ", "follow": "أي شخص أُتابِعُه", - "noone": "لا أحد", - "title": "إشعاري عِندَ" + "noone": "لَا أحد", + "title": "أشعِرني عِندما يَقومُ" } }, "preference": { - "title": "التفضيلات", - "true_black_dark_mode": "النمط الأسود الداكِن الحقيقي", - "disable_avatar_animation": "تعطيل الصور الرمزية المتحرِّكة", - "disable_emoji_animation": "تعطيل الرموز التعبيرية المتحرِّكَة", - "using_default_browser": "اِستخدام المتصفح الافتراضي لفتح الروابط" + "title": "التَّفضيلات", + "true_black_dark_mode": "النَّمَطُ الأسوَدُ الداكِنُ الحَقيقي", + "disable_avatar_animation": "تَعطيلُ الصوَرِ الرمزيَّةِ المُتحرِّكَة", + "disable_emoji_animation": "تَعطيلُ الرُموزِ التَّعبيريَّةِ المُتحرِّكَة", + "using_default_browser": "اِستِخدامُ المُتصفِّحِ الاِفتراضي لِفتحِ الرَّوابِط" }, "boring_zone": { - "title": "المنطقة المملة", - "account_settings": "إعدادات الحساب", - "terms": "شروط الخدمة", - "privacy": "سياسة الخصوصية" + "title": "المنطِقَةُ المُملَّة", + "account_settings": "إعداداتُ الحِساب", + "terms": "شُرُوطُ الخِدمَة", + "privacy": "سِياسَةُ الخُصوصيَّة" }, "spicy_zone": { - "title": "المنطقة الحارة", - "clear": "مسح ذاكرة التخزين المؤقت للوسائط", - "signout": "تسجيل الخروج" + "title": "المنطِقَةُ اللَّاذِعَة", + "clear": "مَحوُ ذاكِرَةُ التَّخزينِ المُؤقت لِلوسائِط", + "signout": "تَسجيلُ الخُروج" } }, "footer": { - "mastodon_description": "ماستدون برنامج مفتوح المصدر. يمكنك المساهمة، أو الإبلاغ عن تقارير الأخطاء على GitHub في %s (%s)" + "mastodon_description": "ماستودون بَرنامجٌ مَفتُوحُ المَصدَر. يُمكِنُكَ المُساهَمَةُ، أوِ الإبلاغُ عَنِ المُشكِلات عَن طريق مِنصَّة جيت هاب (GitHub) في %s (%s)" }, "keyboard": { "close_settings_window": "إغلاق نافذة الإعدادات" } }, "report": { - "title": "ابلغ عن %s", - "step1": "الخطوة 1 من 2", - "step2": "الخطوة 2 من 2", - "content1": "هل ترغب في إضافة أي مشاركات أُخرى إلى الشكوى؟", - "content2": "هل هناك أي شيء يجب أن يعرفه المُراقبين حول هذه الشكوى؟", - "send": "إرسال الشكوى", + "title_report": "إبلاغ", + "title": "الإبلاغ عن %s", + "step1": "الخطوة الأولى مِن أصل اثنتين", + "step2": "الخطوة الثانية والأخيرة", + "content1": "هل ترغب في إضافة أي منشورات أُخرى إلى البلاغ؟", + "content2": "هل هناك أي شيء يجب أن يعرفه المُراقبين حول هذا البلاغ؟", + "report_sent_title": "شُكرًا لَكَ على الإبلاغ، سَوفَ نَنظُرُ فِي هَذَا الأمر.", + "send": "إرسال البلاغ", "skip_to_send": "إرسال بدون تعليق", - "text_placeholder": "اكتب أو الصق تعليقات إضافيَّة" + "text_placeholder": "اكتب أو الصق تعليقات إضافيَّة", + "reported": "مُبْلَغٌ عَنه" }, "preview": { "keyboard": { @@ -543,14 +583,14 @@ } }, "account_list": { - "tab_bar_hint": "المِلف المُحدَّد حاليًا: %s. انقر نقرًا مزدوجًا ثم اضغط مع الاستمرار لإظهار مُبدِّل الحِساب", - "dismiss_account_switcher": "تجاهُل مبدِّل الحساب", - "add_account": "إضافة حساب" + "tab_bar_hint": "المِلف المُحدَّد حاليًا: %s. انقر نقرًا مزدوجًا مع الاستمرار لإظهار مُبدِّل الحِساب", + "dismiss_account_switcher": "تجاهُل مبدِّل الحِساب", + "add_account": "إضافَةُ حِساب" }, "wizard": { "new_in_mastodon": "جديد في ماستودون", "multiple_account_switch_intro_description": "بدِّل بين حسابات متعددة عبر الاستمرار بالضغط على زر الملف الشخصي.", - "accessibility_hint": "انقر نقرًا مزدوجًا لتجاهل النافذة المنبثقة" + "accessibility_hint": "انقر نقرًا مزدوجًا لتجاهُل النافذة المنبثقة" } } } \ No newline at end of file diff --git a/Localization/StringsConvertor/input/ca_ES/app.json b/Localization/StringsConvertor/input/ca_ES/app.json index 2ecd587c..c3aac1e5 100644 --- a/Localization/StringsConvertor/input/ca_ES/app.json +++ b/Localization/StringsConvertor/input/ca_ES/app.json @@ -46,7 +46,7 @@ }, "delete_post": { "title": "Estàs segur que vols suprimir aquesta publicació?", - "delete": "Esborra" + "message": "Estàs segur que vols suprimir aquesta publicació?" }, "clean_cache": { "title": "Neteja la memòria cau", @@ -82,6 +82,7 @@ "share_user": "Compartir %s", "share_post": "Compartir Publicació", "open_in_safari": "Obrir a Safari", + "open_in_browser": "Obre al navegador", "find_people": "Busca persones per seguir", "manually_search": "Cerca manualment a canvi", "skip": "Omet", @@ -139,7 +140,8 @@ "unreblog": "Desfer l'impuls", "favorite": "Favorit", "unfavorite": "Desfer Favorit", - "menu": "Menú" + "menu": "Menú", + "hide": "Amaga" }, "tag": { "url": "URL", @@ -148,6 +150,12 @@ "hashtag": "Etiqueta", "email": "Correu electrònic", "emoji": "Emoji" + }, + "visibility": { + "unlisted": "Tothom pot veure aquesta publicació però no es mostra en la línia de temps pública.", + "private": "Només els seus seguidors poden veure aquesta publicació.", + "private_from_me": "Només els meus seguidors poden veure aquesta publicació.", + "direct": "Només l'usuari mencionat pot veure aquesta publicació." } }, "friendship": { @@ -192,10 +200,14 @@ }, "scene": { "welcome": { - "slogan": "Xarxa social\nde nou a les teves mans." + "slogan": "Xarxa social\nde nou a les teves mans.", + "get_started": "Comença", + "log_in": "Inicia sessió" }, "server_picker": { "title": "Tria un servidor,\nqualsevol servidor.", + "subtitle": "Tria una comunitat segons els teus interessos, regió o una de propòsit general.", + "subtitle_extend": "Tria una comunitat segons els teus interessos, regió o una de propòsit general. Cada comunitat és operada per una organització totalment independent o individualment.", "button": { "category": { "all": "Totes", @@ -248,6 +260,12 @@ }, "password": { "placeholder": "contrasenya", + "require": "La teva contrasenya com a mínim necessita:", + "character_limit": "8 caràcters", + "accessibility": { + "checked": "verificat", + "unchecked": "no verificat" + }, "hint": "La teva contrasenya ha de tenir com a mínim buit caràcters" }, "invite": { @@ -298,7 +316,7 @@ "subtitle": "Acabem d'enviar un correu electrònic a %s,\ntoca l'enllaç per a confirmar el teu compte.", "button": { "open_email_app": "Obre l'aplicació de correu", - "dont_receive_email": "No he rebut cap correu electrònic" + "resend": "Reenvia" }, "dont_receive_email": { "title": "Comprova el teu correu", @@ -401,16 +419,26 @@ "segmented_control": { "posts": "Publicacions", "replies": "Respostes", - "media": "Mèdia" + "posts_and_replies": "Publicacions i Respostes", + "media": "Mèdia", + "about": "Quant a" }, "relationship_action_alert": { + "confirm_mute_user": { + "title": "Silencia el Compte", + "message": "Confirma per a silenciar %s" + }, "confirm_unmute_user": { "title": "Desfer silenciar compte", "message": "Confirma deixar de silenciar a %s" }, - "confirm_unblock_usre": { - "title": "Desbloquejar Compte", - "message": "Confirma desbloquejar a %s" + "confirm_block_user": { + "title": "Bloqueja el Compte", + "message": "Confirma per a bloquejar %s" + }, + "confirm_unblock_user": { + "title": "Desbloqueja el Compte", + "message": "Confirma per a desbloquejar %s" } } }, @@ -461,12 +489,14 @@ "Everything": "Tot", "Mentions": "Mencions" }, - "user_followed_you": "%s et segueix", - "user_favorited your post": "%s ha afavorit el teu estat", - "user_reblogged_your_post": "%s ha impulsat el teu estat", - "user_mentioned_you": "%s t'ha esmentat", - "user_requested_to_follow_you": "%s ha sol·licitat seguir-te", - "user_your_poll_has_ended": "%s L'enquesta ha finalitzat", + "notification_description": { + "followed_you": "et segueix", + "favorited_your_post": "ha afavorit la teva publicació", + "reblogged_your_post": "ha impulsat la teva publicació", + "mentioned_you": "t'ha mencionat", + "request_to_follow_you": "ha sol·licitat seguir-te", + "poll_has_ended": "la enquesta ha finalitzat" + }, "keyobard": { "show_everything": "Mostrar-ho tot", "show_mentions": "Mostrar Mencions" @@ -485,6 +515,13 @@ "light": "Sempre Clara", "dark": "Sempre Fosca" }, + "look_and_feel": { + "title": "Aspecte i Comportament", + "use_system": "Usa el del Sistema", + "really_dark": "Realment Negre", + "sorta_dark": "Una Mena de Fosc", + "light": "Clar" + }, "notifications": { "title": "Notificacions", "favorites": "Ha afavorit el meu estat", @@ -526,14 +563,17 @@ } }, "report": { + "title_report": "Informe", "title": "Informa sobre %s", "step1": "Pas 1 de 2", "step2": "Pas 2 de 2", "content1": "Hi ha alguna altre publicació que vulguis afegir a l'informe?", "content2": "Hi ha alguna cosa que els moderadors hagin de saber sobre aquest informe?", + "report_sent_title": "Gràcies per informar, ho investigarem.", "send": "Envia Informe", "skip_to_send": "Envia sense comentaris", - "text_placeholder": "Escriu o enganxa comentaris addicionals" + "text_placeholder": "Escriu o enganxa comentaris addicionals", + "reported": "REPORTAT" }, "preview": { "keyboard": { diff --git a/Localization/StringsConvertor/input/cy_GB/app.json b/Localization/StringsConvertor/input/cy_GB/app.json index 5c01ae7e..ad99e178 100644 --- a/Localization/StringsConvertor/input/cy_GB/app.json +++ b/Localization/StringsConvertor/input/cy_GB/app.json @@ -45,8 +45,8 @@ "message": "Please enable the photo library access permission to save the photo." }, "delete_post": { - "title": "Are you sure you want to delete this post?", - "delete": "Delete" + "title": "Delete Post", + "message": "Are you sure you want to delete this post?" }, "clean_cache": { "title": "Clean Cache", @@ -82,6 +82,7 @@ "share_user": "Share %s", "share_post": "Share Post", "open_in_safari": "Open in Safari", + "open_in_browser": "Open in Browser", "find_people": "Find people to follow", "manually_search": "Manually search instead", "skip": "Skip", @@ -139,7 +140,8 @@ "unreblog": "Undo reblog", "favorite": "Favorite", "unfavorite": "Unfavorite", - "menu": "Menu" + "menu": "Menu", + "hide": "Hide" }, "tag": { "url": "URL", @@ -148,6 +150,12 @@ "hashtag": "Hashtag", "email": "Email", "emoji": "Emoji" + }, + "visibility": { + "unlisted": "Everyone can see this post but not display in the public timeline.", + "private": "Only their followers can see this post.", + "private_from_me": "Only my followers can see this post.", + "direct": "Only mentioned user can see this post." } }, "friendship": { @@ -192,10 +200,14 @@ }, "scene": { "welcome": { - "slogan": "Social networking\nback in your hands." + "slogan": "Social networking\nback in your hands.", + "get_started": "Get Started", + "log_in": "Log In" }, "server_picker": { - "title": "Pick a server,\nany server.", + "title": "Mastodon is made of users in different communities.", + "subtitle": "Pick a community based on your interests, region, or a general purpose one.", + "subtitle_extend": "Pick a community based on your interests, region, or a general purpose one. Each community is operated by an entirely independent organization or individual.", "button": { "category": { "all": "All", @@ -222,7 +234,7 @@ "category": "CATEGORY" }, "input": { - "placeholder": "Find a server or join your own..." + "placeholder": "Search communities" }, "empty_state": { "finding_servers": "Finding available servers...", @@ -231,7 +243,7 @@ } }, "register": { - "title": "Tell us about you.", + "title": "Let’s get you set up on %s", "input": { "avatar": { "delete": "Delete" @@ -248,6 +260,12 @@ }, "password": { "placeholder": "password", + "require": "Your password needs at least:", + "character_limit": "8 characters", + "accessibility": { + "checked": "checked", + "unchecked": "unchecked" + }, "hint": "Your password needs at least eight characters" }, "invite": { @@ -285,7 +303,7 @@ }, "server_rules": { "title": "Some ground rules.", - "subtitle": "These rules are set by the admins of %s.", + "subtitle": "These are set and enforced by the %s moderators.", "prompt": "By continuing, you’re subject to the terms of service and privacy policy for %s.", "terms_of_service": "terms of service", "privacy_policy": "privacy policy", @@ -295,10 +313,10 @@ }, "confirm_email": { "title": "One last thing.", - "subtitle": "We just sent an email to %s,\ntap the link to confirm your account.", + "subtitle": "Tap the link we emailed to you to verify your account.", "button": { "open_email_app": "Open Email App", - "dont_receive_email": "I never got an email" + "resend": "Resend" }, "dont_receive_email": { "title": "Check your email", @@ -401,14 +419,24 @@ "segmented_control": { "posts": "Posts", "replies": "Replies", - "media": "Media" + "posts_and_replies": "Posts and Replies", + "media": "Media", + "about": "About" }, "relationship_action_alert": { + "confirm_mute_user": { + "title": "Mute Account", + "message": "Confirm to mute %s" + }, "confirm_unmute_user": { "title": "Unmute Account", "message": "Confirm to unmute %s" }, - "confirm_unblock_usre": { + "confirm_block_user": { + "title": "Block Account", + "message": "Confirm to block %s" + }, + "confirm_unblock_user": { "title": "Unblock Account", "message": "Confirm to unblock %s" } @@ -461,12 +489,14 @@ "Everything": "Everything", "Mentions": "Mentions" }, - "user_followed_you": "%s followed you", - "user_favorited your post": "%s favorited your post", - "user_reblogged_your_post": "%s reblogged your post", - "user_mentioned_you": "%s mentioned you", - "user_requested_to_follow_you": "%s requested to follow you", - "user_your_poll_has_ended": "%s Your poll has ended", + "notification_description": { + "followed_you": "followed you", + "favorited_your_post": "favorited your post", + "reblogged_your_post": "reblogged your post", + "mentioned_you": "mentioned you", + "request_to_follow_you": "request to follow you", + "poll_has_ended": "poll has ended" + }, "keyobard": { "show_everything": "Show Everything", "show_mentions": "Show Mentions" @@ -485,6 +515,13 @@ "light": "Always Light", "dark": "Always Dark" }, + "look_and_feel": { + "title": "Look and Feel", + "use_system": "Use System", + "really_dark": "Really Dark", + "sorta_dark": "Sorta Dark", + "light": "Light" + }, "notifications": { "title": "Notifications", "favorites": "Favorites my post", @@ -526,14 +563,17 @@ } }, "report": { + "title_report": "Report", "title": "Report %s", "step1": "Step 1 of 2", "step2": "Step 2 of 2", "content1": "Are there any other posts you’d like to add to the report?", "content2": "Is there anything the moderators should know about this report?", + "report_sent_title": "Thanks for reporting, we’ll look into this.", "send": "Send Report", "skip_to_send": "Send without comment", - "text_placeholder": "Type or paste additional comments" + "text_placeholder": "Type or paste additional comments", + "reported": "REPORTED" }, "preview": { "keyboard": { diff --git a/Localization/StringsConvertor/input/da_DK/app.json b/Localization/StringsConvertor/input/da_DK/app.json index 5c01ae7e..ad99e178 100644 --- a/Localization/StringsConvertor/input/da_DK/app.json +++ b/Localization/StringsConvertor/input/da_DK/app.json @@ -45,8 +45,8 @@ "message": "Please enable the photo library access permission to save the photo." }, "delete_post": { - "title": "Are you sure you want to delete this post?", - "delete": "Delete" + "title": "Delete Post", + "message": "Are you sure you want to delete this post?" }, "clean_cache": { "title": "Clean Cache", @@ -82,6 +82,7 @@ "share_user": "Share %s", "share_post": "Share Post", "open_in_safari": "Open in Safari", + "open_in_browser": "Open in Browser", "find_people": "Find people to follow", "manually_search": "Manually search instead", "skip": "Skip", @@ -139,7 +140,8 @@ "unreblog": "Undo reblog", "favorite": "Favorite", "unfavorite": "Unfavorite", - "menu": "Menu" + "menu": "Menu", + "hide": "Hide" }, "tag": { "url": "URL", @@ -148,6 +150,12 @@ "hashtag": "Hashtag", "email": "Email", "emoji": "Emoji" + }, + "visibility": { + "unlisted": "Everyone can see this post but not display in the public timeline.", + "private": "Only their followers can see this post.", + "private_from_me": "Only my followers can see this post.", + "direct": "Only mentioned user can see this post." } }, "friendship": { @@ -192,10 +200,14 @@ }, "scene": { "welcome": { - "slogan": "Social networking\nback in your hands." + "slogan": "Social networking\nback in your hands.", + "get_started": "Get Started", + "log_in": "Log In" }, "server_picker": { - "title": "Pick a server,\nany server.", + "title": "Mastodon is made of users in different communities.", + "subtitle": "Pick a community based on your interests, region, or a general purpose one.", + "subtitle_extend": "Pick a community based on your interests, region, or a general purpose one. Each community is operated by an entirely independent organization or individual.", "button": { "category": { "all": "All", @@ -222,7 +234,7 @@ "category": "CATEGORY" }, "input": { - "placeholder": "Find a server or join your own..." + "placeholder": "Search communities" }, "empty_state": { "finding_servers": "Finding available servers...", @@ -231,7 +243,7 @@ } }, "register": { - "title": "Tell us about you.", + "title": "Let’s get you set up on %s", "input": { "avatar": { "delete": "Delete" @@ -248,6 +260,12 @@ }, "password": { "placeholder": "password", + "require": "Your password needs at least:", + "character_limit": "8 characters", + "accessibility": { + "checked": "checked", + "unchecked": "unchecked" + }, "hint": "Your password needs at least eight characters" }, "invite": { @@ -285,7 +303,7 @@ }, "server_rules": { "title": "Some ground rules.", - "subtitle": "These rules are set by the admins of %s.", + "subtitle": "These are set and enforced by the %s moderators.", "prompt": "By continuing, you’re subject to the terms of service and privacy policy for %s.", "terms_of_service": "terms of service", "privacy_policy": "privacy policy", @@ -295,10 +313,10 @@ }, "confirm_email": { "title": "One last thing.", - "subtitle": "We just sent an email to %s,\ntap the link to confirm your account.", + "subtitle": "Tap the link we emailed to you to verify your account.", "button": { "open_email_app": "Open Email App", - "dont_receive_email": "I never got an email" + "resend": "Resend" }, "dont_receive_email": { "title": "Check your email", @@ -401,14 +419,24 @@ "segmented_control": { "posts": "Posts", "replies": "Replies", - "media": "Media" + "posts_and_replies": "Posts and Replies", + "media": "Media", + "about": "About" }, "relationship_action_alert": { + "confirm_mute_user": { + "title": "Mute Account", + "message": "Confirm to mute %s" + }, "confirm_unmute_user": { "title": "Unmute Account", "message": "Confirm to unmute %s" }, - "confirm_unblock_usre": { + "confirm_block_user": { + "title": "Block Account", + "message": "Confirm to block %s" + }, + "confirm_unblock_user": { "title": "Unblock Account", "message": "Confirm to unblock %s" } @@ -461,12 +489,14 @@ "Everything": "Everything", "Mentions": "Mentions" }, - "user_followed_you": "%s followed you", - "user_favorited your post": "%s favorited your post", - "user_reblogged_your_post": "%s reblogged your post", - "user_mentioned_you": "%s mentioned you", - "user_requested_to_follow_you": "%s requested to follow you", - "user_your_poll_has_ended": "%s Your poll has ended", + "notification_description": { + "followed_you": "followed you", + "favorited_your_post": "favorited your post", + "reblogged_your_post": "reblogged your post", + "mentioned_you": "mentioned you", + "request_to_follow_you": "request to follow you", + "poll_has_ended": "poll has ended" + }, "keyobard": { "show_everything": "Show Everything", "show_mentions": "Show Mentions" @@ -485,6 +515,13 @@ "light": "Always Light", "dark": "Always Dark" }, + "look_and_feel": { + "title": "Look and Feel", + "use_system": "Use System", + "really_dark": "Really Dark", + "sorta_dark": "Sorta Dark", + "light": "Light" + }, "notifications": { "title": "Notifications", "favorites": "Favorites my post", @@ -526,14 +563,17 @@ } }, "report": { + "title_report": "Report", "title": "Report %s", "step1": "Step 1 of 2", "step2": "Step 2 of 2", "content1": "Are there any other posts you’d like to add to the report?", "content2": "Is there anything the moderators should know about this report?", + "report_sent_title": "Thanks for reporting, we’ll look into this.", "send": "Send Report", "skip_to_send": "Send without comment", - "text_placeholder": "Type or paste additional comments" + "text_placeholder": "Type or paste additional comments", + "reported": "REPORTED" }, "preview": { "keyboard": { diff --git a/Localization/StringsConvertor/input/de_DE/app.json b/Localization/StringsConvertor/input/de_DE/app.json index dc8cdf8c..f62f9f95 100644 --- a/Localization/StringsConvertor/input/de_DE/app.json +++ b/Localization/StringsConvertor/input/de_DE/app.json @@ -46,7 +46,7 @@ }, "delete_post": { "title": "Bist du dir sicher, dass du diesen Beitrag löschen möchtest?", - "delete": "Löschen" + "message": "Bist du dir sicher, dass du diesen Beitrag löschen willst?" }, "clean_cache": { "title": "Zwischenspeicher leeren", @@ -67,7 +67,7 @@ "done": "Fertig", "confirm": "Bestätigen", "continue": "Fortfahren", - "compose": "Compose", + "compose": "Neue Nachricht", "cancel": "Abbrechen", "discard": "Verwerfen", "try_again": "Nochmals versuchen", @@ -82,6 +82,7 @@ "share_user": "%s teilen", "share_post": "Beitrag teilen", "open_in_safari": "In Safari öffnen", + "open_in_browser": "Im Browser anzeigen", "find_people": "Finde Personen zum Folgen", "manually_search": "Stattdessen manuell suchen", "skip": "Überspringen", @@ -139,7 +140,8 @@ "unreblog": "Nicht mehr teilen", "favorite": "Favorit", "unfavorite": "Aus Favoriten entfernen", - "menu": "Menü" + "menu": "Menü", + "hide": "Verstecken" }, "tag": { "url": "URL", @@ -148,6 +150,12 @@ "hashtag": "Hashtag", "email": "E-Mail", "emoji": "Emoji" + }, + "visibility": { + "unlisted": "Jeder kann diesen Post sehen, aber nicht in der öffentlichen Timeline zeigen.", + "private": "Nur Follower des Authors können diesen Beitrag sehen.", + "private_from_me": "Nur meine Follower können diesen Beitrag sehen.", + "direct": "Nur erwähnte Benutzer können diesen Beitrag sehen." } }, "friendship": { @@ -192,10 +200,14 @@ }, "scene": { "welcome": { - "slogan": "Soziale Netzwerke wieder in deinen Händen." + "slogan": "Soziale Netzwerke wieder in deinen Händen.", + "get_started": "Erste Schritte", + "log_in": "Anmelden" }, "server_picker": { "title": "Wähle einen Server,\nbeliebigen Server.", + "subtitle": "Wähle eine Gemeinschaft, die auf deinen Interessen, Region oder einem allgemeinen Zweck basiert.", + "subtitle_extend": "Wähle eine Gemeinschaft basierend auf deinen Interessen, deiner Region oder einem allgemeinen Zweck. Jede Gemeinschaft wird von einer völlig unabhängigen Organisation oder Einzelperson betrieben.", "button": { "category": { "all": "Alle", @@ -248,6 +260,12 @@ }, "password": { "placeholder": "Passwort", + "require": "Anforderungen an dein Passwort:", + "character_limit": "8 Zeichen", + "accessibility": { + "checked": "Häkchen gesetzt", + "unchecked": "Häkchen entfernt" + }, "hint": "Ihr Passwort muss mindestens 8 Zeichen lang sein" }, "invite": { @@ -298,7 +316,7 @@ "subtitle": "Wir haben gerade eine E-Mail an %s gesendet,\ntippe darin auf den Link, um Dein Konto zu bestätigen.", "button": { "open_email_app": "E-Mail-App öffnen", - "dont_receive_email": "Ich habe keine E-Mail erhalten." + "resend": "Erneut senden" }, "dont_receive_email": { "title": "Bitte überprüfe deine E-Mails", @@ -401,24 +419,34 @@ "segmented_control": { "posts": "Beiträge", "replies": "Antworten", - "media": "Medien" + "posts_and_replies": "Beiträge und Antworten", + "media": "Medien", + "about": "Über" }, "relationship_action_alert": { + "confirm_mute_user": { + "title": "Konto stummschalten", + "message": "Bestätige %s stumm zu schalten" + }, "confirm_unmute_user": { "title": "Ton einschalten", "message": "Bestätige um %s nicht mehr stummzuschalten" }, - "confirm_unblock_usre": { + "confirm_block_user": { + "title": "Konto blockieren", + "message": "Bestätige %s zu blockieren" + }, + "confirm_unblock_user": { "title": "Konto entsperren", - "message": "Bestätigen zum Entsperren von %s" + "message": "Bestätige %s zu entsperren" } } }, "follower": { - "footer": "Followers from other servers are not displayed." + "footer": "Follower von anderen Servern werden nicht angezeigt." }, "following": { - "footer": "Follows from other servers are not displayed." + "footer": "Wem das Konto folgt wird von anderen Servern werden nicht angezeigt." }, "search": { "title": "Suche", @@ -461,12 +489,14 @@ "Everything": "Alles", "Mentions": "Erwähnungen" }, - "user_followed_you": "%s folgte dir", - "user_favorited your post": "%s favorisierte deinen Beitrag", - "user_reblogged_your_post": "%s teilte deinen Beitrag", - "user_mentioned_you": "%s erwähnte dich", - "user_requested_to_follow_you": "%s beantragte dir zu folgen", - "user_your_poll_has_ended": "%s deine Umfrage ist beendet", + "notification_description": { + "followed_you": "folgt dir", + "favorited_your_post": "hat deinen Beitrag favorisiert", + "reblogged_your_post": "hat deinen Beitrag geteilt", + "mentioned_you": "hat dich erwähnt", + "request_to_follow_you": "Folgeanfrage", + "poll_has_ended": "Umfrage wurde beendet" + }, "keyobard": { "show_everything": "Alles anzeigen", "show_mentions": "Erwähnungen anzeigen" @@ -485,6 +515,13 @@ "light": "Immer hell", "dark": "Immer dunkel" }, + "look_and_feel": { + "title": "Erscheinungsbild", + "use_system": "Systemeinstellung benutzen", + "really_dark": "Wirklich dunkel", + "sorta_dark": "Ziemlich dunkel", + "light": "Hell" + }, "notifications": { "title": "Benachrichtigungen", "favorites": "Meinen Beitrag favorisiert", @@ -507,7 +544,7 @@ "using_default_browser": "Standardbrowser zum Öffnen von Links verwenden" }, "boring_zone": { - "title": "Der Langweiliger Bereich", + "title": "Der langweilige Bereich", "account_settings": "Kontoeinstellungen", "terms": "Allgemeine Geschäftsbedingungen", "privacy": "Datenschutzerklärung" @@ -526,14 +563,17 @@ } }, "report": { + "title_report": "Melden", "title": "%s melden", "step1": "Schritt 1 von 2", "step2": "Schritt 2 von 2", "content1": "Gibt es noch weitere Beiträge, die du der Meldung hinzufügen möchtest?", "content2": "Gibt es etwas, was die Moderatoren über diese Meldung wissen sollten?", + "report_sent_title": "Danke für deine Meldung, wir werden uns damit beschäftigen.", "send": "Meldung abschicken", "skip_to_send": "Ohne Kommentar abschicken", - "text_placeholder": "Zusätzliche Kommentare eingeben oder einfügen" + "text_placeholder": "Zusätzliche Kommentare eingeben oder einfügen", + "reported": "GEMELDET" }, "preview": { "keyboard": { @@ -544,7 +584,7 @@ }, "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", + "dismiss_account_switcher": "Dialog zum Wechseln des Kontos schließen", "add_account": "Konto hinzufügen" }, "wizard": { diff --git a/Localization/StringsConvertor/input/en_US/app.json b/Localization/StringsConvertor/input/en_US/app.json index 5c01ae7e..ad99e178 100644 --- a/Localization/StringsConvertor/input/en_US/app.json +++ b/Localization/StringsConvertor/input/en_US/app.json @@ -45,8 +45,8 @@ "message": "Please enable the photo library access permission to save the photo." }, "delete_post": { - "title": "Are you sure you want to delete this post?", - "delete": "Delete" + "title": "Delete Post", + "message": "Are you sure you want to delete this post?" }, "clean_cache": { "title": "Clean Cache", @@ -82,6 +82,7 @@ "share_user": "Share %s", "share_post": "Share Post", "open_in_safari": "Open in Safari", + "open_in_browser": "Open in Browser", "find_people": "Find people to follow", "manually_search": "Manually search instead", "skip": "Skip", @@ -139,7 +140,8 @@ "unreblog": "Undo reblog", "favorite": "Favorite", "unfavorite": "Unfavorite", - "menu": "Menu" + "menu": "Menu", + "hide": "Hide" }, "tag": { "url": "URL", @@ -148,6 +150,12 @@ "hashtag": "Hashtag", "email": "Email", "emoji": "Emoji" + }, + "visibility": { + "unlisted": "Everyone can see this post but not display in the public timeline.", + "private": "Only their followers can see this post.", + "private_from_me": "Only my followers can see this post.", + "direct": "Only mentioned user can see this post." } }, "friendship": { @@ -192,10 +200,14 @@ }, "scene": { "welcome": { - "slogan": "Social networking\nback in your hands." + "slogan": "Social networking\nback in your hands.", + "get_started": "Get Started", + "log_in": "Log In" }, "server_picker": { - "title": "Pick a server,\nany server.", + "title": "Mastodon is made of users in different communities.", + "subtitle": "Pick a community based on your interests, region, or a general purpose one.", + "subtitle_extend": "Pick a community based on your interests, region, or a general purpose one. Each community is operated by an entirely independent organization or individual.", "button": { "category": { "all": "All", @@ -222,7 +234,7 @@ "category": "CATEGORY" }, "input": { - "placeholder": "Find a server or join your own..." + "placeholder": "Search communities" }, "empty_state": { "finding_servers": "Finding available servers...", @@ -231,7 +243,7 @@ } }, "register": { - "title": "Tell us about you.", + "title": "Let’s get you set up on %s", "input": { "avatar": { "delete": "Delete" @@ -248,6 +260,12 @@ }, "password": { "placeholder": "password", + "require": "Your password needs at least:", + "character_limit": "8 characters", + "accessibility": { + "checked": "checked", + "unchecked": "unchecked" + }, "hint": "Your password needs at least eight characters" }, "invite": { @@ -285,7 +303,7 @@ }, "server_rules": { "title": "Some ground rules.", - "subtitle": "These rules are set by the admins of %s.", + "subtitle": "These are set and enforced by the %s moderators.", "prompt": "By continuing, you’re subject to the terms of service and privacy policy for %s.", "terms_of_service": "terms of service", "privacy_policy": "privacy policy", @@ -295,10 +313,10 @@ }, "confirm_email": { "title": "One last thing.", - "subtitle": "We just sent an email to %s,\ntap the link to confirm your account.", + "subtitle": "Tap the link we emailed to you to verify your account.", "button": { "open_email_app": "Open Email App", - "dont_receive_email": "I never got an email" + "resend": "Resend" }, "dont_receive_email": { "title": "Check your email", @@ -401,14 +419,24 @@ "segmented_control": { "posts": "Posts", "replies": "Replies", - "media": "Media" + "posts_and_replies": "Posts and Replies", + "media": "Media", + "about": "About" }, "relationship_action_alert": { + "confirm_mute_user": { + "title": "Mute Account", + "message": "Confirm to mute %s" + }, "confirm_unmute_user": { "title": "Unmute Account", "message": "Confirm to unmute %s" }, - "confirm_unblock_usre": { + "confirm_block_user": { + "title": "Block Account", + "message": "Confirm to block %s" + }, + "confirm_unblock_user": { "title": "Unblock Account", "message": "Confirm to unblock %s" } @@ -461,12 +489,14 @@ "Everything": "Everything", "Mentions": "Mentions" }, - "user_followed_you": "%s followed you", - "user_favorited your post": "%s favorited your post", - "user_reblogged_your_post": "%s reblogged your post", - "user_mentioned_you": "%s mentioned you", - "user_requested_to_follow_you": "%s requested to follow you", - "user_your_poll_has_ended": "%s Your poll has ended", + "notification_description": { + "followed_you": "followed you", + "favorited_your_post": "favorited your post", + "reblogged_your_post": "reblogged your post", + "mentioned_you": "mentioned you", + "request_to_follow_you": "request to follow you", + "poll_has_ended": "poll has ended" + }, "keyobard": { "show_everything": "Show Everything", "show_mentions": "Show Mentions" @@ -485,6 +515,13 @@ "light": "Always Light", "dark": "Always Dark" }, + "look_and_feel": { + "title": "Look and Feel", + "use_system": "Use System", + "really_dark": "Really Dark", + "sorta_dark": "Sorta Dark", + "light": "Light" + }, "notifications": { "title": "Notifications", "favorites": "Favorites my post", @@ -526,14 +563,17 @@ } }, "report": { + "title_report": "Report", "title": "Report %s", "step1": "Step 1 of 2", "step2": "Step 2 of 2", "content1": "Are there any other posts you’d like to add to the report?", "content2": "Is there anything the moderators should know about this report?", + "report_sent_title": "Thanks for reporting, we’ll look into this.", "send": "Send Report", "skip_to_send": "Send without comment", - "text_placeholder": "Type or paste additional comments" + "text_placeholder": "Type or paste additional comments", + "reported": "REPORTED" }, "preview": { "keyboard": { diff --git a/Localization/StringsConvertor/input/es_AR/app.json b/Localization/StringsConvertor/input/es_AR/app.json index ed909ecf..106ffb64 100644 --- a/Localization/StringsConvertor/input/es_AR/app.json +++ b/Localization/StringsConvertor/input/es_AR/app.json @@ -46,7 +46,7 @@ }, "delete_post": { "title": "¿Estás seguro que querés eliminar este mensaje?", - "delete": "Eliminar" + "message": "¿Estás seguro que querés eliminar este mensaje?" }, "clean_cache": { "title": "Limpiar caché", @@ -82,6 +82,7 @@ "share_user": "Compartir %s", "share_post": "Compartir mensaje", "open_in_safari": "Abrir en Safari", + "open_in_browser": "Abrir en el navegador", "find_people": "Encontrá cuentas para seguir", "manually_search": "Buscar manualmente", "skip": "Omitir", @@ -139,7 +140,8 @@ "unreblog": "Deshacer adhesión", "favorite": "Marcar como favorito", "unfavorite": "Dejar de marcar como favorito", - "menu": "Menú" + "menu": "Menú", + "hide": "Ocultar" }, "tag": { "url": "Dirección web", @@ -148,6 +150,12 @@ "hashtag": "Etiqueta", "email": "Correo electrónico", "emoji": "Emoji" + }, + "visibility": { + "unlisted": "Todo el mundo puede ver este mensaje pero no mostrarse en la línea temporal pública.", + "private": "Sólo sus seguidores pueden ver este mensaje.", + "private_from_me": "Sólo mis seguidores pueden ver este mensaje.", + "direct": "Sólo el usuario mencionado puede ver este mensaje." } }, "friendship": { @@ -192,10 +200,14 @@ }, "scene": { "welcome": { - "slogan": "La red social,\nnuevamente en tu poder." + "slogan": "La red social,\nnuevamente en tu poder.", + "get_started": "Comenzá", + "log_in": "Iniciar sesión" }, "server_picker": { "title": "Elegí un servidor,\nel que quieras.", + "subtitle": "Elegí una comunidad basada en tus intereses, región o una de propósitos generales.", + "subtitle_extend": "Elegí una comunidad basada en tus intereses, región o una de propósitos generales. Cada comunidad es operada por una organización o individuo totalmente independiente.", "button": { "category": { "all": "Todas", @@ -248,6 +260,12 @@ }, "password": { "placeholder": "contraseña", + "require": "Tu contraseña necesita al menos:", + "character_limit": "8 caracteres", + "accessibility": { + "checked": "marcado", + "unchecked": "sin marcar" + }, "hint": "Tu contraseña necesita al menos ocho caracteres" }, "invite": { @@ -298,7 +316,7 @@ "subtitle": "Acabamos de enviar un correo electrónico a %s,\npulsá en el enlace para confirmar tu cuenta.", "button": { "open_email_app": "Abrir aplicación de correo electrónico", - "dont_receive_email": "Nunca recibí un correo electrónico" + "resend": "Reenviar" }, "dont_receive_email": { "title": "Revisá tu correo electrónico", @@ -401,14 +419,24 @@ "segmented_control": { "posts": "Mensajes", "replies": "Respuestas", - "media": "Medios" + "posts_and_replies": "Mensajes y respuestas", + "media": "Medios", + "about": "Información" }, "relationship_action_alert": { + "confirm_mute_user": { + "title": "Silenciar cuenta", + "message": "Confirmá para silenciar a %s" + }, "confirm_unmute_user": { "title": "Dejar de silenciar cuenta", "message": "Confirmá para dejar de silenciar a %s" }, - "confirm_unblock_usre": { + "confirm_block_user": { + "title": "Bloquear cuenta", + "message": "Confirmá para desbloquear a %s" + }, + "confirm_unblock_user": { "title": "Desbloquear cuenta", "message": "Confirmá para desbloquear a %s" } @@ -461,12 +489,14 @@ "Everything": "Todo", "Mentions": "Menciones" }, - "user_followed_you": "%s te sigue", - "user_favorited your post": "%s marcó tu msj. como favorito", - "user_reblogged_your_post": "%s adhirió a tu mensaje", - "user_mentioned_you": "%s te mencionó", - "user_requested_to_follow_you": "%s solicitó seguirte", - "user_your_poll_has_ended": "%s, tu encuesta finalizó", + "notification_description": { + "followed_you": "te sigue", + "favorited_your_post": "marcó como favorito tu mensaje", + "reblogged_your_post": "adhirió a tu mensaje", + "mentioned_you": "te mencionó", + "request_to_follow_you": "solicitó seguirte", + "poll_has_ended": "la encuesta terminó" + }, "keyobard": { "show_everything": "Mostrar todo", "show_mentions": "Mostrar menciones" @@ -485,6 +515,13 @@ "light": "Siempre clara", "dark": "Siempre oscura" }, + "look_and_feel": { + "title": "Apariencia", + "use_system": "Usar sistema", + "really_dark": "Oscuro de verdad", + "sorta_dark": "Algo oscuro", + "light": "Claro" + }, "notifications": { "title": "Notificaciones", "favorites": "Marcó como favorito mi mensaje", @@ -526,14 +563,17 @@ } }, "report": { + "title_report": "Denunciar", "title": "Denunciar a %s", "step1": "Paso 1 de 2", "step2": "Paso 2 de 2", "content1": "¿Hay otros mensajes que te gustaría agregar a la denuncia?", "content2": "¿Hay algo que los moderadores deban saber sobre esta denuncia?", + "report_sent_title": "Gracias por tu denuncia, vamos a revisarla.", "send": "Enviar denuncia", "skip_to_send": "Enviar sin comentarios", - "text_placeholder": "Escribí o pegá comentarios adicionales" + "text_placeholder": "Escribí o pegá comentarios adicionales", + "reported": "DENUNCIADA" }, "preview": { "keyboard": { diff --git a/Localization/StringsConvertor/input/es_ES/Localizable.stringsdict b/Localization/StringsConvertor/input/es_ES/Localizable.stringsdict index d31d8825..186218af 100644 --- a/Localization/StringsConvertor/input/es_ES/Localizable.stringsdict +++ b/Localization/StringsConvertor/input/es_ES/Localizable.stringsdict @@ -13,9 +13,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 unread notification</string> + <string>1 notificación no leída</string> <key>other</key> - <string>%ld unread notification</string> + <string>%ld notificaciones no leídas</string> </dict> </dict> <key>a11y.plural.count.input_limit_exceeds</key> diff --git a/Localization/StringsConvertor/input/es_ES/app.json b/Localization/StringsConvertor/input/es_ES/app.json index 72967c40..cfebae26 100644 --- a/Localization/StringsConvertor/input/es_ES/app.json +++ b/Localization/StringsConvertor/input/es_ES/app.json @@ -46,7 +46,7 @@ }, "delete_post": { "title": "¿Estás seguro de que deseas eliminar esta publicación?", - "delete": "Eliminar" + "message": "¿Estás seguro de que quieres borrar esta publicación?" }, "clean_cache": { "title": "Limpiar Caché", @@ -82,6 +82,7 @@ "share_user": "Compartir %s", "share_post": "Compartir publicación", "open_in_safari": "Abrir en Safari", + "open_in_browser": "Abrir en el navegador", "find_people": "Encuentra gente a la que seguir", "manually_search": "Mejor hacer una búsqueda manual", "skip": "Omitir", @@ -139,7 +140,8 @@ "unreblog": "Deshacer reblogueo", "favorite": "Favorito", "unfavorite": "No favorito", - "menu": "Menú" + "menu": "Menú", + "hide": "Ocultar" }, "tag": { "url": "URL", @@ -148,6 +150,12 @@ "hashtag": "Etiqueta", "email": "E-mail", "emoji": "Emoji" + }, + "visibility": { + "unlisted": "Todo el mundo puede ver este post pero no mostrar en la línea de tiempo pública.", + "private": "Sólo sus seguidores pueden ver este mensaje.", + "private_from_me": "Sólo mis seguidores pueden ver este mensaje.", + "direct": "Sólo el usuario mencionado puede ver este mensaje." } }, "friendship": { @@ -192,10 +200,14 @@ }, "scene": { "welcome": { - "slogan": "Las redes sociales\nde nuevo en tus manos." + "slogan": "Las redes sociales\nde nuevo en tus manos.", + "get_started": "Empezar", + "log_in": "Iniciar sesión" }, "server_picker": { "title": "Elige un servidor,\ncualquier servidor.", + "subtitle": "Elige una comunidad relacionada con tus intereses, con tu región o una más genérica.", + "subtitle_extend": "Elige una comunidad relacionada con tus intereses, con tu región o una más genérica. Cada comunidad está operada por una organización o individuo completamente independiente.", "button": { "category": { "all": "Todas", @@ -248,6 +260,12 @@ }, "password": { "placeholder": "contraseña", + "require": "Tu contraseña debe contener como mínimo:", + "character_limit": "8 caracteres", + "accessibility": { + "checked": "marcado", + "unchecked": "sin marcar" + }, "hint": "Tu contraseña necesita tener al menos ocho caracteres" }, "invite": { @@ -298,7 +316,7 @@ "subtitle": "Te acabamos de enviar un correo a %s,\npulsa en el enlace para confirmar tu cuenta.", "button": { "open_email_app": "Abrir Aplicación de Correo Electrónico", - "dont_receive_email": "No he recibido el correo electrónico" + "resend": "Reenviar" }, "dont_receive_email": { "title": "Revisa tu correo electrónico", @@ -401,15 +419,25 @@ "segmented_control": { "posts": "Publicaciones", "replies": "Respuestas", - "media": "Multimedia" + "posts_and_replies": "Publicaciones y respuestas", + "media": "Multimedia", + "about": "Acerca de" }, "relationship_action_alert": { + "confirm_mute_user": { + "title": "Silenciar cuenta", + "message": "Confirmar para silenciar %s" + }, "confirm_unmute_user": { "title": "Dejar de Silenciar Cuenta", "message": "Confirmar para dejar de silenciar a %s" }, - "confirm_unblock_usre": { - "title": "Desbloquear Cuenta", + "confirm_block_user": { + "title": "Bloquear cuenta", + "message": "Confirmar para bloquear a %s" + }, + "confirm_unblock_user": { + "title": "Desbloquear cuenta", "message": "Confirmar para desbloquear a %s" } } @@ -461,12 +489,14 @@ "Everything": "Todo", "Mentions": "Menciones" }, - "user_followed_you": "%s te ha empezado a seguir", - "user_favorited your post": "%s marcó tu post como favorito", - "user_reblogged_your_post": "%s reblogueó tu publicación", - "user_mentioned_you": "%s te ha mencionado", - "user_requested_to_follow_you": "%s ha solicitado seguirte", - "user_your_poll_has_ended": "%s Tu encuesta ha terminado", + "notification_description": { + "followed_you": "te siguió", + "favorited_your_post": "ha marcado como favorita tu publicación", + "reblogged_your_post": "reblogueó tu publicación", + "mentioned_you": "te mencionó", + "request_to_follow_you": "solicitó seguirte", + "poll_has_ended": "encuesta ha terminado" + }, "keyobard": { "show_everything": "Mostrar Todo", "show_mentions": "Mostrar Menciones" @@ -485,6 +515,13 @@ "light": "Siempre Clara", "dark": "Siempre Oscura" }, + "look_and_feel": { + "title": "Apariencia", + "use_system": "Uso del sistema", + "really_dark": "Realmente Oscuro", + "sorta_dark": "Más o Menos Oscuro", + "light": "Claro" + }, "notifications": { "title": "Notificaciones", "favorites": "Marque como favorita mi publicación", @@ -526,14 +563,17 @@ } }, "report": { + "title_report": "Reportar", "title": "Reportar %s", "step1": "Paso 1 de 2", "step2": "Paso 2 de 2", "content1": "¿Hay alguna otra publicación que te gustaría añadir al reporte?", "content2": "¿Hay algo que los moderadores deberían saber acerca de este reporte?", + "report_sent_title": "Gracias por reportar, estudiaremos esto.", "send": "Enviar Reporte", "skip_to_send": "Enviar sin comentarios", - "text_placeholder": "Escribe o pega comentarios adicionales" + "text_placeholder": "Escribe o pega comentarios adicionales", + "reported": "REPORTADO" }, "preview": { "keyboard": { @@ -543,14 +583,14 @@ } }, "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" + "tab_bar_hint": "Perfil seleccionado actualmente: %s. Haz un doble toque y mantén pulsado para mostrar el selector de cuentas", + "dismiss_account_switcher": "Descartar el selector de cuentas", + "add_account": "Añadir cuenta" }, "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" + "new_in_mastodon": "Nuevo en Mastodon", + "multiple_account_switch_intro_description": "Cambie entre varias cuentas manteniendo presionado el botón de perfil.", + "accessibility_hint": "Haz doble toque para descartar este asistente" } } } \ No newline at end of file diff --git a/Localization/StringsConvertor/input/eu_ES/Localizable.stringsdict b/Localization/StringsConvertor/input/eu_ES/Localizable.stringsdict new file mode 100644 index 00000000..817e8372 --- /dev/null +++ b/Localization/StringsConvertor/input/eu_ES/Localizable.stringsdict @@ -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>Irakurri gabeko jakinarazpen bat</string> + <key>other</key> + <string>Irakurri gabeko %ld jakinarazpen</string> + </dict> + </dict> + <key>a11y.plural.count.input_limit_exceeds</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>Sarrerak %#@character_count@ karaktereko muga gainditzen du</string> + <key>character_count</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>ld</string> + <key>one</key> + <string>karaktere bat</string> + <key>other</key> + <string>%ld karaktere</string> + </dict> + </dict> + <key>a11y.plural.count.input_limit_remains</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>Sarreraren karaktere muga %#@character_count@ da oraindik</string> + <key>character_count</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>ld</string> + <key>one</key> + <string>karaktere bat</string> + <key>other</key> + <string>%ld karaktere</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>bidalketa</string> + <key>other</key> + <string>bidalketa</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>Bidalketa bat</string> + <key>other</key> + <string>%ld bidalketa</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>Gogoko bat</string> + <key>other</key> + <string>%ld gogoko</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>Bultzada bat</string> + <key>other</key> + <string>%ld bultzada</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>Boto bat</string> + <key>other</key> + <string>%ld boto</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>Boto-emaile bat</string> + <key>other</key> + <string>%ld boto-emaile</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>Pertsona bat hizketan</string> + <key>other</key> + <string>%ld pertsona hizketan</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>Bat jarraitzen</string> + <key>other</key> + <string>%ld jarraitzen</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>Jarraitzaile bat</string> + <key>other</key> + <string>%ld jarraitzaile</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>Urte bat geratzen da</string> + <key>other</key> + <string>%ld urte geratzen dira</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>Hilabete bat geratzen da</string> + <key>other</key> + <string>%ld hilabete geratzen dira</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>Egun bat geratzen da</string> + <key>other</key> + <string>%ld egun geratzen dira</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>Ordu 1 geratzen da</string> + <key>other</key> + <string>%ld ordu geratzen dira</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>Minutu 1 geratzen da</string> + <key>other</key> + <string>%ld minutu geratzen dira</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>Segundo 1 geratzen da</string> + <key>other</key> + <string>%ld segundo geratzen dira</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>Duela urtebete</string> + <key>other</key> + <string>Duela %ld urte</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>Duela hilabete</string> + <key>other</key> + <string>Duela %ld hilabete</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>Duela egun bat</string> + <key>other</key> + <string>Duela %ld egun</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>Duela ordubete</string> + <key>other</key> + <string>Duela %ld ordu</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>Duela minutu bat</string> + <key>other</key> + <string>Duela %ld minutu</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>Duela segundo bat</string> + <key>other</key> + <string>Duela %ld segundo</string> + </dict> + </dict> + </dict> +</plist> diff --git a/Localization/StringsConvertor/input/eu_ES/app.json b/Localization/StringsConvertor/input/eu_ES/app.json new file mode 100644 index 00000000..39d06227 --- /dev/null +++ b/Localization/StringsConvertor/input/eu_ES/app.json @@ -0,0 +1,596 @@ +{ + "common": { + "alerts": { + "common": { + "please_try_again": "Mesedez, saiatu berriro.", + "please_try_again_later": "Mesedez beranduago saiatu." + }, + "sign_up_failure": { + "title": "Hutsegitea izen-ematean" + }, + "server_error": { + "title": "Zerbitzari-errorea" + }, + "vote_failure": { + "title": "Hutsegitea botoa ematean", + "poll_ended": "Inkesta amaitu da" + }, + "discard_post_content": { + "title": "Baztertu zirriborroa", + "message": "Berretsi idatzitako bidalketaren edukia baztertzea." + }, + "publish_post_failure": { + "title": "Hutsegitea argitaratzean", + "message": "Huts egin du bidalketa argitaratzean.\nEgiaztatu Interneteko konexioa.", + "attachments_message": { + "video_attach_with_photo": "Ezin da irudiak dituen bidalketa batean bideo bat erantsi.", + "more_than_one_video": "Ezin da bideo bat baino gehiago erantsi." + } + }, + "edit_profile_failure": { + "title": "Errorea profila editatzean", + "message": "Ezin da profila editatu. Mesedez saiatu berriro." + }, + "sign_out": { + "title": "Amaitu saioa", + "message": "Ziur saioa amaitu nahi duzula?", + "confirm": "Amaitu saioa" + }, + "block_domain": { + "title": "Ziur, erabat ziur, %s domeinu osoa blokeatu nahi duzula? Gehienetan erabiltzaile gutxi batzuk blokeatu edo mututzearekin nahikoa da. Ez duzu domeinu horretako edukirik ikusiko eta domeinu horretako zure jarraitzaileak kenduko dira.", + "block_entire_domain": "Blokeatu domeinua" + }, + "save_photo_failure": { + "title": "Hutsegitea argazkia gordetzean", + "message": "Gaitu argazki galeriarako sarbidearen baimena argazkia gordetzeko." + }, + "delete_post": { + "title": "Ziur zaude bidalketa hau ezabatu nahi duzula?", + "message": "Ziur bidalketa hau ezabatu nahi duzula?" + }, + "clean_cache": { + "title": "Garbitu cache-a", + "message": "Behar bezala garbitu da %s cache-a." + } + }, + "controls": { + "actions": { + "back": "Atzera", + "next": "Hurrengoa", + "previous": "Aurrekoa", + "open": "Ireki", + "add": "Gehitu", + "remove": "Kendu", + "edit": "Editatu", + "save": "Gorde", + "ok": "Ados", + "done": "Egina", + "confirm": "Berretsi", + "continue": "Jarraitu", + "compose": "Idatzi", + "cancel": "Utzi", + "discard": "Baztertu", + "try_again": "Saiatu berriro", + "take_photo": "Atera argazkia", + "save_photo": "Gorde argazkia", + "copy_photo": "Kopiatu argazkia", + "sign_in": "Hasi saioa", + "sign_up": "Eman Izena", + "see_more": "Ikusi gehiago", + "preview": "Aurrebista", + "share": "Partekatu", + "share_user": "Partekatu %s", + "share_post": "Partekatu bidalketa", + "open_in_safari": "Ireki Safarin", + "open_in_browser": "Ireki nabigatzailean", + "find_people": "Bilatu jarraitzeko jendea", + "manually_search": "Eskuz bilatu", + "skip": "Saltatu", + "reply": "Erantzun", + "report_user": "Salatu %s", + "block_domain": "Blokeatu %s", + "unblock_domain": "Desblokeatu %s", + "settings": "Ezarpenak", + "delete": "Ezabatu" + }, + "tabs": { + "home": "Hasiera", + "search": "Bilatu", + "notification": "Jakinarazpena", + "profile": "Profila" + }, + "keyboard": { + "common": { + "switch_to_tab": "Aldatu %s(e)ra", + "compose_new_post": "Idatzi bidalketa berria", + "show_favorites": "Erakutsi gogokoak", + "open_settings": "Ireki ezarpenak" + }, + "timeline": { + "previous_status": "Aurreko bidalketa", + "next_status": "Hurrengo bidalketa", + "open_status": "Ireki bidalketa", + "open_author_profile": "Ireki egilearen profila", + "open_reblogger_profile": "Ireki bultzada eman duenaren profila", + "reply_status": "Erantzun bidalketari", + "toggle_reblog": "Txandakatu bidalketaren bultzada", + "toggle_favorite": "Txandakatu bidalketa gogoko egitea", + "toggle_content_warning": "Txandakatu edukiaren abisua", + "preview_image": "Aurreikusi irudia" + }, + "segmented_control": { + "previous_section": "Aurreko sekzioa", + "next_section": "Hurrengo sekzioa" + } + }, + "status": { + "user_reblogged": "%s erabiltzaileak bultzada eman dio", + "user_replied_to": "%s(r)i erantzuten", + "show_post": "Erakutsi bidalketa", + "show_user_profile": "Erakutsi erabiltzailearen profila", + "content_warning": "Edukiaren abisua", + "media_content_warning": "Ukitu edonon bistaratzeko", + "poll": { + "vote": "Bozkatu", + "closed": "Itxita" + }, + "actions": { + "reply": "Erantzun", + "reblog": "Bultzada", + "unreblog": "Desegin bultzada", + "favorite": "Gogokoa", + "unfavorite": "Kendu gogokoa", + "menu": "Menua", + "hide": "Ezkutatu" + }, + "tag": { + "url": "URLa", + "mention": "Aipatu", + "link": "Esteka", + "hashtag": "Traola", + "email": "Eposta", + "emoji": "Emojia" + }, + "visibility": { + "unlisted": "Edozeinek ikusi dezake bidalketa hau baina ez da denbora-lerro publikoan bistaratuko.", + "private": "Beren jarraitzaileek soilik ikus dezakete bidalketa hau.", + "private_from_me": "Nire jarraitzaileek soilik ikus dezakete bidalketa hau.", + "direct": "Aipatutako erabiltzaileek soilik ikus dezakete bidalketa hau." + } + }, + "friendship": { + "follow": "Jarraitu", + "following": "Jarraitzen", + "request": "Eskaera", + "pending": "Zain", + "block": "Blokeatu", + "block_user": "Blokeatu %s", + "block_domain": "Blokeatu %s", + "unblock": "Desblokeatu", + "unblock_user": "Desblokeatu %s", + "blocked": "Blokeatuta", + "mute": "Mututu", + "mute_user": "Mututu %s", + "unmute": "Desmututu", + "unmute_user": "Desmututu %s", + "muted": "Mutututa", + "edit_info": "Editatu informazioa" + }, + "timeline": { + "filtered": "Iragazita", + "timestamp": { + "now": "Orain" + }, + "loader": { + "load_missing_posts": "Kargatu falta diren bidalketak", + "loading_missing_posts": "Falta diren bidalketak kargatzen...", + "show_more_replies": "Erakutsi erantzun gehiago" + }, + "header": { + "no_status_found": "Ez da bidalketa aurkitu", + "blocking_warning": "Ezin duzu erabiltzaile honen profila ikusi\ndesblokeatzen duzun arte.\nZure profilak itxura hau du berarentzat.", + "user_blocking_warning": "Ezin duzu %s erabiltzailearen\nprofila ikusi desblokeatzen duzun arte.\nZure profilak itxura hau du berarentzat.", + "blocked_warning": "Ezin duzu erabiltzaile honen profila ikusi\ndesblokeatzen zaituen arte.", + "user_blocked_warning": "Ezin duzu %s erabiltzailearen\nprofila ikusi desblokeatzen zaituen arte.", + "suspended_warning": "Erabiltzaile hau kanporatua izan da.", + "user_suspended_warning": "%s kontua kanporatua izan da." + } + } + } + }, + "scene": { + "welcome": { + "slogan": "Sare sozialak\nberriz zure eskuetan.", + "get_started": "Nola hasi", + "log_in": "Hasi saioa" + }, + "server_picker": { + "title": "Aukeratu zerbitzari bat,\nedozein zerbitzari.", + "subtitle": "Aukeratu komunitate bat zure interes edo lurraldearen arabera, edo erabilera orokorreko bat.", + "subtitle_extend": "Aukeratu komunitate bat zure interes edo lurraldearen arabera, edo erabilera orokorreko bat. Komunitate bakoitza erakunde edo norbanako independente batek kudeatzen du.", + "button": { + "category": { + "all": "Guztiak", + "all_accessiblity_description": "Kategoria: Guztiak", + "academia": "akademia", + "activism": "aktibismoa", + "food": "janaria", + "furry": "furry", + "games": "jokoak", + "general": "orokorra", + "journalism": "kazetaritza", + "lgbt": "LGBTQ+", + "regional": "herrialdekoa", + "art": "artea", + "music": "musika", + "tech": "teknologia" + }, + "see_less": "Ikusi gutxiago", + "see_more": "Ikusi gehiago" + }, + "label": { + "language": "HIZKUNTZA", + "users": "ERABILTZAILEAK", + "category": "KATEGORIA" + }, + "input": { + "placeholder": "Bilatu zerbitzari bat edo sortu zurea..." + }, + "empty_state": { + "finding_servers": "Erabilgarri dauden zerbitzariak bilatzen...", + "bad_network": "Arazoren bat egon da datuak kargatzean. Egiaztatu zure Interneteko konexioa.", + "no_results": "Emaitzarik ez" + } + }, + "register": { + "title": "Hitz egin iezaguzu zuri buruz.", + "input": { + "avatar": { + "delete": "Ezabatu" + }, + "username": { + "placeholder": "erabiltzaile-izena", + "duplicate_prompt": "Erabiltzaile-izen hau hartuta dago." + }, + "display_name": { + "placeholder": "pantaila-izena" + }, + "email": { + "placeholder": "eposta" + }, + "password": { + "placeholder": "pasahitza", + "require": "Zure pasahitzak izan behar ditu gutxienez:", + "character_limit": "8 karaktere", + "accessibility": { + "checked": "hautatuta", + "unchecked": "hautatu gabe" + }, + "hint": "Pasahitzak zortzi karaktere izan behar ditu gutxienez" + }, + "invite": { + "registration_user_invite_request": "Zergatik elkartu nahi duzu?" + } + }, + "error": { + "item": { + "username": "Erabiltzaile-izena", + "email": "Eposta", + "password": "Pasahitza", + "agreement": "Adostasuna", + "locale": "Eskualdeko ezarpenak", + "reason": "Arrazoia" + }, + "reason": { + "blocked": "%s(e)k onartu gabeko eposta hornitzaile bat erabiltzen du", + "unreachable": "dirudienez %s ez da existitzen", + "taken": "%s dagoeneko erabiltzen da", + "reserved": "%s gako-hitz erreserbatu bat da", + "accepted": "%s onartu behar da", + "blank": "%s beharrezkoa da", + "invalid": "%s baliogabea da", + "too_long": "%s luzeegia da", + "too_short": "%s laburregia da", + "inclusion": "%s ez da onartutako balio bat" + }, + "special": { + "username_invalid": "Erabiltzaile-izenak karaktere alfanumerikoak eta azpimarrak soilik eduki ditzake", + "username_too_long": "Erabiltzaile-izena luzeegia da (ezin ditu 30 karaktere baino gehiago izan)", + "email_invalid": "Hau ez da baliozko eposta helbidea", + "password_too_short": "Pasahitza laburregia da (gutxienez 8 karaktere izan behar ditu)" + } + } + }, + "server_rules": { + "title": "Oinarrizko arau batzuk.", + "subtitle": "Arau hauek %s instantziako administratzaileek ezarri dituzte.", + "prompt": "Jarraituz gero, %s instantziaren zerbitzu-baldintzak eta pribatutasun-gidalerroak onartzen dituzu.", + "terms_of_service": "zerbitzu-baldintzak", + "privacy_policy": "pribatutasun-gidalerroak", + "button": { + "confirm": "Ados nago" + } + }, + "confirm_email": { + "title": "Eta azkenik...", + "subtitle": "Eposta bat bidali dizugu %s helbidera,\nsakatu kontua berresteko esteka.", + "button": { + "open_email_app": "Ireki eposta aplikazioa", + "resend": "Berbidali" + }, + "dont_receive_email": { + "title": "Begiratu zure eposta", + "description": "Egiaztatu zure eposta helbidea zuzena den eta begiratu zaborraren karpeta.", + "resend_email": "Birbidali eposta" + }, + "open_email_app": { + "title": "Egiaztatu zure sarrerako ontzia.", + "description": "Eposta bat bidali dizugu. Egiaztatu zure zaborraren karpeta.", + "mail": "Posta", + "open_email_client": "Ireki eposta bezeroa" + } + }, + "home_timeline": { + "title": "Hasiera", + "navigation_bar_state": { + "offline": "Konexio gabe", + "new_posts": "Ikusi bidal. berriak", + "published": "Argitaratua!", + "Publishing": "Bidalketa argitaratzen..." + } + }, + "suggestion_account": { + "title": "Bilatu jarraitzeko jendea", + "follow_explain": "Norbait jarraitzen duzunean, bere bidalketak zure hasierako denbora-lerroan agertuko zaizkizu." + }, + "compose": { + "title": { + "new_post": "Bidalketa berria", + "new_reply": "Erantzun berria" + }, + "media_selection": { + "camera": "Atera argazkia", + "photo_library": "Argazki-liburutegia", + "browse": "Arakatu" + }, + "content_input_placeholder": "Idatzi edo itsatsi buruan duzuna", + "compose_action": "Argitaratu", + "replying_to_user": "%s(r)i erantzuten", + "attachment": { + "photo": "argazkia", + "video": "bideoa", + "attachment_broken": "%s hondatuta dago eta ezin da\nMastodonera igo.", + "description_photo": "Deskribatu argazkia ikusmen arazoak dituztenentzat...", + "description_video": "Deskribatu bideoa ikusmen arazoak dituztenentzat..." + }, + "poll": { + "duration_time": "Iraupena: %s", + "thirty_minutes": "30 minutu", + "one_hour": "Ordu 1", + "six_hours": "6 ordu", + "one_day": "Egun 1", + "three_days": "3 egun", + "seven_days": "7 egun", + "option_number": "%ld aukera" + }, + "content_warning": { + "placeholder": "Idatzi abisu zehatz bat hemen..." + }, + "visibility": { + "public": "Publikoa", + "unlisted": "Zerrendatu gabea", + "private": "Jarraitzaileak soilik", + "direct": "Aipatzen dudan jendea soilik" + }, + "auto_complete": { + "space_to_add": "Sakatu zuriunea gehitzeko" + }, + "accessibility": { + "append_attachment": "Gehitu eranskina", + "append_poll": "Gehitu inkesta", + "remove_poll": "Kendu inkesta", + "custom_emoji_picker": "Emoji pertsonalizatuen hautatzailea", + "enable_content_warning": "Gaitu edukiaren abisua", + "disable_content_warning": "Desgaitu edukiaren abisua", + "post_visibility_menu": "Bidalketaren ikusgaitasunaren menua" + }, + "keyboard": { + "discard_post": "Baztertu bidalketa", + "publish_post": "Argitaratu bidalketa", + "toggle_poll": "Txandakatu inkesta", + "toggle_content_warning": "Txandakatu edukiaren abisua", + "append_attachment_entry": "Gehitu eranskina - %s", + "select_visibility_entry": "Hautatu ikusgaitasuna - %s" + } + }, + "profile": { + "dashboard": { + "posts": "bidalketa", + "following": "jarraitzen", + "followers": "jarraitzaile" + }, + "fields": { + "add_row": "Gehitu errenkada", + "placeholder": { + "label": "Etiketa", + "content": "Edukia" + } + }, + "segmented_control": { + "posts": "Bidalketak", + "replies": "Erantzunak", + "posts_and_replies": "Bidalketak eta erantzunak", + "media": "Multimedia", + "about": "Honi buruz" + }, + "relationship_action_alert": { + "confirm_mute_user": { + "title": "Mututu kontua", + "message": "Berretsi %s mututzea" + }, + "confirm_unmute_user": { + "title": "Desmututu kontua", + "message": "Berretsi %s desmututzea" + }, + "confirm_block_user": { + "title": "Blokeatu kontua", + "message": "Berretsi %s blokeatzea" + }, + "confirm_unblock_user": { + "title": "Desblokeatu kontua", + "message": "Berretsi %s desblokeatzea" + } + } + }, + "follower": { + "footer": "Beste zerbitzarietako jarraitzaileak ez dira bistaratzen." + }, + "following": { + "footer": "Beste zerbitzarietan jarraitutakoak ez dira bistaratzen." + }, + "search": { + "title": "Bilatu", + "search_bar": { + "placeholder": "Bilatu traolak eta erabiltzaileak", + "cancel": "Utzi" + }, + "recommend": { + "button_text": "Ikusi guztiak", + "hash_tag": { + "title": "Mastodoneko joerak", + "description": "Deigarri gertatzen ari diren traolak", + "people_talking": "%s pertsona hizketan" + }, + "accounts": { + "title": "Gustuko izan ditzakezun kontuak", + "description": "Kontu hauek jarraitu nahiko dituzu behar bada", + "follow": "Jarraitu" + } + }, + "searching": { + "segment": { + "all": "Guztiak", + "people": "Jendea", + "hashtags": "Traolak", + "posts": "Bidalketak" + }, + "empty_state": { + "no_results": "Emaitzarik ez" + }, + "recent_search": "Azken bilaketak", + "clear": "Garbitu" + } + }, + "favorite": { + "title": "Zure gogokoak" + }, + "notification": { + "title": { + "Everything": "Dena", + "Mentions": "Aipamenak" + }, + "notification_description": { + "followed_you": "zu jarraitzen hasi da", + "favorited_your_post": "erabiltzaileak zure bidalketa gogoko du", + "reblogged_your_post": "erabiltzaileak bultzada eman dio zure bidalketari", + "mentioned_you": "erabiltzaileak aipatu zaitu", + "request_to_follow_you": "erabiltzaileak zu jarraitzea eskatu du", + "poll_has_ended": "inkesta amaitu da" + }, + "keyobard": { + "show_everything": "Erakutsi guztia", + "show_mentions": "Erakutsi aipamenak" + } + }, + "thread": { + "back_title": "Bidalketa", + "title": "%s(e)n bidalketa" + }, + "settings": { + "title": "Ezarpenak", + "section": { + "appearance": { + "title": "Itxura", + "automatic": "Automatikoa", + "light": "Beti argia", + "dark": "Beti iluna" + }, + "look_and_feel": { + "title": "Itxura", + "use_system": "Erabili sistemakoa", + "really_dark": "Oso iluna", + "sorta_dark": "Ilun antzekoa", + "light": "Argia" + }, + "notifications": { + "title": "Jakinarazpenak", + "favorites": "Nire bidalketa gogoko egitean", + "follows": "Jarraitzen nau", + "boosts": "Nire bidalketa bultzatu du", + "mentions": "Aipatu nau", + "trigger": { + "anyone": "edozein", + "follower": "jarraitzaile bat", + "follow": "jarraitzen dudan edonor", + "noone": "inor ez", + "title": "Noiz jakinarazi:" + } + }, + "preference": { + "title": "Hobespenak", + "true_black_dark_mode": "Benetako modu beltz iluna", + "disable_avatar_animation": "Desgaitu abatar animatuak", + "disable_emoji_animation": "Desgaitu emoji animatuak", + "using_default_browser": "Erabili nabigatzaile lehenetsia estekak irekitzeko" + }, + "boring_zone": { + "title": "Eremu aspergarria", + "account_settings": "Kontuaren ezarpenak", + "terms": "Zerbitzu-baldintzak", + "privacy": "Pribatutasun-gidalerroak" + }, + "spicy_zone": { + "title": "Eremu beroa", + "clear": "Garbitu multimediaren cachea", + "signout": "Amaitu saioa" + } + }, + "footer": { + "mastodon_description": "Mastodon software librea da. Arazoen berri eman dezakezu GitHub bidez: %s (%s)" + }, + "keyboard": { + "close_settings_window": "Itxi ezarpenen leihoa" + } + }, + "report": { + "title_report": "Salatu", + "title": "Salatu %s", + "step1": "1. urratsa 2tik", + "step2": "2. urratsa 2tik", + "content1": "Salaketan beste bidalketarik gehitu nahi duzu?", + "content2": "Moderatzaileek besterik jakin behar dute salaketa honi buruz?", + "report_sent_title": "Mila esker salaketagatik, berrikusiko dugu.", + "send": "Bidali salaketa", + "skip_to_send": "Bidali iruzkinik gabe", + "text_placeholder": "Idatzi edo itsatsi iruzkin gehigarriak", + "reported": "SALATUA" + }, + "preview": { + "keyboard": { + "close_preview": "Itxi aurrebista", + "show_next": "Erakutsi hurrengoa", + "show_previous": "Erakutsi aurrekoa" + } + }, + "account_list": { + "tab_bar_hint": "Unean hautatutako profila: %s. Ukitu birritan, ondoren eduki sakatuta kontu-aldatzailea erakusteko", + "dismiss_account_switcher": "Baztertu kontu-aldatzailea", + "add_account": "Gehitu kontua" + }, + "wizard": { + "new_in_mastodon": "Berria Mastodonen", + "multiple_account_switch_intro_description": "Aldatu hainbat konturen artean profilaren botoia sakatuta edukiz.", + "accessibility_hint": "Ukitu birritan morroi hau baztertzeko" + } + } +} \ No newline at end of file diff --git a/Localization/StringsConvertor/input/eu_ES/ios-infoPlist.json b/Localization/StringsConvertor/input/eu_ES/ios-infoPlist.json new file mode 100644 index 00000000..bc0457ea --- /dev/null +++ b/Localization/StringsConvertor/input/eu_ES/ios-infoPlist.json @@ -0,0 +1,6 @@ +{ + "NSCameraUsageDescription": "Bidalketetarako argazkiak ateratzeko erabiltzen da", + "NSPhotoLibraryAddUsageDescription": "Argazkiak Argazki-liburutegian gordetzeko erabiltzen da", + "NewPostShortcutItemTitle": "Bidalketa berria", + "SearchShortcutItemTitle": "Bilatu" +} diff --git a/Localization/StringsConvertor/input/fr_FR/Localizable.stringsdict b/Localization/StringsConvertor/input/fr_FR/Localizable.stringsdict index 4a912e4b..37f07e67 100644 --- a/Localization/StringsConvertor/input/fr_FR/Localizable.stringsdict +++ b/Localization/StringsConvertor/input/fr_FR/Localizable.stringsdict @@ -37,7 +37,7 @@ <key>a11y.plural.count.input_limit_remains</key> <dict> <key>NSStringLocalizedFormatKey</key> - <string>Input limit remains %#@character_count@</string> + <string>La limite d'entrée reste %#@character_count@</string> <key>character_count</key> <dict> <key>NSStringFormatSpecTypeKey</key> diff --git a/Localization/StringsConvertor/input/fr_FR/app.json b/Localization/StringsConvertor/input/fr_FR/app.json index dd834928..9941ff99 100644 --- a/Localization/StringsConvertor/input/fr_FR/app.json +++ b/Localization/StringsConvertor/input/fr_FR/app.json @@ -46,7 +46,7 @@ }, "delete_post": { "title": "Voulez-vous vraiment supprimer ce message ?", - "delete": "Supprimer" + "message": "Voulez-vous vraiment supprimer ce message ?" }, "clean_cache": { "title": "Vider le cache", @@ -67,7 +67,7 @@ "done": "Terminé", "confirm": "Confirmer", "continue": "Continuer", - "compose": "Compose", + "compose": "Rédiger", "cancel": "Annuler", "discard": "Abandonner", "try_again": "Réessayer", @@ -82,6 +82,7 @@ "share_user": "Partager %s", "share_post": "Partager la publication", "open_in_safari": "Ouvrir dans Safari", + "open_in_browser": "Ouvrir dans le navigateur", "find_people": "Trouver des personnes à suivre", "manually_search": "Rechercher manuellement à la place", "skip": "Passer", @@ -139,7 +140,8 @@ "unreblog": "Annuler le reblog", "favorite": "Favori", "unfavorite": "Retirer des favoris", - "menu": "Menu" + "menu": "Menu", + "hide": "Cacher" }, "tag": { "url": "URL", @@ -148,6 +150,12 @@ "hashtag": "Hashtag", "email": "Courriel", "emoji": "Émoji" + }, + "visibility": { + "unlisted": "Tout le monde peut voir ce message mais ne sera pas affiché sur le fil public.", + "private": "Seul·e·s leurs abonné·e·s peuvent voir ce message.", + "private_from_me": "Seul·e·s mes abonné·e·s peuvent voir ce message.", + "direct": "Seul·e l’utilisateur·rice mentionnée peut voir ce message." } }, "friendship": { @@ -192,10 +200,14 @@ }, "scene": { "welcome": { - "slogan": "Le réseau social qui vous rend le contrôle." + "slogan": "Le réseau social qui vous rend le contrôle.", + "get_started": "Prise en main", + "log_in": "Se connecter" }, "server_picker": { "title": "Choisissez un serveur,\nn'importe quel serveur.", + "subtitle": "Choisissez une communauté en fonction de vos intérêts, de votre région ou de votre objectif général.", + "subtitle_extend": "Choisissez une communauté basée sur vos intérêts, votre région ou un but général. Chaque communauté est gérée par une organisation ou un individu entièrement indépendant.", "button": { "category": { "all": "Tout", @@ -248,6 +260,12 @@ }, "password": { "placeholder": "mot de passe", + "require": "Votre mot de passe doit être composé d’au moins :", + "character_limit": "8 caractères", + "accessibility": { + "checked": "vérifié", + "unchecked": "non vérifié" + }, "hint": "Votre mot de passe doit contenir au moins 8 caractères" }, "invite": { @@ -298,7 +316,7 @@ "subtitle": "Nous venons d’envoyer un courriel à %s,\ntapotez le lien pour confirmer votre compte.", "button": { "open_email_app": "Ouvrir l’application de courriel", - "dont_receive_email": "Je n’ai jamais reçu de courriel" + "resend": "Renvoyer" }, "dont_receive_email": { "title": "Vérifier vos courriels", @@ -401,14 +419,24 @@ "segmented_control": { "posts": "Publications", "replies": "Réponses", - "media": "Média" + "posts_and_replies": "Messages et réponses", + "media": "Média", + "about": "À propos" }, "relationship_action_alert": { + "confirm_mute_user": { + "title": "Masquer le compte", + "message": "Êtes-vous sûr de vouloir mettre en sourdine %s" + }, "confirm_unmute_user": { "title": "Ne plus mettre en sourdine ce compte", "message": "Êtes-vous sûr de vouloir désactiver la sourdine de %s" }, - "confirm_unblock_usre": { + "confirm_block_user": { + "title": "Bloquer le compte", + "message": "Confirmer le blocage de %s" + }, + "confirm_unblock_user": { "title": "Débloquer le compte", "message": "Confirmer le déblocage de %s" } @@ -418,7 +446,7 @@ "footer": "Les abonné·e·s issus des autres serveurs ne sont pas affiché·e·s." }, "following": { - "footer": "Follows from other servers are not displayed." + "footer": "Les abonnés issus des autres serveurs ne sont pas affichés." }, "search": { "title": "Rechercher", @@ -461,12 +489,14 @@ "Everything": "Tout", "Mentions": "Mentions" }, - "user_followed_you": "%s s’est abonné à vous", - "user_favorited your post": "%s a mis votre pouet en favori", - "user_reblogged_your_post": "%s a partagé votre publication", - "user_mentioned_you": "%s vous a mentionné", - "user_requested_to_follow_you": "%s a demandé à vous suivre", - "user_your_poll_has_ended": "%s votre sondage est terminé", + "notification_description": { + "followed_you": "s’est abonné à vous", + "favorited_your_post": "a ajouté votre message à ses favoris", + "reblogged_your_post": "a partagé votre message", + "mentioned_you": "vous a mentionné", + "request_to_follow_you": "vous a envoyé une demande d’abonnement", + "poll_has_ended": "le sondage est terminé" + }, "keyobard": { "show_everything": "Tout Afficher", "show_mentions": "Afficher les mentions" @@ -485,6 +515,13 @@ "light": "Toujours claire", "dark": "Toujours sombre" }, + "look_and_feel": { + "title": "Apparence", + "use_system": "Utiliser le thème du système", + "really_dark": "Très sombre", + "sorta_dark": "Légèrement sombre", + "light": "Clair" + }, "notifications": { "title": "Notifications", "favorites": "Ajoute l’une de mes publications à ses favoris", @@ -526,14 +563,17 @@ } }, "report": { + "title_report": "Signalement", "title": "Signaler %s", "step1": "Étape 1 de 2", "step2": "Étape 2 de 2", "content1": "Y a-t-il d’autres messages que vous aimeriez ajouter au signalement?", "content2": "Y a-t-il quelque chose que les modérateurs devraient savoir sur ce rapport ?", + "report_sent_title": "Merci de nous l’avoir signalé, nous allons examiner cela.", "send": "Envoyer le rapport", "skip_to_send": "Envoyer sans commentaire", - "text_placeholder": "Tapez ou collez des informations supplémentaires" + "text_placeholder": "Tapez ou collez des informations supplémentaires", + "reported": "SIGNALÉ" }, "preview": { "keyboard": { @@ -543,8 +583,8 @@ } }, "account_list": { - "tab_bar_hint": "Current selected profile: %s. Double tap then hold to show account switcher", - "dismiss_account_switcher": "Dismiss Account Switcher", + "tab_bar_hint": "Profil sélectionné actuel: %s. Double appui puis maintenez enfoncé pour afficher le changement de compte", + "dismiss_account_switcher": "Rejeter le commutateur de compte", "add_account": "Ajouter un compte" }, "wizard": { diff --git a/Localization/StringsConvertor/input/gd_GB/app.json b/Localization/StringsConvertor/input/gd_GB/app.json index b5c66f8f..520293d4 100644 --- a/Localization/StringsConvertor/input/gd_GB/app.json +++ b/Localization/StringsConvertor/input/gd_GB/app.json @@ -46,7 +46,7 @@ }, "delete_post": { "title": "A bheil thu cinnteach gu bheil thu airson am post seo a sguabadh às?", - "delete": "Sguab às" + "message": "A bheil thu cinnteach gu bheil thu airson am post seo a sguabadh às?" }, "clean_cache": { "title": "Falamhaich an tasgadan", @@ -82,6 +82,7 @@ "share_user": "Co-roinn %s", "share_post": "Co-roinn am post", "open_in_safari": "Fosgail ann an Safari", + "open_in_browser": "Fosgail sa bhrabhsair", "find_people": "Lorg daoine a leanas tu", "manually_search": "Lorg a làimh ’na àite", "skip": "Leum thairis air", @@ -139,7 +140,8 @@ "unreblog": "Na brosnaich tuilleadh", "favorite": "Cuir ris na h-annsachdan", "unfavorite": "Thoir air falbh o na h-annsachdan", - "menu": "Clàr-taice" + "menu": "Clàr-taice", + "hide": "Falaich" }, "tag": { "url": "URL", @@ -148,6 +150,12 @@ "hashtag": "Taga hais", "email": "Post-d", "emoji": "Emoji" + }, + "visibility": { + "unlisted": "Chì a h-uile duine am post seo ach cha nochd e air an loidhne-ama phoblach.", + "private": "Chan fhaic ach an luchd-leantainn aca am post seo.", + "private_from_me": "Chan fhaic ach an luchd-leantainn agam am post seo.", + "direct": "Chan fhaic ach an cleachdaiche air an dugadh iomradh am post seo." } }, "friendship": { @@ -192,10 +200,14 @@ }, "scene": { "welcome": { - "slogan": "A’ cur nan lìonraidhean sòisealta\n’nad làmhan fhèin." + "slogan": "A’ cur nan lìonraidhean sòisealta\n’nad làmhan fhèin.", + "get_started": "Dèan toiseach-tòiseachaidh", + "log_in": "Clàraich a-steach" }, "server_picker": { "title": "Tagh frithealaiche sam bith.", + "subtitle": "Tagh coimhearsnachd stèidhichte air d’ ùidhean no an roinn-dùthcha agad no tè choitcheann.", + "subtitle_extend": "Tagh coimhearsnachd stèidhichte air d’ ùidhean no an roinn-dùthcha agad no tè choitcheann. Tha gach coimhearsnachd ’ga stiùireadh le buidheann no neach gu neo-eisimeileach.", "button": { "category": { "all": "Na h-uile", @@ -248,6 +260,12 @@ }, "password": { "placeholder": "facal-faire", + "require": "Feumaidh am facal-faire agad co-dhiù:", + "character_limit": "8 caractaran", + "accessibility": { + "checked": "le cromag", + "unchecked": "gun chromag" + }, "hint": "Feumaidh ochd caractaran a bhith san fhacal-fhaire agad air a char as giorra" }, "invite": { @@ -298,7 +316,7 @@ "subtitle": "Tha sinn air post-d a chur gu %s,\nthoir gnogag air a’ chunntas a dhearbhadh a’ chunntais agad.", "button": { "open_email_app": "Fosgail aplacaid a’ phuist-d", - "dont_receive_email": "Cha d’ fhuair mi post-d a-riamh" + "resend": "Ath-chuir" }, "dont_receive_email": { "title": "Thoir sùil air a’ phost-d agad", @@ -401,14 +419,24 @@ "segmented_control": { "posts": "Postaichean", "replies": "Freagairtean", - "media": "Meadhanan" + "posts_and_replies": "Postaichean ’s freagairtean", + "media": "Meadhanan", + "about": "Mu dhèidhinn" }, "relationship_action_alert": { + "confirm_mute_user": { + "title": "Mùch an cunntas", + "message": "Dearbh mùchadh %s" + }, "confirm_unmute_user": { "title": "Dì-mhùch an cunntas", "message": "Dearbh dì-mhùchadh %s" }, - "confirm_unblock_usre": { + "confirm_block_user": { + "title": "Bac an cunntas", + "message": "Dearbh bacadh %s" + }, + "confirm_unblock_user": { "title": "Dì-bhac an cunntas", "message": "Dearbh dì-bhacadh %s" } @@ -461,12 +489,14 @@ "Everything": "A h-uile rud", "Mentions": "Iomraidhean" }, - "user_followed_you": "Tha %s a’ leantainn ort a-nis", - "user_favorited your post": "Is annsa le %s am post agad", - "user_reblogged_your_post": "Bhrosnaich %s am post agad", - "user_mentioned_you": "Thug %s iomradh ort", - "user_requested_to_follow_you": "Dh’iarr %s leantainn ort", - "user_your_poll_has_ended": "Crìoch cunntais-bheachd aig %s", + "notification_description": { + "followed_you": "– ’s iad ’gad leantainn a-nis", + "favorited_your_post": "– ’s iad air am post agad a chur ris na h-annsachdan aca", + "reblogged_your_post": "– ’s iad air am post agad a bhrosnachadh", + "mentioned_you": "– ’s iad air iomradh a thoirt ort", + "request_to_follow_you": "iarrtas leantainn ort", + "poll_has_ended": "thàinig cunntas-bheachd gu crìoch" + }, "keyobard": { "show_everything": "Seall a h-uile càil", "show_mentions": "Seall na h-iomraidhean" @@ -485,6 +515,13 @@ "light": "Soilleir an-còmhnaidh", "dark": "Dorcha an-còmhnaidh" }, + "look_and_feel": { + "title": "Coltas", + "use_system": "Cleachd coltas an t-siostaim", + "really_dark": "Glè dhorcha", + "sorta_dark": "Caran dorcha", + "light": "Soilleir" + }, "notifications": { "title": "Brathan", "favorites": "Nuair as annsa leotha am post agam", @@ -526,14 +563,17 @@ } }, "report": { + "title_report": "Dèan gearan", "title": "Dèan gearan mu %s", "step1": "Ceum 1 à 2", "step2": "Ceum 2 à 2", "content1": "A bheil post sam bith eile ann a bu mhiann leat cur ris a’ ghearan?", "content2": "A bheil rud sam bith ann a bu mhiann leat innse dha na maoir mun ghearan seo?", + "report_sent_title": "Mòran taing airson a’ ghearain, bheir sinn sùil air.", "send": "Cuir an gearan", "skip_to_send": "Cuir gun bheachd ris", - "text_placeholder": "Sgrìobh no cuir ann beachdan a bharrachd" + "text_placeholder": "Sgrìobh no cuir ann beachdan a bharrachd", + "reported": "CHAIDH GEARAN A DHÈANAMH" }, "preview": { "keyboard": { diff --git a/Localization/StringsConvertor/input/hi_IN/app.json b/Localization/StringsConvertor/input/hi_IN/app.json index 5c01ae7e..ad99e178 100644 --- a/Localization/StringsConvertor/input/hi_IN/app.json +++ b/Localization/StringsConvertor/input/hi_IN/app.json @@ -45,8 +45,8 @@ "message": "Please enable the photo library access permission to save the photo." }, "delete_post": { - "title": "Are you sure you want to delete this post?", - "delete": "Delete" + "title": "Delete Post", + "message": "Are you sure you want to delete this post?" }, "clean_cache": { "title": "Clean Cache", @@ -82,6 +82,7 @@ "share_user": "Share %s", "share_post": "Share Post", "open_in_safari": "Open in Safari", + "open_in_browser": "Open in Browser", "find_people": "Find people to follow", "manually_search": "Manually search instead", "skip": "Skip", @@ -139,7 +140,8 @@ "unreblog": "Undo reblog", "favorite": "Favorite", "unfavorite": "Unfavorite", - "menu": "Menu" + "menu": "Menu", + "hide": "Hide" }, "tag": { "url": "URL", @@ -148,6 +150,12 @@ "hashtag": "Hashtag", "email": "Email", "emoji": "Emoji" + }, + "visibility": { + "unlisted": "Everyone can see this post but not display in the public timeline.", + "private": "Only their followers can see this post.", + "private_from_me": "Only my followers can see this post.", + "direct": "Only mentioned user can see this post." } }, "friendship": { @@ -192,10 +200,14 @@ }, "scene": { "welcome": { - "slogan": "Social networking\nback in your hands." + "slogan": "Social networking\nback in your hands.", + "get_started": "Get Started", + "log_in": "Log In" }, "server_picker": { - "title": "Pick a server,\nany server.", + "title": "Mastodon is made of users in different communities.", + "subtitle": "Pick a community based on your interests, region, or a general purpose one.", + "subtitle_extend": "Pick a community based on your interests, region, or a general purpose one. Each community is operated by an entirely independent organization or individual.", "button": { "category": { "all": "All", @@ -222,7 +234,7 @@ "category": "CATEGORY" }, "input": { - "placeholder": "Find a server or join your own..." + "placeholder": "Search communities" }, "empty_state": { "finding_servers": "Finding available servers...", @@ -231,7 +243,7 @@ } }, "register": { - "title": "Tell us about you.", + "title": "Let’s get you set up on %s", "input": { "avatar": { "delete": "Delete" @@ -248,6 +260,12 @@ }, "password": { "placeholder": "password", + "require": "Your password needs at least:", + "character_limit": "8 characters", + "accessibility": { + "checked": "checked", + "unchecked": "unchecked" + }, "hint": "Your password needs at least eight characters" }, "invite": { @@ -285,7 +303,7 @@ }, "server_rules": { "title": "Some ground rules.", - "subtitle": "These rules are set by the admins of %s.", + "subtitle": "These are set and enforced by the %s moderators.", "prompt": "By continuing, you’re subject to the terms of service and privacy policy for %s.", "terms_of_service": "terms of service", "privacy_policy": "privacy policy", @@ -295,10 +313,10 @@ }, "confirm_email": { "title": "One last thing.", - "subtitle": "We just sent an email to %s,\ntap the link to confirm your account.", + "subtitle": "Tap the link we emailed to you to verify your account.", "button": { "open_email_app": "Open Email App", - "dont_receive_email": "I never got an email" + "resend": "Resend" }, "dont_receive_email": { "title": "Check your email", @@ -401,14 +419,24 @@ "segmented_control": { "posts": "Posts", "replies": "Replies", - "media": "Media" + "posts_and_replies": "Posts and Replies", + "media": "Media", + "about": "About" }, "relationship_action_alert": { + "confirm_mute_user": { + "title": "Mute Account", + "message": "Confirm to mute %s" + }, "confirm_unmute_user": { "title": "Unmute Account", "message": "Confirm to unmute %s" }, - "confirm_unblock_usre": { + "confirm_block_user": { + "title": "Block Account", + "message": "Confirm to block %s" + }, + "confirm_unblock_user": { "title": "Unblock Account", "message": "Confirm to unblock %s" } @@ -461,12 +489,14 @@ "Everything": "Everything", "Mentions": "Mentions" }, - "user_followed_you": "%s followed you", - "user_favorited your post": "%s favorited your post", - "user_reblogged_your_post": "%s reblogged your post", - "user_mentioned_you": "%s mentioned you", - "user_requested_to_follow_you": "%s requested to follow you", - "user_your_poll_has_ended": "%s Your poll has ended", + "notification_description": { + "followed_you": "followed you", + "favorited_your_post": "favorited your post", + "reblogged_your_post": "reblogged your post", + "mentioned_you": "mentioned you", + "request_to_follow_you": "request to follow you", + "poll_has_ended": "poll has ended" + }, "keyobard": { "show_everything": "Show Everything", "show_mentions": "Show Mentions" @@ -485,6 +515,13 @@ "light": "Always Light", "dark": "Always Dark" }, + "look_and_feel": { + "title": "Look and Feel", + "use_system": "Use System", + "really_dark": "Really Dark", + "sorta_dark": "Sorta Dark", + "light": "Light" + }, "notifications": { "title": "Notifications", "favorites": "Favorites my post", @@ -526,14 +563,17 @@ } }, "report": { + "title_report": "Report", "title": "Report %s", "step1": "Step 1 of 2", "step2": "Step 2 of 2", "content1": "Are there any other posts you’d like to add to the report?", "content2": "Is there anything the moderators should know about this report?", + "report_sent_title": "Thanks for reporting, we’ll look into this.", "send": "Send Report", "skip_to_send": "Send without comment", - "text_placeholder": "Type or paste additional comments" + "text_placeholder": "Type or paste additional comments", + "reported": "REPORTED" }, "preview": { "keyboard": { diff --git a/Localization/StringsConvertor/input/id_ID/app.json b/Localization/StringsConvertor/input/id_ID/app.json index 6f317125..c6af04e0 100644 --- a/Localization/StringsConvertor/input/id_ID/app.json +++ b/Localization/StringsConvertor/input/id_ID/app.json @@ -46,7 +46,7 @@ }, "delete_post": { "title": "Apakah Anda yakin ingin menghapus postingan ini?", - "delete": "Hapus" + "message": "Are you sure you want to delete this post?" }, "clean_cache": { "title": "Bersihkan Cache", @@ -82,6 +82,7 @@ "share_user": "Bagikan %s", "share_post": "Bagikan Postingan", "open_in_safari": "Buka di Safari", + "open_in_browser": "Open in Browser", "find_people": "Cari orang untuk diikuti", "manually_search": "Manually search instead", "skip": "Lewati", @@ -139,7 +140,8 @@ "unreblog": "Undo reblog", "favorite": "Favorit", "unfavorite": "Unfavorite", - "menu": "Menu" + "menu": "Menu", + "hide": "Hide" }, "tag": { "url": "URL", @@ -148,6 +150,12 @@ "hashtag": "Tagar", "email": "Surel", "emoji": "Emoji" + }, + "visibility": { + "unlisted": "Everyone can see this post but not display in the public timeline.", + "private": "Only their followers can see this post.", + "private_from_me": "Only my followers can see this post.", + "direct": "Only mentioned user can see this post." } }, "friendship": { @@ -192,10 +200,14 @@ }, "scene": { "welcome": { - "slogan": "Social networking\nback in your hands." + "slogan": "Social networking\nback in your hands.", + "get_started": "Get Started", + "log_in": "Log In" }, "server_picker": { "title": "Pilih sebuah server,\nserver manapun.", + "subtitle": "Pick a community based on your interests, region, or a general purpose one.", + "subtitle_extend": "Pick a community based on your interests, region, or a general purpose one. Each community is operated by an entirely independent organization or individual.", "button": { "category": { "all": "Semua", @@ -222,7 +234,7 @@ "category": "KATEGORI" }, "input": { - "placeholder": "Find a server or join your own..." + "placeholder": "Search communities" }, "empty_state": { "finding_servers": "Mencari server yang tersedia...", @@ -248,6 +260,12 @@ }, "password": { "placeholder": "kata sandi", + "require": "Your password needs at least:", + "character_limit": "8 characters", + "accessibility": { + "checked": "checked", + "unchecked": "unchecked" + }, "hint": "Kata sandi Anda harus memiliki sekurang-kurangnya delapan karakter" }, "invite": { @@ -298,7 +316,7 @@ "subtitle": "Kami baru saja mengirim sebuah surel ke %s,\nketuk tautannya untuk mengkonfirmasi akun Anda.", "button": { "open_email_app": "Buka Aplikasi Surel", - "dont_receive_email": "Saya tidak mendapatkan surel" + "resend": "Resend" }, "dont_receive_email": { "title": "Periksa surel Anda", @@ -401,15 +419,25 @@ "segmented_control": { "posts": "Postingan", "replies": "Balasan", - "media": "Media" + "posts_and_replies": "Posts and Replies", + "media": "Media", + "about": "About" }, "relationship_action_alert": { + "confirm_mute_user": { + "title": "Mute Account", + "message": "Confirm to mute %s" + }, "confirm_unmute_user": { "title": "Berhenti Membisukan Akun", "message": "Confirm to unmute %s" }, - "confirm_unblock_usre": { - "title": "Berhenti Memblokir Akun", + "confirm_block_user": { + "title": "Block Account", + "message": "Confirm to block %s" + }, + "confirm_unblock_user": { + "title": "Unblock Account", "message": "Confirm to unblock %s" } } @@ -461,12 +489,14 @@ "Everything": "Segalanya", "Mentions": "Sebutan" }, - "user_followed_you": "%s mengikuti Anda", - "user_favorited your post": "%s favorited your post", - "user_reblogged_your_post": "%s reblogged your post", - "user_mentioned_you": "%s menyebut Anda", - "user_requested_to_follow_you": "%s ingin mengikuti Anda", - "user_your_poll_has_ended": "%s Japat Anda telah berakhir", + "notification_description": { + "followed_you": "followed you", + "favorited_your_post": "favorited your post", + "reblogged_your_post": "reblogged your post", + "mentioned_you": "mentioned you", + "request_to_follow_you": "request to follow you", + "poll_has_ended": "poll has ended" + }, "keyobard": { "show_everything": "Tampilkan Segalanya", "show_mentions": "Tampilkan Sebutan" @@ -485,6 +515,13 @@ "light": "Selalu Cerah", "dark": "Selalu Gelap" }, + "look_and_feel": { + "title": "Look and Feel", + "use_system": "Use System", + "really_dark": "Really Dark", + "sorta_dark": "Sorta Dark", + "light": "Light" + }, "notifications": { "title": "Notifikasi", "favorites": "Favorites my post", @@ -526,14 +563,17 @@ } }, "report": { + "title_report": "Report", "title": "Laporkan %s", "step1": "Langkah 1 dari 2", "step2": "Langkah 2 dari 2", "content1": "Apakah ada postingan lain yang ingin Anda tambahkan ke laporannya?", "content2": "Ada yang moderator harus tahu tentang laporan ini?", + "report_sent_title": "Thanks for reporting, we’ll look into this.", "send": "Kirim Laporan", "skip_to_send": "Kirim tanpa komentar", - "text_placeholder": "Ketik atau tempel komentar tambahan" + "text_placeholder": "Ketik atau tempel komentar tambahan", + "reported": "REPORTED" }, "preview": { "keyboard": { diff --git a/Localization/StringsConvertor/input/it_IT/Localizable.stringsdict b/Localization/StringsConvertor/input/it_IT/Localizable.stringsdict new file mode 100644 index 00000000..730e2902 --- /dev/null +++ b/Localization/StringsConvertor/input/it_IT/Localizable.stringsdict @@ -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 unread notification</string> + <key>other</key> + <string>%ld unread notification</string> + </dict> + </dict> + <key>a11y.plural.count.input_limit_exceeds</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>Input limit exceeds %#@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 character</string> + <key>other</key> + <string>%ld characters</string> + </dict> + </dict> + <key>a11y.plural.count.input_limit_remains</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>Input limit remains %#@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 character</string> + <key>other</key> + <string>%ld characters</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>post</string> + <key>other</key> + <string>posts</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 post</string> + <key>other</key> + <string>%ld posts</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 favorite</string> + <key>other</key> + <string>%ld favorites</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 reblog</string> + <key>other</key> + <string>%ld reblogs</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 vote</string> + <key>other</key> + <string>%ld votes</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 voter</string> + <key>other</key> + <string>%ld voters</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 people talking</string> + <key>other</key> + <string>%ld people talking</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 following</string> + <key>other</key> + <string>%ld following</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 follower</string> + <key>other</key> + <string>%ld followers</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 year left</string> + <key>other</key> + <string>%ld years left</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 months left</string> + <key>other</key> + <string>%ld months left</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 day left</string> + <key>other</key> + <string>%ld days left</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 hour left</string> + <key>other</key> + <string>%ld hours left</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 minute left</string> + <key>other</key> + <string>%ld minutes left</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 second left</string> + <key>other</key> + <string>%ld seconds left</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>1y ago</string> + <key>other</key> + <string>%ldy ago</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>1M ago</string> + <key>other</key> + <string>%ldM ago</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>1d ago</string> + <key>other</key> + <string>%ldd ago</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>1h ago</string> + <key>other</key> + <string>%ldh ago</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>1m ago</string> + <key>other</key> + <string>%ldm ago</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>1s ago</string> + <key>other</key> + <string>%lds ago</string> + </dict> + </dict> + </dict> +</plist> diff --git a/Localization/StringsConvertor/input/it_IT/app.json b/Localization/StringsConvertor/input/it_IT/app.json new file mode 100644 index 00000000..ad99e178 --- /dev/null +++ b/Localization/StringsConvertor/input/it_IT/app.json @@ -0,0 +1,596 @@ +{ + "common": { + "alerts": { + "common": { + "please_try_again": "Please try again.", + "please_try_again_later": "Please try again later." + }, + "sign_up_failure": { + "title": "Sign Up Failure" + }, + "server_error": { + "title": "Server Error" + }, + "vote_failure": { + "title": "Vote Failure", + "poll_ended": "The poll has ended" + }, + "discard_post_content": { + "title": "Discard Draft", + "message": "Confirm to discard composed post content." + }, + "publish_post_failure": { + "title": "Publish Failure", + "message": "Failed to publish the post.\nPlease check your internet connection.", + "attachments_message": { + "video_attach_with_photo": "Cannot attach a video to a post that already contains images.", + "more_than_one_video": "Cannot attach more than one video." + } + }, + "edit_profile_failure": { + "title": "Edit Profile Error", + "message": "Cannot edit profile. Please try again." + }, + "sign_out": { + "title": "Sign Out", + "message": "Are you sure you want to sign out?", + "confirm": "Sign Out" + }, + "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.", + "block_entire_domain": "Block Domain" + }, + "save_photo_failure": { + "title": "Save Photo Failure", + "message": "Please enable the photo library access permission to save the photo." + }, + "delete_post": { + "title": "Delete Post", + "message": "Are you sure you want to delete this post?" + }, + "clean_cache": { + "title": "Clean Cache", + "message": "Successfully cleaned %s cache." + } + }, + "controls": { + "actions": { + "back": "Back", + "next": "Next", + "previous": "Previous", + "open": "Open", + "add": "Add", + "remove": "Remove", + "edit": "Edit", + "save": "Save", + "ok": "OK", + "done": "Done", + "confirm": "Confirm", + "continue": "Continue", + "compose": "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": "Share %s", + "share_post": "Share Post", + "open_in_safari": "Open in Safari", + "open_in_browser": "Open in Browser", + "find_people": "Find people to follow", + "manually_search": "Manually search instead", + "skip": "Skip", + "reply": "Reply", + "report_user": "Report %s", + "block_domain": "Block %s", + "unblock_domain": "Unblock %s", + "settings": "Settings", + "delete": "Delete" + }, + "tabs": { + "home": "Home", + "search": "Search", + "notification": "Notification", + "profile": "Profile" + }, + "keyboard": { + "common": { + "switch_to_tab": "Switch to %s", + "compose_new_post": "Compose New Post", + "show_favorites": "Show Favorites", + "open_settings": "Open Settings" + }, + "timeline": { + "previous_status": "Previous Post", + "next_status": "Next Post", + "open_status": "Open Post", + "open_author_profile": "Open Author's Profile", + "open_reblogger_profile": "Open Reblogger's Profile", + "reply_status": "Reply to Post", + "toggle_reblog": "Toggle Reblog on Post", + "toggle_favorite": "Toggle Favorite on Post", + "toggle_content_warning": "Toggle Content Warning", + "preview_image": "Preview Image" + }, + "segmented_control": { + "previous_section": "Previous Section", + "next_section": "Next Section" + } + }, + "status": { + "user_reblogged": "%s reblogged", + "user_replied_to": "Replied to %s", + "show_post": "Show Post", + "show_user_profile": "Show user profile", + "content_warning": "Content Warning", + "media_content_warning": "Tap anywhere to reveal", + "poll": { + "vote": "Vote", + "closed": "Closed" + }, + "actions": { + "reply": "Reply", + "reblog": "Reblog", + "unreblog": "Undo reblog", + "favorite": "Favorite", + "unfavorite": "Unfavorite", + "menu": "Menu", + "hide": "Hide" + }, + "tag": { + "url": "URL", + "mention": "Mention", + "link": "Link", + "hashtag": "Hashtag", + "email": "Email", + "emoji": "Emoji" + }, + "visibility": { + "unlisted": "Everyone can see this post but not display in the public timeline.", + "private": "Only their followers can see this post.", + "private_from_me": "Only my followers can see this post.", + "direct": "Only mentioned user can see this post." + } + }, + "friendship": { + "follow": "Follow", + "following": "Following", + "request": "Request", + "pending": "Pending", + "block": "Block", + "block_user": "Block %s", + "block_domain": "Block %s", + "unblock": "Unblock", + "unblock_user": "Unblock %s", + "blocked": "Blocked", + "mute": "Mute", + "mute_user": "Mute %s", + "unmute": "Unmute", + "unmute_user": "Unmute %s", + "muted": "Muted", + "edit_info": "Edit Info" + }, + "timeline": { + "filtered": "Filtered", + "timestamp": { + "now": "Now" + }, + "loader": { + "load_missing_posts": "Load missing posts", + "loading_missing_posts": "Loading missing posts...", + "show_more_replies": "Show more replies" + }, + "header": { + "no_status_found": "No Post Found", + "blocking_warning": "You can’t view this user's profile\nuntil you unblock them.\nYour profile looks like this to them.", + "user_blocking_warning": "You can’t view %s’s profile\nuntil you unblock them.\nYour profile looks like this to them.", + "blocked_warning": "You can’t view this user’s profile\nuntil they unblock you.", + "user_blocked_warning": "You can’t view %s’s profile\nuntil they unblock you.", + "suspended_warning": "This user has been suspended.", + "user_suspended_warning": "%s’s account has been suspended." + } + } + } + }, + "scene": { + "welcome": { + "slogan": "Social networking\nback in your hands.", + "get_started": "Get Started", + "log_in": "Log In" + }, + "server_picker": { + "title": "Mastodon is made of users in different communities.", + "subtitle": "Pick a community based on your interests, region, or a general purpose one.", + "subtitle_extend": "Pick a community based on your interests, region, or a general purpose one. Each community is operated by an entirely independent organization or individual.", + "button": { + "category": { + "all": "All", + "all_accessiblity_description": "Category: All", + "academia": "academia", + "activism": "activism", + "food": "food", + "furry": "furry", + "games": "games", + "general": "general", + "journalism": "journalism", + "lgbt": "lgbt", + "regional": "regional", + "art": "art", + "music": "music", + "tech": "tech" + }, + "see_less": "See Less", + "see_more": "See More" + }, + "label": { + "language": "LANGUAGE", + "users": "USERS", + "category": "CATEGORY" + }, + "input": { + "placeholder": "Search communities" + }, + "empty_state": { + "finding_servers": "Finding available servers...", + "bad_network": "Something went wrong while loading the data. Check your internet connection.", + "no_results": "No results" + } + }, + "register": { + "title": "Let’s get you set up on %s", + "input": { + "avatar": { + "delete": "Delete" + }, + "username": { + "placeholder": "username", + "duplicate_prompt": "This username is taken." + }, + "display_name": { + "placeholder": "display name" + }, + "email": { + "placeholder": "email" + }, + "password": { + "placeholder": "password", + "require": "Your password needs at least:", + "character_limit": "8 characters", + "accessibility": { + "checked": "checked", + "unchecked": "unchecked" + }, + "hint": "Your password needs at least eight characters" + }, + "invite": { + "registration_user_invite_request": "Why do you want to join?" + } + }, + "error": { + "item": { + "username": "Username", + "email": "Email", + "password": "Password", + "agreement": "Agreement", + "locale": "Locale", + "reason": "Reason" + }, + "reason": { + "blocked": "%s contains a disallowed email provider", + "unreachable": "%s does not seem to exist", + "taken": "%s is already in use", + "reserved": "%s is a reserved keyword", + "accepted": "%s must be accepted", + "blank": "%s is required", + "invalid": "%s is invalid", + "too_long": "%s is too long", + "too_short": "%s is too short", + "inclusion": "%s is not a supported value" + }, + "special": { + "username_invalid": "Username must only contain alphanumeric characters and underscores", + "username_too_long": "Username is too long (can’t be longer than 30 characters)", + "email_invalid": "This is not a valid email address", + "password_too_short": "Password is too short (must be at least 8 characters)" + } + } + }, + "server_rules": { + "title": "Some ground rules.", + "subtitle": "These are set and enforced by the %s moderators.", + "prompt": "By continuing, you’re subject to the terms of service and privacy policy for %s.", + "terms_of_service": "terms of service", + "privacy_policy": "privacy policy", + "button": { + "confirm": "I Agree" + } + }, + "confirm_email": { + "title": "One last thing.", + "subtitle": "Tap the link we emailed to you to verify your account.", + "button": { + "open_email_app": "Open Email App", + "resend": "Resend" + }, + "dont_receive_email": { + "title": "Check your email", + "description": "Check if your email address is correct as well as your junk folder if you haven’t.", + "resend_email": "Resend Email" + }, + "open_email_app": { + "title": "Check your inbox.", + "description": "We just sent you an email. Check your junk folder if you haven’t.", + "mail": "Mail", + "open_email_client": "Open Email Client" + } + }, + "home_timeline": { + "title": "Home", + "navigation_bar_state": { + "offline": "Offline", + "new_posts": "See new posts", + "published": "Published!", + "Publishing": "Publishing post..." + } + }, + "suggestion_account": { + "title": "Find People to Follow", + "follow_explain": "When you follow someone, you’ll see their posts in your home feed." + }, + "compose": { + "title": { + "new_post": "New Post", + "new_reply": "New Reply" + }, + "media_selection": { + "camera": "Take Photo", + "photo_library": "Photo Library", + "browse": "Browse" + }, + "content_input_placeholder": "Type or paste what’s on your mind", + "compose_action": "Publish", + "replying_to_user": "replying to %s", + "attachment": { + "photo": "photo", + "video": "video", + "attachment_broken": "This %s is broken and can’t be\nuploaded to Mastodon.", + "description_photo": "Describe the photo for the visually-impaired...", + "description_video": "Describe the video for the visually-impaired..." + }, + "poll": { + "duration_time": "Duration: %s", + "thirty_minutes": "30 minutes", + "one_hour": "1 Hour", + "six_hours": "6 Hours", + "one_day": "1 Day", + "three_days": "3 Days", + "seven_days": "7 Days", + "option_number": "Option %ld" + }, + "content_warning": { + "placeholder": "Write an accurate warning here..." + }, + "visibility": { + "public": "Public", + "unlisted": "Unlisted", + "private": "Followers only", + "direct": "Only people I mention" + }, + "auto_complete": { + "space_to_add": "Space to add" + }, + "accessibility": { + "append_attachment": "Add Attachment", + "append_poll": "Add 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" + }, + "keyboard": { + "discard_post": "Discard Post", + "publish_post": "Publish Post", + "toggle_poll": "Toggle Poll", + "toggle_content_warning": "Toggle Content Warning", + "append_attachment_entry": "Add Attachment - %s", + "select_visibility_entry": "Select Visibility - %s" + } + }, + "profile": { + "dashboard": { + "posts": "posts", + "following": "following", + "followers": "followers" + }, + "fields": { + "add_row": "Add Row", + "placeholder": { + "label": "Label", + "content": "Content" + } + }, + "segmented_control": { + "posts": "Posts", + "replies": "Replies", + "posts_and_replies": "Posts and Replies", + "media": "Media", + "about": "About" + }, + "relationship_action_alert": { + "confirm_mute_user": { + "title": "Mute Account", + "message": "Confirm to mute %s" + }, + "confirm_unmute_user": { + "title": "Unmute Account", + "message": "Confirm to unmute %s" + }, + "confirm_block_user": { + "title": "Block Account", + "message": "Confirm to block %s" + }, + "confirm_unblock_user": { + "title": "Unblock Account", + "message": "Confirm to unblock %s" + } + } + }, + "follower": { + "footer": "Followers from other servers are not displayed." + }, + "following": { + "footer": "Follows from other servers are not displayed." + }, + "search": { + "title": "Search", + "search_bar": { + "placeholder": "Search hashtags and users", + "cancel": "Cancel" + }, + "recommend": { + "button_text": "See All", + "hash_tag": { + "title": "Trending on Mastodon", + "description": "Hashtags that are getting quite a bit of attention", + "people_talking": "%s people are talking" + }, + "accounts": { + "title": "Accounts you might like", + "description": "You may like to follow these accounts", + "follow": "Follow" + } + }, + "searching": { + "segment": { + "all": "All", + "people": "People", + "hashtags": "Hashtags", + "posts": "Posts" + }, + "empty_state": { + "no_results": "No results" + }, + "recent_search": "Recent searches", + "clear": "Clear" + } + }, + "favorite": { + "title": "Your Favorites" + }, + "notification": { + "title": { + "Everything": "Everything", + "Mentions": "Mentions" + }, + "notification_description": { + "followed_you": "followed you", + "favorited_your_post": "favorited your post", + "reblogged_your_post": "reblogged your post", + "mentioned_you": "mentioned you", + "request_to_follow_you": "request to follow you", + "poll_has_ended": "poll has ended" + }, + "keyobard": { + "show_everything": "Show Everything", + "show_mentions": "Show Mentions" + } + }, + "thread": { + "back_title": "Post", + "title": "Post from %s" + }, + "settings": { + "title": "Settings", + "section": { + "appearance": { + "title": "Appearance", + "automatic": "Automatic", + "light": "Always Light", + "dark": "Always Dark" + }, + "look_and_feel": { + "title": "Look and Feel", + "use_system": "Use System", + "really_dark": "Really Dark", + "sorta_dark": "Sorta Dark", + "light": "Light" + }, + "notifications": { + "title": "Notifications", + "favorites": "Favorites my post", + "follows": "Follows me", + "boosts": "Reblogs my post", + "mentions": "Mentions me", + "trigger": { + "anyone": "anyone", + "follower": "a follower", + "follow": "anyone I follow", + "noone": "no one", + "title": "Notify me when" + } + }, + "preference": { + "title": "Preferences", + "true_black_dark_mode": "True black dark mode", + "disable_avatar_animation": "Disable animated avatars", + "disable_emoji_animation": "Disable animated emojis", + "using_default_browser": "Use default browser to open links" + }, + "boring_zone": { + "title": "The Boring Zone", + "account_settings": "Account Settings", + "terms": "Terms of Service", + "privacy": "Privacy Policy" + }, + "spicy_zone": { + "title": "The Spicy Zone", + "clear": "Clear Media Cache", + "signout": "Sign Out" + } + }, + "footer": { + "mastodon_description": "Mastodon is open source software. You can report issues on GitHub at %s (%s)" + }, + "keyboard": { + "close_settings_window": "Close Settings Window" + } + }, + "report": { + "title_report": "Report", + "title": "Report %s", + "step1": "Step 1 of 2", + "step2": "Step 2 of 2", + "content1": "Are there any other posts you’d like to add to the report?", + "content2": "Is there anything the moderators should know about this report?", + "report_sent_title": "Thanks for reporting, we’ll look into this.", + "send": "Send Report", + "skip_to_send": "Send without comment", + "text_placeholder": "Type or paste additional comments", + "reported": "REPORTED" + }, + "preview": { + "keyboard": { + "close_preview": "Close Preview", + "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" + } + } +} \ No newline at end of file diff --git a/Localization/StringsConvertor/input/it_IT/ios-infoPlist.json b/Localization/StringsConvertor/input/it_IT/ios-infoPlist.json new file mode 100644 index 00000000..c6db73de --- /dev/null +++ b/Localization/StringsConvertor/input/it_IT/ios-infoPlist.json @@ -0,0 +1,6 @@ +{ + "NSCameraUsageDescription": "Used to take photo for post status", + "NSPhotoLibraryAddUsageDescription": "Used to save photo into the Photo Library", + "NewPostShortcutItemTitle": "New Post", + "SearchShortcutItemTitle": "Search" +} diff --git a/Localization/StringsConvertor/input/ja_JP/Localizable.stringsdict b/Localization/StringsConvertor/input/ja_JP/Localizable.stringsdict index c51a9a29..f1c5e6e2 100644 --- a/Localization/StringsConvertor/input/ja_JP/Localizable.stringsdict +++ b/Localization/StringsConvertor/input/ja_JP/Localizable.stringsdict @@ -279,7 +279,7 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>other</key> - <string>%ld分前</string> + <string>%ldか月前</string> </dict> </dict> <key>date.day.ago.abbr</key> diff --git a/Localization/StringsConvertor/input/ja_JP/app.json b/Localization/StringsConvertor/input/ja_JP/app.json index 417ca3e3..7ddfa51c 100644 --- a/Localization/StringsConvertor/input/ja_JP/app.json +++ b/Localization/StringsConvertor/input/ja_JP/app.json @@ -23,7 +23,7 @@ "title": "失敗", "message": "投稿に失敗しました。\nインターネットに接続されているか確認してください。", "attachments_message": { - "video_attach_with_photo": "すでに画像が含まれている投稿に、動画を添付することができません。", + "video_attach_with_photo": "すでに画像が含まれている投稿に、動画を添付することはできません。", "more_than_one_video": "複数の動画を添付することはできません。" } }, @@ -46,7 +46,7 @@ }, "delete_post": { "title": "この投稿を消去しますか?", - "delete": "消去" + "message": "本当に削除しますか?" }, "clean_cache": { "title": "キャッシュを消去", @@ -67,7 +67,7 @@ "done": "完了", "confirm": "確認", "continue": "続ける", - "compose": "Compose", + "compose": "新規作成", "cancel": "キャンセル", "discard": "破棄", "try_again": "再実行", @@ -82,11 +82,12 @@ "share_user": "%sを共有", "share_post": "投稿を共有", "open_in_safari": "Safariで開く", + "open_in_browser": "ブラウザで開く", "find_people": "フォローする人を見つける", "manually_search": "手動で検索する", "skip": "スキップ", "reply": "リプライ", - "report_user": "%sを報告", + "report_user": "%sを通報", "block_domain": "%sをブロック", "unblock_domain": "%sのブロックを解除", "settings": "設定", @@ -139,7 +140,8 @@ "unreblog": "ブーストを戻す", "favorite": "お気に入り", "unfavorite": "お気に入り登録を取り消す", - "menu": "メニュー" + "menu": "メニュー", + "hide": "非表示" }, "tag": { "url": "URL", @@ -148,6 +150,12 @@ "hashtag": "ハッシュタグ", "email": "メール", "emoji": "絵文字" + }, + "visibility": { + "unlisted": "この投稿は誰でも見ることができますが、公開タイムラインには表示されません。", + "private": "この投稿はフォロワーに限り見ることができます。", + "private_from_me": "この投稿はフォロワーに限り見ることができます。", + "direct": "この投稿はメンションされたユーザーに限り見ることができます。" } }, "friendship": { @@ -192,10 +200,14 @@ }, "scene": { "welcome": { - "slogan": "ソーシャルネットワーキングを、あなたの手の中に." + "slogan": "ソーシャルネットワーキングを、あなたの手の中に.", + "get_started": "Get Started", + "log_in": "ログイン" }, "server_picker": { "title": "サーバーを選択", + "subtitle": "あなたの興味分野・地域に合ったコミュニティや、汎用のものを選択してください。", + "subtitle_extend": "あなたの興味分野・地域に合ったコミュニティや、汎用のものを選択してください。各コミュニティはそれぞれ完全に独立した組織や個人によって運営されています。", "button": { "category": { "all": "すべて", @@ -203,7 +215,7 @@ "academia": "アカデミア", "activism": "アクティビズム", "food": "食べ物", - "furry": "furry", + "furry": "ケモノ", "games": "ゲーム", "general": "全般", "journalism": "言論", @@ -248,6 +260,12 @@ }, "password": { "placeholder": "パスワード", + "require": "Your password needs at least:", + "character_limit": "8 characters", + "accessibility": { + "checked": "checked", + "unchecked": "unchecked" + }, "hint": "パスワードは最低でも8文字必要です。" }, "invite": { @@ -298,7 +316,7 @@ "subtitle": "先程 %s にメールを送信しました。リンクをタップしてアカウントを確認してください。", "button": { "open_email_app": "メールアプリを開く", - "dont_receive_email": "メールがこない" + "resend": "Resend" }, "dont_receive_email": { "title": "メールをチェックしてください", @@ -342,8 +360,8 @@ "photo": "写真", "video": "動画", "attachment_broken": "%sは壊れていてMastodonにアップロードできません。", - "description_photo": "視覚障がい者のために写真を説明", - "description_video": "視覚障がい者のための映像の説明" + "description_photo": "閲覧が難しいユーザーへの画像説明", + "description_video": "閲覧が難しいユーザーへの映像説明" }, "poll": { "duration_time": "期間: %s", @@ -401,24 +419,34 @@ "segmented_control": { "posts": "投稿", "replies": "リプライ", - "media": "メディア" + "posts_and_replies": "Posts and Replies", + "media": "メディア", + "about": "About" }, "relationship_action_alert": { + "confirm_mute_user": { + "title": "Mute Account", + "message": "Confirm to mute %s" + }, "confirm_unmute_user": { "title": "ミュートを解除", "message": "%sをミュートしますか?" }, - "confirm_unblock_usre": { - "title": "ブロックを解除", - "message": "%sのブロックを解除しますか?" + "confirm_block_user": { + "title": "Block Account", + "message": "Confirm to block %s" + }, + "confirm_unblock_user": { + "title": "Unblock Account", + "message": "Confirm to unblock %s" } } }, "follower": { - "footer": "Followers from other servers are not displayed." + "footer": "他のサーバーからのフォロワーは表示されません。" }, "following": { - "footer": "Follows from other servers are not displayed." + "footer": "他のサーバーにいるフォローは表示されません。" }, "search": { "title": "検索", @@ -461,12 +489,14 @@ "Everything": "すべて", "Mentions": "メンション" }, - "user_followed_you": "%s にフォローされました", - "user_favorited your post": "%s がお気に入り登録しました", - "user_reblogged_your_post": "%s がブーストしました", - "user_mentioned_you": "%s に返信されました", - "user_requested_to_follow_you": "%s がフォローリクエストを送信しました", - "user_your_poll_has_ended": "%s 投票が終了しました", + "notification_description": { + "followed_you": "followed you", + "favorited_your_post": "favorited your post", + "reblogged_your_post": "reblogged your post", + "mentioned_you": "mentioned you", + "request_to_follow_you": "request to follow you", + "poll_has_ended": "poll has ended" + }, "keyobard": { "show_everything": "すべて見る", "show_mentions": "メンションを見る" @@ -485,6 +515,13 @@ "light": "ライト", "dark": "ダーク" }, + "look_and_feel": { + "title": "Look and Feel", + "use_system": "Use System", + "really_dark": "Really Dark", + "sorta_dark": "Sorta Dark", + "light": "Light" + }, "notifications": { "title": "通知", "favorites": "お気に入り登録", @@ -502,7 +539,7 @@ "preference": { "title": "環境設定", "true_black_dark_mode": "真っ黒なダークテーマを使用する", - "disable_avatar_animation": "アニメーションアバターの無効化する", + "disable_avatar_animation": "アバターのアニメーションを無効化する", "disable_emoji_animation": "絵文字のアニメーションを無効化する", "using_default_browser": "既定のブラウザでリンクを開く" }, @@ -526,14 +563,17 @@ } }, "report": { - "title": "%sを報告", + "title_report": "Report", + "title": "%sを通報", "step1": "ステップ 1/2", "step2": "ステップ 2/2", - "content1": "他に報告したい投稿はありますか?", - "content2": "この報告についてモデレーターに言いたいことはありますか?", - "send": "報告を送信", + "content1": "他に通報したい投稿はありますか?", + "content2": "この通報についてモデレーターに伝達しておきたい事項はありますか?", + "report_sent_title": "Thanks for reporting, we’ll look into this.", + "send": "通報を送信", "skip_to_send": "コメントなしで送信", - "text_placeholder": "追加コメントを入力" + "text_placeholder": "追加コメントを入力", + "reported": "REPORTED" }, "preview": { "keyboard": { @@ -543,14 +583,14 @@ } }, "account_list": { - "tab_bar_hint": "Current selected profile: %s. Double tap then hold to show account switcher", - "dismiss_account_switcher": "Dismiss Account Switcher", + "tab_bar_hint": "現在のアカウント: %s. ダブルタップしてアカウント切替画面を表示します", + "dismiss_account_switcher": "アカウント切替画面を閉じます", "add_account": "アカウントを追加" }, "wizard": { "new_in_mastodon": "Mastodon の新機能", "multiple_account_switch_intro_description": "プロフィールボタンを押して複数のアカウントを切り替えます。", - "accessibility_hint": "Double tap to dismiss this wizard" + "accessibility_hint": "チュートリアルを閉じるには、ダブルタップしてください" } } } \ No newline at end of file diff --git a/Localization/StringsConvertor/input/kab_KAB/Localizable.stringsdict b/Localization/StringsConvertor/input/kab_KAB/Localizable.stringsdict new file mode 100644 index 00000000..8a2bac9e --- /dev/null +++ b/Localization/StringsConvertor/input/kab_KAB/Localizable.stringsdict @@ -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 wulɣu ur nettwaɣra</string> + <key>other</key> + <string>%ld yilɣa ur nettwaɣra</string> + </dict> + </dict> + <key>a11y.plural.count.input_limit_exceeds</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>Talast n unekcum tɛedda %#@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 usekkil</string> + <key>other</key> + <string>%ld yisekkilen</string> + </dict> + </dict> + <key>a11y.plural.count.input_limit_remains</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>Talast n unekcum yeqqim-d seg-s %#@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 usekkil</string> + <key>other</key> + <string>%ld yisekkilen</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>tasuffeɣt</string> + <key>other</key> + <string>tisuffaɣ</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 tsuffeɣt</string> + <key>other</key> + <string>%ld n tsuffaɣ</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>1unurif</string> + <key>other</key> + <string>%ld yinurifen</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>1uɛiwed n usuffeɣ</string> + <key>other</key> + <string>%ld n uɛiwed n usuffeɣ</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 tefrant</string> + <key>other</key> + <string>%ld tefranin</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>1umefran</string> + <key>other</key> + <string>%ld imefranen</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 umdan i yettmeslayen</string> + <key>other</key> + <string>%ld yimdanen i yettmeslayen</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 uneḍfar</string> + <key>other</key> + <string>%ld yineḍfaren</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 uneḍfar</string> + <key>other</key> + <string>%ld yineḍfaren</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>Yeqqim-d 1 useggas</string> + <key>other</key> + <string>Qqimen-d %ld yiseggasen</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 wayyur i d-yeqqimen</string> + <key>other</key> + <string>%ld wayyuren i d-yeqqimen</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>Yeqqim-d 1 wass</string> + <key>other</key> + <string>Qqimen-d %ld wussan</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>Yeqqim-d 1 usrag</string> + <key>other</key> + <string>Qqimen-d %ld yisragen</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 tesdat i d-yeqqimen</string> + <key>other</key> + <string>%ld tesdatin i d-yeqqimen</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 tasint i d-yeqqimen</string> + <key>other</key> + <string>%ld tsinin i d-yeqqimen</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 useggas aya</string> + <key>other</key> + <string>%ld yiseggasen aya</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 wayyur aya</string> + <key>other</key> + <string>%ld wayyuren aya</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 wass aya</string> + <key>other</key> + <string>%ld wussan aya</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 usrag aya</string> + <key>other</key> + <string>%ld yisragen aya</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 tesdat aya</string> + <key>other</key> + <string>%ld tesdatin aya</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 tasint aya</string> + <key>other</key> + <string>%ld tsinin aya</string> + </dict> + </dict> + </dict> +</plist> diff --git a/Localization/StringsConvertor/input/kab_KAB/app.json b/Localization/StringsConvertor/input/kab_KAB/app.json new file mode 100644 index 00000000..74c16795 --- /dev/null +++ b/Localization/StringsConvertor/input/kab_KAB/app.json @@ -0,0 +1,596 @@ +{ + "common": { + "alerts": { + "common": { + "please_try_again": "Ttxil εreḍ tikelt-nniḍen.", + "please_try_again_later": "Ttxil εreḍ tikelt-nniḍen ticki." + }, + "sign_up_failure": { + "title": "Tuccḍa deg unekcum" + }, + "server_error": { + "title": "Tuccḍa n uqeddac" + }, + "vote_failure": { + "title": "Tuccḍa deg ufran", + "poll_ended": "Tafrant tfuk" + }, + "discard_post_content": { + "title": "Kkes arewway", + "message": "Sentem i wakken ad yettusefsax ugbur n tsuffeɣt." + }, + "publish_post_failure": { + "title": "Yecceḍ usuffeɣ", + "message": "Yecceḍ usuffeɣ n tsuffeɣt.\nMa ulac aɣilif, senqed tuqqna-inek internet.", + "attachments_message": { + "video_attach_with_photo": "Ur tezmireḍ ara ad tsedduḍ tavidyut deg tsuffeɣt ideg llant yakan tugniwin.", + "more_than_one_video": "Ur tezmireḍ ara ad ugar n tvidyut." + } + }, + "edit_profile_failure": { + "title": "Ẓreg tuccḍa n umaɣnu", + "message": "Yegguma ad yettwaẓreg umaɣnu. Ɛreḍ tikkelt-nniḍen." + }, + "sign_out": { + "title": "Ffeɣ", + "message": "Tebɣiḍ ad teffɣeḍ?", + "confirm": "Ffeɣ" + }, + "block_domain": { + "title": "D tidet, d tidet tebɣiḍ ad tesweḥleḍ %s akken ma yella? Deg tuget, kra n yisewḥal d ugdal ad yili d ayen iwulmen, yettwafernen. Ur tettwaliḍ ara agbur seg taɣult-nni neɣ kra seg yineḍfaren-ik i tt-yesseqdacen.", + "block_entire_domain": "Sewḥel taɣult" + }, + "save_photo_failure": { + "title": "Tuccḍa deg usekles n tewlaft", + "message": "Ma ulac aɣilif, rmed tasiregt n unekcum ɣer temkarḍit n tewlafin i usekles n tewlaft." + }, + "delete_post": { + "title": "Tebɣiḍ s tidet ad tekkseḍ tasuffeɣt-agi?", + "message": "Tebɣiḍ s tidet ad tekkseḍ tasuffeɣt-agi?" + }, + "clean_cache": { + "title": "Sfeḍ tuffirt", + "message": "Yettwasfeḍ %s n tkatut tuffirt akken iwata." + } + }, + "controls": { + "actions": { + "back": "Tuɣalin", + "next": "Uḍfir", + "previous": "Uzwir", + "open": "Ldi", + "add": "Rnu", + "remove": "Kkes", + "edit": "Ẓreg", + "save": "Sekles", + "ok": "IH", + "done": "Immed", + "confirm": "Sentem", + "continue": "Kemmel", + "compose": "Sudes", + "cancel": "Sefsex", + "discard": "Sefsex", + "try_again": "Ɛreḍ tikkelt-nniḍen", + "take_photo": "Ṭṭef tawlaft", + "save_photo": "Sekles tawlaft", + "copy_photo": "Nɣel tawlaft", + "sign_in": "Qqen", + "sign_up": "Jerred amiḍan", + "see_more": "Wali ugar", + "preview": "Taskant", + "share": "Bḍu", + "share_user": "Bḍu %s", + "share_post": "Bḍu tasuffeɣt", + "open_in_safari": "Ldi deg Safari", + "open_in_browser": "Ldi deg yiminig", + "find_people": "Af imdanen ara tḍefreḍ", + "manually_search": "Anadi s ufus deg wadeg-is", + "skip": "Zgel", + "reply": "Err", + "report_user": "Cetki ɣef %s", + "block_domain": "Sewḥel %s", + "unblock_domain": "Serreḥ i %s", + "settings": "Iɣewwaṛen", + "delete": "Kkes" + }, + "tabs": { + "home": "Agejdan", + "search": "Nadi", + "notification": "Tilɣa", + "profile": "Amaɣnu" + }, + "keyboard": { + "common": { + "switch_to_tab": "Ddu ɣer %s", + "compose_new_post": "Aru tasuffeɣt tamaynut", + "show_favorites": "Sken-d ismenyifen", + "open_settings": "Ldi iɣewwaren" + }, + "timeline": { + "previous_status": "Amagrad uzwir", + "next_status": "Amagrad uḍfir", + "open_status": "Ldi tasuffeɣt", + "open_author_profile": "Ldi amaɣnu n umeskar", + "open_reblogger_profile": "Ldi amaɣnu n win i yulsen asuffeɣ", + "reply_status": "Err ɣef tsuffeɣt", + "toggle_reblog": "Abeddel n unallas n tsuffeɣt", + "toggle_favorite": "Abeddel n usmenyaf i tsuffeɣt", + "toggle_content_warning": "Beddel alɣu n ugbur", + "preview_image": "Asenqed n tugna" + }, + "segmented_control": { + "previous_section": "Tafrant tuzwirt", + "next_section": "Tigezmi tuḍfirt" + } + }, + "status": { + "user_reblogged": "Tettwasuffeɣ-d %s i tikkelt-nniḍen", + "user_replied_to": "Yerra ɣef %s", + "show_post": "Sken-d tasuffeɣt", + "show_user_profile": "Ssken-d amaɣnu n useqdac", + "content_warning": "Alɣu n ugbur", + "media_content_warning": "Sit anida tebɣiḍ i wakken ad twaliḍ", + "poll": { + "vote": "Dɣeṛ", + "closed": "Ifukk" + }, + "actions": { + "reply": "Err", + "reblog": "Aɛiwed n usuffeɣ", + "unreblog": "Sefsex allus n usuffeɣ", + "favorite": "Anurif", + "unfavorite": "Kkes seg yismenyifen", + "menu": "Umuɣ", + "hide": "Ffer" + }, + "tag": { + "url": "URL", + "mention": "Tabdart", + "link": "Aseɣwen", + "hashtag": "Ahacṭag", + "email": "Imayl", + "emoji": "Emuji" + }, + "visibility": { + "unlisted": "Yal wa yezmer ad iwali tsuffeɣt-a maca ur d-tettwaskaneḍ ara deg yizirig n wakud azayaz.", + "private": "D ineḍfaren-is kan i izemren ad walin tsuffeɣ-a.", + "private_from_me": "D ineḍfaren-is kan i izemren ad walin tsuffeɣ-a.", + "direct": "D ineḍfaren-is kan i izemren ad walin tsuffeɣ-a." + } + }, + "friendship": { + "follow": "Ḍfeṛ", + "following": "Yettwaḍfar", + "request": "Tuttra", + "pending": "Yegguni", + "block": "Sewḥel", + "block_user": "Sewḥel %s", + "block_domain": "Sewḥel %s", + "unblock": "Serreḥ", + "unblock_user": "Serreḥ i %s", + "blocked": "Yettusewḥel", + "mute": "Sgugem", + "mute_user": "Sgugem %s", + "unmute": "Kkes asgugem", + "unmute_user": "Kkes asgugem ɣef %s", + "muted": "Yettwasgugem", + "edit_info": "Ẓreg talɣut" + }, + "timeline": { + "filtered": "Yettwasizdeg", + "timestamp": { + "now": "Tura" + }, + "loader": { + "load_missing_posts": "Sali tisuffaɣ i iruḥen", + "loading_missing_posts": "Asali n tsuffaɣ i iruḥen...", + "show_more_replies": "Ssken-d ugar n tririyin" + }, + "header": { + "no_status_found": "Ulac tasuffeɣt yettwafen", + "blocking_warning": "Ur tezmireḍ ara ad twaliḍ amaɣnu n useqdac-a\nalamma tekkseḍ-as asewḥel.\nAkka i as-d-yettban umaɣnu-inek.", + "user_blocking_warning": "Ur tezmireḍ ara ad twaliḍ amaɣnu n %s\nalamma tekkseḍ-as asewḥel.\nAkka i as-d-yettban umaɣnu-inek.", + "blocked_warning": "Ur tezmireḍ ara ad twaliḍ amaɣnu n useqdac-a\nAkka i as-d-yettban umaɣnu-inek.", + "user_blocked_warning": "Ur tezmireḍ ara ad twaliḍ amaɣnu n %s\nAkka i as-d-yettban umaɣnu-inek.", + "suspended_warning": "Yettwaseḥbes useqdac-a.", + "user_suspended_warning": "Yettwaseḥbes umiḍan n %s." + } + } + } + }, + "scene": { + "welcome": { + "slogan": "Izeḍwa inmettiyen\nuɣalen-d ɣer ufus-ik.", + "get_started": "Aha bdu tura", + "log_in": "Qqen" + }, + "server_picker": { + "title": "Mastodon yettwaxdem i yiseqdacen deg waṭas n temɣiwnin.", + "subtitle": "Fren tamɣiwent almend n wayen tḥemmleḍ, n tmurt-ik neɣ n yiswi-inek amatu.", + "subtitle_extend": "Fren tamɣiwent almend n wayen tḥemmleḍ, n tmurt-ik neɣ n yiswi-inek amatu. Yal tamɣiwent tsedday-itt tkebbanit neɣ amdan ilelliyen.", + "button": { + "category": { + "all": "Akk", + "all_accessiblity_description": "Taggayt: Akk", + "academia": "akadimi", + "activism": "tinuɣmest", + "food": "učči", + "furry": "furry", + "games": "uraren", + "general": "amatu", + "journalism": "taɣamsa", + "lgbt": "lgbt", + "regional": "amnaḍan", + "art": "taẓuri", + "music": "aẓawan", + "tech": "atiknikan" + }, + "see_less": "Sken cwiṭ", + "see_more": "Wali ugar" + }, + "label": { + "language": "TUTLAYT", + "users": "ISEQDACEN", + "category": "TAGGAYT" + }, + "input": { + "placeholder": "Nadi timɣiwnin" + }, + "empty_state": { + "finding_servers": "Tifin n yiqeddacen yellan...", + "bad_network": "Tella-d tuccḍa lawan n usali n yisefka. Senqed tuqqna-ink internet.", + "no_results": "Ulac igemmaḍ" + } + }, + "register": { + "title": "Aha ad nebdu asbadu ɣef %s", + "input": { + "avatar": { + "delete": "Kkes" + }, + "username": { + "placeholder": "isem n useqdac", + "duplicate_prompt": "Isem-ayi n umseqdac yettwaṭṭef yakan." + }, + "display_name": { + "placeholder": "isem ara d-yettwaskanen" + }, + "email": { + "placeholder": "imayl" + }, + "password": { + "placeholder": "awal uffir", + "require": "Awal-ik uffir yesra ma drus:", + "character_limit": "8 n yisekkilen", + "accessibility": { + "checked": "yettwasenqed", + "unchecked": "ur yettwasenqed ara" + }, + "hint": "Awal-ik uffir yesra ma drus ṭam n yisekkilen" + }, + "invite": { + "registration_user_invite_request": "Acimi tebγiḍ ad ternuḍ iman-ik?" + } + }, + "error": { + "item": { + "username": "Isem n useqdac", + "email": "Imayl", + "password": "Awal uffir", + "agreement": "Amtawa", + "locale": "Tadigant", + "reason": "Taɣẓint" + }, + "reason": { + "blocked": "%s deg-s asaǧǧăw n yimayl ur nettusireg ara", + "unreachable": "%s ur yettban ara yella", + "taken": "%s yettwaseqdec yakan", + "reserved": "%s d awal uffir yettwaḥarren", + "accepted": "%s ilaq ad yettwaqbal", + "blank": "isra %s", + "invalid": "%s d arameɣtu", + "too_long": "%s ɣezzif aṭas", + "too_short": "%s wezzil aṭas", + "inclusion": "%s mačči d azal yettusefraken" + }, + "special": { + "username_invalid": "Isem n useqdac ilaq ad yesɛu kan isekkilen igmumḍinen d wid yettujerrden", + "username_too_long": "Isem n useqdac ɣezzif aṭas (ur ilaq ara ad iɛeddi nnig 30 yisekkilen)", + "email_invalid": "Tagi mačči d tansa n yimayl tameɣtut", + "password_too_short": "Awal uffir wezzil aṭas (ilaq ad yesɛu ma drus 8 yisekkilen)" + } + } + }, + "server_rules": { + "title": "Kra n yilugan igejdanen.", + "subtitle": "Ilugan-a ttusbadun sɣur inedbalen n %s.", + "prompt": "Mi ara tkemmleḍ, ilaq ad tqebleḍ tiwtilin n yimeẓla d tsertit tabaḍnit n %s.", + "terms_of_service": "tiwetlin n useqdec", + "privacy_policy": "tasertit tabaḍnit", + "button": { + "confirm": "Qebleɣ" + } + }, + "confirm_email": { + "title": "Taɣawsa taneggarut.", + "subtitle": "Sit ɣef useɣwen i ak-n-uznen i wakken ad tesneqdeḍ amiḍan-ik.", + "button": { + "open_email_app": "Ldi asnas n yimayl", + "resend": "Ales tuzna" + }, + "dont_receive_email": { + "title": "Senqed imayl-ik·im", + "description": "Senqed ma yella tansa-inek n imayl d tameɣut akked uspam ma yella ur t-tufiḍ ara.", + "resend_email": "Ales tuzna n yimayl" + }, + "open_email_app": { + "title": "Sefqed Tanaka-inek.", + "description": "Akken kan i ak-n-nuzen imayl. Sefqed aspam ma yella ur t-tufiḍ ara.", + "mail": "Imayl", + "open_email_client": "Ldi amsaɣ n yimayl" + } + }, + "home_timeline": { + "title": "Agejdan", + "navigation_bar_state": { + "offline": "Beṛṛa n tuqqna", + "new_posts": "Tissufaɣ timaynutin", + "published": "Yettwasuffeɣ!", + "Publishing": "Asuffeɣ tasuffeɣt..." + } + }, + "suggestion_account": { + "title": "Af imdanen ara tḍefreḍ", + "follow_explain": "Mi ara teṭṭafareḍ albaɛḍ, ad twaliḍ tisuffaɣ-is deg usuddem-inek agejdan." + }, + "compose": { + "title": { + "new_post": "Tasuffeɣt tamaynut", + "new_reply": "Tiririt tamaynut" + }, + "media_selection": { + "camera": "Ṭṭef tawlaft", + "photo_library": "Tanedlist n tewlaft", + "browse": "Snirem" + }, + "content_input_placeholder": "Aru neɣ senteḍ ayen yellan deg wallaɣ-ik", + "compose_action": "Sufeɣ", + "replying_to_user": "tiririt ɣef %s", + "attachment": { + "photo": "tawlaft", + "video": "tavidyutt", + "attachment_broken": "%s-a yerreẓ, ur yezmir ara\nAd d-yettwasali ɣef Mastodon.", + "description_photo": "Glem-d tawlaft i wid yesɛan ugur deg yiẓri...", + "description_video": "Glem-d tavidyut i wid yesɛan ugur deg yiẓri..." + }, + "poll": { + "duration_time": "Tangazt: %s", + "thirty_minutes": "30 n tesdatin", + "one_hour": "1 n wesrag", + "six_hours": "6 n yisragen", + "one_day": "1 n wass", + "three_days": "3 n wussan", + "seven_days": "7 n wussan", + "option_number": "Taxtiṛt %ld" + }, + "content_warning": { + "placeholder": "Aru alɣu-inek s telqeyt da..." + }, + "visibility": { + "public": "Azayez", + "unlisted": "War tabdert", + "private": "Imeḍfaṛen kan", + "direct": "Imdanen i d-bedreɣ kan" + }, + "auto_complete": { + "space_to_add": "Tallunt ara yettwarnun" + }, + "accessibility": { + "append_attachment": "Rnu taceqquft yeddan", + "append_poll": "Rnu asenqed", + "remove_poll": "Kkes asenqed", + "custom_emoji_picker": "Amefran n yimujiten udmawanen", + "enable_content_warning": "Rmed alɣu n ugbur", + "disable_content_warning": "Sens alɣu n ugbur", + "post_visibility_menu": "Umuɣ n ubani n tsuffeɣt" + }, + "keyboard": { + "discard_post": "Sefsex tasuffeɣt", + "publish_post": "Suffeɣ tasuffeɣt", + "toggle_poll": "Beddel asenqed", + "toggle_content_warning": "Beddel alɣu n ugbur", + "append_attachment_entry": "Rnu taceqquft yeddan - %s", + "select_visibility_entry": "Fren timeẓriwt - %s" + } + }, + "profile": { + "dashboard": { + "posts": "tisuffaɣ", + "following": "iṭafaṛ", + "followers": "imeḍfaren" + }, + "fields": { + "add_row": "Rnu izirig", + "placeholder": { + "label": "Tabzimt", + "content": "Agbur" + } + }, + "segmented_control": { + "posts": "Imagraden", + "replies": "Tiririyin", + "posts_and_replies": "Tisuffaɣ d tririyin", + "media": "Amidya", + "about": "Ɣef" + }, + "relationship_action_alert": { + "confirm_mute_user": { + "title": "Sgugem amiḍan", + "message": "Sentem asgugem i %s" + }, + "confirm_unmute_user": { + "title": "Kkes asgugem i umiḍan", + "message": "Sentem tukksa n usgugem i %s" + }, + "confirm_block_user": { + "title": "Sewḥel amiḍan", + "message": "Sentem asewḥel n %s" + }, + "confirm_unblock_user": { + "title": "Kkes asewḥel i umiḍan", + "message": "Sentem tukksa n usgugem i %s" + } + } + }, + "follower": { + "footer": "Ineḍfaren seg yiqeddacen-nniḍen ur d-ttwaskanen ara." + }, + "following": { + "footer": "Ineḍfaren seg yiqeddacen-nniḍen ur d-ttwaskanen ara." + }, + "search": { + "title": "Nadi", + "search_bar": { + "placeholder": "Nadi hashtags d yiseqdacen", + "cancel": "Sefsex" + }, + "recommend": { + "button_text": "Wali akk", + "hash_tag": { + "title": "Ayen mucaɛen ɣef Mastodon", + "description": "Hashtags i d-ijebbden aṭas lwelha", + "people_talking": "%s yimdanen i yettmeslayen" + }, + "accounts": { + "title": "Imiḍanen i tzemreḍ ad tḥemmleḍ", + "description": "Ahat tebɣiḍ ad tḍefreḍ imiḍanen-a", + "follow": "Ḍfeṛ" + } + }, + "searching": { + "segment": { + "all": "Akk", + "people": "Imdanen", + "hashtags": "Ihacṭagen", + "posts": "Tisuffaɣ" + }, + "empty_state": { + "no_results": "Ulac igemmaḍ" + }, + "recent_search": "Inadiyen imaynuten", + "clear": "Sfeḍ" + } + }, + "favorite": { + "title": "Ismenyifen-ik·im" + }, + "notification": { + "title": { + "Everything": "Akk", + "Mentions": "Abdar" + }, + "notification_description": { + "followed_you": "iṭṭafar-ik·ikem", + "favorited_your_post": "yesmenyef tasuffeɣt-ik·im", + "reblogged_your_post": "iɛawed-as asuffeɣ i tsuffeɣt-ik·im", + "mentioned_you": "yebder-ik·ikem-id", + "request_to_follow_you": "issuter aḍfar-inek", + "poll_has_ended": "asenqed iffuk" + }, + "keyobard": { + "show_everything": "Sken yal taɣawsa", + "show_mentions": "Sken tisedmirin" + } + }, + "thread": { + "back_title": "Amagrad", + "title": "Tasuffeɣt sɣur %s" + }, + "settings": { + "title": "Iɣewwaṛen", + "section": { + "appearance": { + "title": "Apparence", + "automatic": "Awurman", + "light": "Yezga d aceεlal", + "dark": "Yezga d aberkan" + }, + "look_and_feel": { + "title": "Wali, tḥalfuḍ", + "use_system": "Seqdec anagraw", + "really_dark": "D aberkan s tidet", + "sorta_dark": "D aberkan cwiya", + "light": "Aceɛlal" + }, + "notifications": { + "title": "Tilɣa", + "favorites": "Yerna tasuffeɣt-iw ɣer yismenyafen-ines", + "follows": "Yeṭṭafar-iyi", + "boosts": "Yules asuffeɣ n tduffeɣt-iw", + "mentions": "Ibder-iyi-d", + "trigger": { + "anyone": "yal yiwen", + "follower": "ameḍfar", + "follow": "yal win ara ḍefreɣ", + "noone": "ula yiwen", + "title": "Selɣu-yi-d mi ara" + } + }, + "preference": { + "title": "Imenyafen", + "true_black_dark_mode": "Askar aberkan n tidet", + "disable_avatar_animation": "Sens ivaṭaren yettembiwilen", + "disable_emoji_animation": "Sens imujiten yettembiwilen", + "using_default_browser": "Seqdec iminig amezwer i twaledyawt n yiseɣwan" + }, + "boring_zone": { + "title": "Tamnaḍt yessefcalen", + "account_settings": "Iɣewwaṛen n umiḍan", + "terms": "Tiwtilin n useqdec", + "privacy": "Tasertit tabaḍnit" + }, + "spicy_zone": { + "title": "Tamnaḍt tamihawt", + "clear": "Sfeḍ takatut tuffirt n umidyat", + "signout": "Senser" + } + }, + "footer": { + "mastodon_description": "Maṣṭudun d aseɣzan s uɣbalu yeldin. Tzemreḍ ad temmleḍ uguren deg GitHub %s (%s)" + }, + "keyboard": { + "close_settings_window": "Mdel asfaylu n iɣewwaṛen" + } + }, + "report": { + "title_report": "Aneqqis", + "title": "Aneqqis %s", + "step1": "Aḥric 1 seg 2", + "step2": "Aḥric 2 seg 2", + "content1": "Tebɣiḍ ad ternuḍ tisuffaɣ-nniḍen ɣer uneqqis?", + "content2": "Yella wayen i ilaqen ad teẓren yimḍebbren ɣef uneqqis-a?", + "report_sent_title": "Tanemmirt ɣef uneqqis, ad nwali deg waya.", + "send": "Azen aneqis", + "skip_to_send": "Azen s war awennit", + "text_placeholder": "Aru neɣ senteḍ iwenniten-nniḍen", + "reported": "YETTWAMMEL" + }, + "preview": { + "keyboard": { + "close_preview": "Mdel timeẓri", + "show_next": "Sken uḍfir", + "show_previous": "Sken udfir" + } + }, + "account_list": { + "tab_bar_hint": "Amaɣnu amiran yettwafernen: %s. Sit berdayen syen teǧǧeḍ aḍad-ik·im i uskan abeddel n umiḍan", + "dismiss_account_switcher": "Sefsex abeddel n umiḍan", + "add_account": "Rnu amiḍan" + }, + "wizard": { + "new_in_mastodon": "Amaynut deg Maṣṭudun", + "multiple_account_switch_intro_description": "Beddel gar waṭas n yimiḍanen s tussda ɣezzifen ɣef tqeffalt n umaɣnu.", + "accessibility_hint": "Sin isitiyen i usefsex n umarag-a" + } + } +} \ No newline at end of file diff --git a/Localization/StringsConvertor/input/kab_KAB/ios-infoPlist.json b/Localization/StringsConvertor/input/kab_KAB/ios-infoPlist.json new file mode 100644 index 00000000..41128876 --- /dev/null +++ b/Localization/StringsConvertor/input/kab_KAB/ios-infoPlist.json @@ -0,0 +1,6 @@ +{ + "NSCameraUsageDescription": "Yettwaseqdac i tuṭṭfa n tewlafin deg usuffeɣ n waddaden", + "NSPhotoLibraryAddUsageDescription": "Yettwaseqdac i usekles n tewlafin deg temkarḍit n tewlafin", + "NewPostShortcutItemTitle": "Tasuffeɣt tamaynut", + "SearchShortcutItemTitle": "Nadi" +} diff --git a/Localization/StringsConvertor/input/kmr_TR/app.json b/Localization/StringsConvertor/input/kmr_TR/app.json index c360eb43..5d1d70fb 100644 --- a/Localization/StringsConvertor/input/kmr_TR/app.json +++ b/Localization/StringsConvertor/input/kmr_TR/app.json @@ -45,8 +45,8 @@ "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" + "title": "Şandiyê jê bibe", + "message": "Ma tu dixwazî vê şandiyê jê bibî?" }, "clean_cache": { "title": "Pêşbîrê pak bike", @@ -82,6 +82,7 @@ "share_user": "%s parve bike", "share_post": "Şandiyê parve bike", "open_in_safari": "Di Safariyê de veke", + "open_in_browser": "Di gerokê de veke", "find_people": "Mirovan bo şopandinê bibîne", "manually_search": "Ji devlê bi destan lêgerînê bike", "skip": "Derbas bike", @@ -112,7 +113,7 @@ "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_reblog": "Ji nû ve 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ê" @@ -123,7 +124,7 @@ } }, "status": { - "user_reblogged": "%s ji nû ve hate nivîsandin", + "user_reblogged": "%s ji nû ve nivîsand", "user_replied_to": "Bersiv da %s", "show_post": "Şandiyê nîşan bide", "show_user_profile": "Profîla bikarhêner nîşan bide", @@ -139,7 +140,8 @@ "unreblog": "Ji nû ve nivîsandinê vegere", "favorite": "Bijarte", "unfavorite": "Nebijarte", - "menu": "Kulîn" + "menu": "Kulîn", + "hide": "Veşêre" }, "tag": { "url": "URL", @@ -148,6 +150,12 @@ "hashtag": "Hashtag", "email": "E-name", "emoji": "Emojî" + }, + "visibility": { + "unlisted": "Her kes dikare vê şandiyê bibîne lê nayê nîşandan di demnameya gelemperî de.", + "private": "Tenê şopînerên wan dikarin vê şandiyê bibînin.", + "private_from_me": "Tenê şopînerên min dikarin vê şandiyê bibînin.", + "direct": "Tenê bikarhênerê qalkirî dikare vê şandiyê bibîne." } }, "friendship": { @@ -192,10 +200,14 @@ }, "scene": { "welcome": { - "slogan": "Torên civakî\ndi destên te de." + "slogan": "Torên civakî\ndi destên te de.", + "get_started": "Dest pê bike", + "log_in": "Têkeve" }, "server_picker": { "title": "Rajekarekê hilbijêre,\nHer kîjan rajekar be.", + "subtitle": "Li gorî berjewendî, herêm, an jî armancek gelemperî civakekê hilbijêre.", + "subtitle_extend": "Li gorî berjewendî, herêm, an jî armancek gelemperî civakekê hilbijêre. Her civakek ji hêla rêxistinek an kesek bi tevahî serbixwe ve tê xebitandin.", "button": { "category": { "all": "Hemû", @@ -231,7 +243,7 @@ } }, "register": { - "title": "Ji me re hinekî qala xwe bike.", + "title": "Ji me re hinekî qala xwe bike %s", "input": { "avatar": { "delete": "Jê bibe" @@ -248,6 +260,12 @@ }, "password": { "placeholder": "pêborîn", + "require": "Pêdiviya pêborîna te ya herî kêm:", + "character_limit": "8 tîp", + "accessibility": { + "checked": "hate kontrolkirin", + "unchecked": "nehate kontrolkirin" + }, "hint": "Pêborîna te herî kêm divê ji 8 tîpan pêk bê" }, "invite": { @@ -285,7 +303,7 @@ }, "server_rules": { "title": "Hinek rêzikên bingehîn.", - "subtitle": "Ev rêzik ji aliyê rêvebirên %s ve tên sazkirin.", + "subtitle": "Ev rêzik ji aliyê çavdêrê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ê", @@ -298,7 +316,7 @@ "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" + "resend": "Ji nû ve bişîne" }, "dont_receive_email": { "title": "E-nameyê xwe kontrol bike", @@ -401,16 +419,26 @@ "segmented_control": { "posts": "Şandî", "replies": "Bersiv", - "media": "Medya" + "posts_and_replies": "Şandî û bersiv", + "media": "Medya", + "about": "Derbar" }, "relationship_action_alert": { + "confirm_mute_user": { + "title": "Ajimêrê bêdeng bike", + "message": "Ji bo bêdengkirina %s bipejirîne" + }, "confirm_unmute_user": { "title": "Ajimêrê bêdeng neke", - "message": "Ji bo vekirina bêdengkirinê bipejirîne %s" + "message": "Ji bo vekirina bêdengkirinê %s bipejirîne" }, - "confirm_unblock_usre": { + "confirm_block_user": { + "title": "Ajimêr asteng bike", + "message": "Ji bo rakirina astengkirinê %s bipejirîne" + }, + "confirm_unblock_user": { "title": "Astengiyê li ser ajimêr rake", - "message": "Ji bo rakirina astengkirinê bipejirîne %s" + "message": "Ji bo rakirina astengkirinê %s bipejirîne" } } }, @@ -461,12 +489,14 @@ "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", + "notification_description": { + "followed_you": "te şopand", + "favorited_your_post": "şandiya te hez kir", + "reblogged_your_post": "şandiya te ji nû ve nivisand", + "mentioned_you": "qale te kir", + "request_to_follow_you": "dixwazê te bişopîne", + "poll_has_ended": "rapirsî qediya" + }, "keyobard": { "show_everything": "Her tiştî nîşan bide", "show_mentions": "Qalkirinan nîşan bike" @@ -482,9 +512,16 @@ "appearance": { "title": "Xuyang", "automatic": "Xweber", - "light": "Her dem ronî", + "light": "Her dem ronahî", "dark": "Her dem tarî" }, + "look_and_feel": { + "title": "Xuyang", + "use_system": "Pergalê bi kar bîne", + "really_dark": "Tarî", + "sorta_dark": "Hinekî tarî", + "light": "Ronahî" + }, "notifications": { "title": "Agahdarî", "favorites": "Şandiyên min hez kir", @@ -500,7 +537,7 @@ } }, "preference": { - "title": "Hilbijarte", + "title": "Sazkarî", "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", @@ -526,14 +563,17 @@ } }, "report": { + "title_report": "Ragihandin", "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?", + "report_sent_title": "Spas ji bo ragihandina te, em ê binirxînin.", "send": "Ragihandinê bişîne", "skip_to_send": "Bêyî şirove bişîne", - "text_placeholder": "Şiroveyên daxwazkirê binivîsine an jî pê ve bike" + "text_placeholder": "Şiroveyên daxwazkirê binivîsine an jî pê ve bike", + "reported": "HATE RAGIHANDIN" }, "preview": { "keyboard": { diff --git a/Localization/StringsConvertor/input/ko_KR/app.json b/Localization/StringsConvertor/input/ko_KR/app.json index 571b1465..3f9f4c19 100644 --- a/Localization/StringsConvertor/input/ko_KR/app.json +++ b/Localization/StringsConvertor/input/ko_KR/app.json @@ -46,7 +46,7 @@ }, "delete_post": { "title": "정말로 이 게시물을 삭제하시겠습니까?", - "delete": "삭제" + "message": "Are you sure you want to delete this post?" }, "clean_cache": { "title": "캐시 삭제", @@ -82,6 +82,7 @@ "share_user": "%s를 공유", "share_post": "게시물 공유", "open_in_safari": "사파리에서 열기", + "open_in_browser": "Open in Browser", "find_people": "팔로우 할 사람들 찾기", "manually_search": "대신 수동으로 검색하기", "skip": "건너뛰기", @@ -139,7 +140,8 @@ "unreblog": "리블로그 취소", "favorite": "즐겨찾기", "unfavorite": "즐겨찾기 해제", - "menu": "메뉴" + "menu": "메뉴", + "hide": "Hide" }, "tag": { "url": "URL", @@ -148,6 +150,12 @@ "hashtag": "해시태그", "email": "이메일", "emoji": "에모지" + }, + "visibility": { + "unlisted": "Everyone can see this post but not display in the public timeline.", + "private": "Only their followers can see this post.", + "private_from_me": "Only my followers can see this post.", + "direct": "Only mentioned user can see this post." } }, "friendship": { @@ -192,10 +200,14 @@ }, "scene": { "welcome": { - "slogan": "소셜 네트워킹을\n여러분의 손에 돌려드립니다." + "slogan": "소셜 네트워킹을\n여러분의 손에 돌려드립니다.", + "get_started": "Get Started", + "log_in": "Log In" }, "server_picker": { "title": "서버를 고르세요,\n아무 서버나 좋습니다.", + "subtitle": "Pick a community based on your interests, region, or a general purpose one.", + "subtitle_extend": "Pick a community based on your interests, region, or a general purpose one. Each community is operated by an entirely independent organization or individual.", "button": { "category": { "all": "모두", @@ -222,7 +234,7 @@ "category": "분류" }, "input": { - "placeholder": "Find a server or join your own..." + "placeholder": "Search communities" }, "empty_state": { "finding_servers": "Finding available servers...", @@ -231,7 +243,7 @@ } }, "register": { - "title": "Tell us about you.", + "title": "Let’s get you set up on %s", "input": { "avatar": { "delete": "삭제" @@ -248,6 +260,12 @@ }, "password": { "placeholder": "암호", + "require": "Your password needs at least:", + "character_limit": "8 characters", + "accessibility": { + "checked": "checked", + "unchecked": "unchecked" + }, "hint": "암호는 최소 8글자 이상이어야 합니다" }, "invite": { @@ -285,7 +303,7 @@ }, "server_rules": { "title": "Some ground rules.", - "subtitle": "These rules are set by the admins of %s.", + "subtitle": "These are set and enforced by the %s moderators.", "prompt": "By continuing, you’re subject to the terms of service and privacy policy for %s.", "terms_of_service": "terms of service", "privacy_policy": "privacy policy", @@ -295,10 +313,10 @@ }, "confirm_email": { "title": "마지막으로.", - "subtitle": "We just sent an email to %s,\ntap the link to confirm your account.", + "subtitle": "Tap the link we emailed to you to verify your account.", "button": { "open_email_app": "Open Email App", - "dont_receive_email": "I never got an email" + "resend": "Resend" }, "dont_receive_email": { "title": "Check your email", @@ -401,16 +419,26 @@ "segmented_control": { "posts": "게시물", "replies": "답글", - "media": "미디어" + "posts_and_replies": "Posts and Replies", + "media": "미디어", + "about": "About" }, "relationship_action_alert": { + "confirm_mute_user": { + "title": "Mute Account", + "message": "Confirm to mute %s" + }, "confirm_unmute_user": { "title": "계정 뮤트 해제", "message": "%s 뮤트 해제 확인" }, - "confirm_unblock_usre": { - "title": "계정 차단 해제", - "message": "%s 차단 해제 확인" + "confirm_block_user": { + "title": "Block Account", + "message": "Confirm to block %s" + }, + "confirm_unblock_user": { + "title": "Unblock Account", + "message": "Confirm to unblock %s" } } }, @@ -461,12 +489,14 @@ "Everything": "Everything", "Mentions": "Mentions" }, - "user_followed_you": "%s followed you", - "user_favorited your post": "%s favorited your post", - "user_reblogged_your_post": "%s reblogged your post", - "user_mentioned_you": "%s mentioned you", - "user_requested_to_follow_you": "%s requested to follow you", - "user_your_poll_has_ended": "%s Your poll has ended", + "notification_description": { + "followed_you": "followed you", + "favorited_your_post": "favorited your post", + "reblogged_your_post": "reblogged your post", + "mentioned_you": "mentioned you", + "request_to_follow_you": "request to follow you", + "poll_has_ended": "poll has ended" + }, "keyobard": { "show_everything": "Show Everything", "show_mentions": "Show Mentions" @@ -485,6 +515,13 @@ "light": "Always Light", "dark": "Always Dark" }, + "look_and_feel": { + "title": "Look and Feel", + "use_system": "Use System", + "really_dark": "Really Dark", + "sorta_dark": "Sorta Dark", + "light": "Light" + }, "notifications": { "title": "Notifications", "favorites": "Favorites my post", @@ -526,14 +563,17 @@ } }, "report": { + "title_report": "Report", "title": "%s 신고하기", "step1": "1단계 (총 2단계)", "step2": "2단계 (총 2단계)", "content1": "신고에 추가하고 싶은 다른 게시물이 존재하나요?", "content2": "이 신고에 대해 중재자들이 알아야 할 것이 있나요?", + "report_sent_title": "Thanks for reporting, we’ll look into this.", "send": "신고 전송", "skip_to_send": "추가설명 없이 보내기", - "text_placeholder": "추가 설명을 적거나 붙여넣으세요" + "text_placeholder": "추가 설명을 적거나 붙여넣으세요", + "reported": "REPORTED" }, "preview": { "keyboard": { diff --git a/Localization/StringsConvertor/input/nl_NL/app.json b/Localization/StringsConvertor/input/nl_NL/app.json index d8ee1e57..ae8f2d2d 100644 --- a/Localization/StringsConvertor/input/nl_NL/app.json +++ b/Localization/StringsConvertor/input/nl_NL/app.json @@ -46,7 +46,7 @@ }, "delete_post": { "title": "Weet u zeker dat u dit bericht wilt verwijderen?", - "delete": "Verwijderen" + "message": "Are you sure you want to delete this post?" }, "clean_cache": { "title": "Cache-geheugen Wissen", @@ -82,6 +82,7 @@ "share_user": "Delen %s", "share_post": "Bericht Delen", "open_in_safari": "Open in Safari", + "open_in_browser": "Open in Browser", "find_people": "Zoek mensen om te volgen", "manually_search": "Handmatig zoeken", "skip": "Overslaan", @@ -139,7 +140,8 @@ "unreblog": "Delen ongedaan maken", "favorite": "Toevoegen aan Favorieten", "unfavorite": "Verwijderen uit Favorieten", - "menu": "Menu" + "menu": "Menu", + "hide": "Hide" }, "tag": { "url": "URL", @@ -148,6 +150,12 @@ "hashtag": "Hashtag", "email": "Email", "emoji": "Emoji" + }, + "visibility": { + "unlisted": "Everyone can see this post but not display in the public timeline.", + "private": "Only their followers can see this post.", + "private_from_me": "Only my followers can see this post.", + "direct": "Only mentioned user can see this post." } }, "friendship": { @@ -192,10 +200,14 @@ }, "scene": { "welcome": { - "slogan": "Sociale media terug in uw handen." + "slogan": "Sociale media terug in uw handen.", + "get_started": "Get Started", + "log_in": "Log In" }, "server_picker": { "title": "Kies een server, welke dan ook.", + "subtitle": "Pick a community based on your interests, region, or a general purpose one.", + "subtitle_extend": "Pick a community based on your interests, region, or a general purpose one. Each community is operated by an entirely independent organization or individual.", "button": { "category": { "all": "Alles", @@ -248,6 +260,12 @@ }, "password": { "placeholder": "wachtwoord", + "require": "Your password needs at least:", + "character_limit": "8 characters", + "accessibility": { + "checked": "checked", + "unchecked": "unchecked" + }, "hint": "Uw wachtwoord moet ten minste acht tekens bevatten" }, "invite": { @@ -298,7 +316,7 @@ "subtitle": "We hebben een e-mail gestuurd naar %s,\nklik op de link om uw account te bevestigen.", "button": { "open_email_app": "Email Openen", - "dont_receive_email": "Ik heb geen email ontvangen" + "resend": "Resend" }, "dont_receive_email": { "title": "Controleer uw emailadres", @@ -401,16 +419,26 @@ "segmented_control": { "posts": "Berichten", "replies": "Reacties", - "media": "Media" + "posts_and_replies": "Posts and Replies", + "media": "Media", + "about": "About" }, "relationship_action_alert": { + "confirm_mute_user": { + "title": "Mute Account", + "message": "Confirm to mute %s" + }, "confirm_unmute_user": { "title": "Account Negeren", "message": "Bevestig om %s te negeren" }, - "confirm_unblock_usre": { - "title": "Account niet langer negeren", - "message": "Bevestig om %s te deblokkeren" + "confirm_block_user": { + "title": "Block Account", + "message": "Confirm to block %s" + }, + "confirm_unblock_user": { + "title": "Unblock Account", + "message": "Confirm to unblock %s" } } }, @@ -461,12 +489,14 @@ "Everything": "Alles", "Mentions": "Vermeldingen" }, - "user_followed_you": "%s followed you", - "user_favorited your post": "%s favorited your post", - "user_reblogged_your_post": "%s reblogged your post", - "user_mentioned_you": "%s mentioned you", - "user_requested_to_follow_you": "%s requested to follow you", - "user_your_poll_has_ended": "%s Your poll has ended", + "notification_description": { + "followed_you": "followed you", + "favorited_your_post": "favorited your post", + "reblogged_your_post": "reblogged your post", + "mentioned_you": "mentioned you", + "request_to_follow_you": "request to follow you", + "poll_has_ended": "poll has ended" + }, "keyobard": { "show_everything": "Alles weergeven", "show_mentions": "Vermeldingen weergeven" @@ -485,6 +515,13 @@ "light": "Altijd Licht", "dark": "Altijd Donker" }, + "look_and_feel": { + "title": "Look and Feel", + "use_system": "Use System", + "really_dark": "Really Dark", + "sorta_dark": "Sorta Dark", + "light": "Light" + }, "notifications": { "title": "Meldingen", "favorites": "Mijn bericht als favoriet toevoegt", @@ -526,14 +563,17 @@ } }, "report": { + "title_report": "Report", "title": "Rapporteer %s", "step1": "Stap 1 van 2", "step2": "Stap 2 van 2", "content1": "Zijn er nog meer berichten die u aan het rapport wilt toevoegen?", "content2": "Is er iets anders over dit rapport dat de moderators zouden moeten weten?", + "report_sent_title": "Thanks for reporting, we’ll look into this.", "send": "Stuur rapport", "skip_to_send": "Verstuur zonder opmerkingen", - "text_placeholder": "Schrijf of plak aanvullende opmerkingen" + "text_placeholder": "Schrijf of plak aanvullende opmerkingen", + "reported": "REPORTED" }, "preview": { "keyboard": { diff --git a/Localization/StringsConvertor/input/pt_BR/app.json b/Localization/StringsConvertor/input/pt_BR/app.json index 5c01ae7e..ad99e178 100644 --- a/Localization/StringsConvertor/input/pt_BR/app.json +++ b/Localization/StringsConvertor/input/pt_BR/app.json @@ -45,8 +45,8 @@ "message": "Please enable the photo library access permission to save the photo." }, "delete_post": { - "title": "Are you sure you want to delete this post?", - "delete": "Delete" + "title": "Delete Post", + "message": "Are you sure you want to delete this post?" }, "clean_cache": { "title": "Clean Cache", @@ -82,6 +82,7 @@ "share_user": "Share %s", "share_post": "Share Post", "open_in_safari": "Open in Safari", + "open_in_browser": "Open in Browser", "find_people": "Find people to follow", "manually_search": "Manually search instead", "skip": "Skip", @@ -139,7 +140,8 @@ "unreblog": "Undo reblog", "favorite": "Favorite", "unfavorite": "Unfavorite", - "menu": "Menu" + "menu": "Menu", + "hide": "Hide" }, "tag": { "url": "URL", @@ -148,6 +150,12 @@ "hashtag": "Hashtag", "email": "Email", "emoji": "Emoji" + }, + "visibility": { + "unlisted": "Everyone can see this post but not display in the public timeline.", + "private": "Only their followers can see this post.", + "private_from_me": "Only my followers can see this post.", + "direct": "Only mentioned user can see this post." } }, "friendship": { @@ -192,10 +200,14 @@ }, "scene": { "welcome": { - "slogan": "Social networking\nback in your hands." + "slogan": "Social networking\nback in your hands.", + "get_started": "Get Started", + "log_in": "Log In" }, "server_picker": { - "title": "Pick a server,\nany server.", + "title": "Mastodon is made of users in different communities.", + "subtitle": "Pick a community based on your interests, region, or a general purpose one.", + "subtitle_extend": "Pick a community based on your interests, region, or a general purpose one. Each community is operated by an entirely independent organization or individual.", "button": { "category": { "all": "All", @@ -222,7 +234,7 @@ "category": "CATEGORY" }, "input": { - "placeholder": "Find a server or join your own..." + "placeholder": "Search communities" }, "empty_state": { "finding_servers": "Finding available servers...", @@ -231,7 +243,7 @@ } }, "register": { - "title": "Tell us about you.", + "title": "Let’s get you set up on %s", "input": { "avatar": { "delete": "Delete" @@ -248,6 +260,12 @@ }, "password": { "placeholder": "password", + "require": "Your password needs at least:", + "character_limit": "8 characters", + "accessibility": { + "checked": "checked", + "unchecked": "unchecked" + }, "hint": "Your password needs at least eight characters" }, "invite": { @@ -285,7 +303,7 @@ }, "server_rules": { "title": "Some ground rules.", - "subtitle": "These rules are set by the admins of %s.", + "subtitle": "These are set and enforced by the %s moderators.", "prompt": "By continuing, you’re subject to the terms of service and privacy policy for %s.", "terms_of_service": "terms of service", "privacy_policy": "privacy policy", @@ -295,10 +313,10 @@ }, "confirm_email": { "title": "One last thing.", - "subtitle": "We just sent an email to %s,\ntap the link to confirm your account.", + "subtitle": "Tap the link we emailed to you to verify your account.", "button": { "open_email_app": "Open Email App", - "dont_receive_email": "I never got an email" + "resend": "Resend" }, "dont_receive_email": { "title": "Check your email", @@ -401,14 +419,24 @@ "segmented_control": { "posts": "Posts", "replies": "Replies", - "media": "Media" + "posts_and_replies": "Posts and Replies", + "media": "Media", + "about": "About" }, "relationship_action_alert": { + "confirm_mute_user": { + "title": "Mute Account", + "message": "Confirm to mute %s" + }, "confirm_unmute_user": { "title": "Unmute Account", "message": "Confirm to unmute %s" }, - "confirm_unblock_usre": { + "confirm_block_user": { + "title": "Block Account", + "message": "Confirm to block %s" + }, + "confirm_unblock_user": { "title": "Unblock Account", "message": "Confirm to unblock %s" } @@ -461,12 +489,14 @@ "Everything": "Everything", "Mentions": "Mentions" }, - "user_followed_you": "%s followed you", - "user_favorited your post": "%s favorited your post", - "user_reblogged_your_post": "%s reblogged your post", - "user_mentioned_you": "%s mentioned you", - "user_requested_to_follow_you": "%s requested to follow you", - "user_your_poll_has_ended": "%s Your poll has ended", + "notification_description": { + "followed_you": "followed you", + "favorited_your_post": "favorited your post", + "reblogged_your_post": "reblogged your post", + "mentioned_you": "mentioned you", + "request_to_follow_you": "request to follow you", + "poll_has_ended": "poll has ended" + }, "keyobard": { "show_everything": "Show Everything", "show_mentions": "Show Mentions" @@ -485,6 +515,13 @@ "light": "Always Light", "dark": "Always Dark" }, + "look_and_feel": { + "title": "Look and Feel", + "use_system": "Use System", + "really_dark": "Really Dark", + "sorta_dark": "Sorta Dark", + "light": "Light" + }, "notifications": { "title": "Notifications", "favorites": "Favorites my post", @@ -526,14 +563,17 @@ } }, "report": { + "title_report": "Report", "title": "Report %s", "step1": "Step 1 of 2", "step2": "Step 2 of 2", "content1": "Are there any other posts you’d like to add to the report?", "content2": "Is there anything the moderators should know about this report?", + "report_sent_title": "Thanks for reporting, we’ll look into this.", "send": "Send Report", "skip_to_send": "Send without comment", - "text_placeholder": "Type or paste additional comments" + "text_placeholder": "Type or paste additional comments", + "reported": "REPORTED" }, "preview": { "keyboard": { diff --git a/Localization/StringsConvertor/input/pt_PT/app.json b/Localization/StringsConvertor/input/pt_PT/app.json index 5c01ae7e..ad99e178 100644 --- a/Localization/StringsConvertor/input/pt_PT/app.json +++ b/Localization/StringsConvertor/input/pt_PT/app.json @@ -45,8 +45,8 @@ "message": "Please enable the photo library access permission to save the photo." }, "delete_post": { - "title": "Are you sure you want to delete this post?", - "delete": "Delete" + "title": "Delete Post", + "message": "Are you sure you want to delete this post?" }, "clean_cache": { "title": "Clean Cache", @@ -82,6 +82,7 @@ "share_user": "Share %s", "share_post": "Share Post", "open_in_safari": "Open in Safari", + "open_in_browser": "Open in Browser", "find_people": "Find people to follow", "manually_search": "Manually search instead", "skip": "Skip", @@ -139,7 +140,8 @@ "unreblog": "Undo reblog", "favorite": "Favorite", "unfavorite": "Unfavorite", - "menu": "Menu" + "menu": "Menu", + "hide": "Hide" }, "tag": { "url": "URL", @@ -148,6 +150,12 @@ "hashtag": "Hashtag", "email": "Email", "emoji": "Emoji" + }, + "visibility": { + "unlisted": "Everyone can see this post but not display in the public timeline.", + "private": "Only their followers can see this post.", + "private_from_me": "Only my followers can see this post.", + "direct": "Only mentioned user can see this post." } }, "friendship": { @@ -192,10 +200,14 @@ }, "scene": { "welcome": { - "slogan": "Social networking\nback in your hands." + "slogan": "Social networking\nback in your hands.", + "get_started": "Get Started", + "log_in": "Log In" }, "server_picker": { - "title": "Pick a server,\nany server.", + "title": "Mastodon is made of users in different communities.", + "subtitle": "Pick a community based on your interests, region, or a general purpose one.", + "subtitle_extend": "Pick a community based on your interests, region, or a general purpose one. Each community is operated by an entirely independent organization or individual.", "button": { "category": { "all": "All", @@ -222,7 +234,7 @@ "category": "CATEGORY" }, "input": { - "placeholder": "Find a server or join your own..." + "placeholder": "Search communities" }, "empty_state": { "finding_servers": "Finding available servers...", @@ -231,7 +243,7 @@ } }, "register": { - "title": "Tell us about you.", + "title": "Let’s get you set up on %s", "input": { "avatar": { "delete": "Delete" @@ -248,6 +260,12 @@ }, "password": { "placeholder": "password", + "require": "Your password needs at least:", + "character_limit": "8 characters", + "accessibility": { + "checked": "checked", + "unchecked": "unchecked" + }, "hint": "Your password needs at least eight characters" }, "invite": { @@ -285,7 +303,7 @@ }, "server_rules": { "title": "Some ground rules.", - "subtitle": "These rules are set by the admins of %s.", + "subtitle": "These are set and enforced by the %s moderators.", "prompt": "By continuing, you’re subject to the terms of service and privacy policy for %s.", "terms_of_service": "terms of service", "privacy_policy": "privacy policy", @@ -295,10 +313,10 @@ }, "confirm_email": { "title": "One last thing.", - "subtitle": "We just sent an email to %s,\ntap the link to confirm your account.", + "subtitle": "Tap the link we emailed to you to verify your account.", "button": { "open_email_app": "Open Email App", - "dont_receive_email": "I never got an email" + "resend": "Resend" }, "dont_receive_email": { "title": "Check your email", @@ -401,14 +419,24 @@ "segmented_control": { "posts": "Posts", "replies": "Replies", - "media": "Media" + "posts_and_replies": "Posts and Replies", + "media": "Media", + "about": "About" }, "relationship_action_alert": { + "confirm_mute_user": { + "title": "Mute Account", + "message": "Confirm to mute %s" + }, "confirm_unmute_user": { "title": "Unmute Account", "message": "Confirm to unmute %s" }, - "confirm_unblock_usre": { + "confirm_block_user": { + "title": "Block Account", + "message": "Confirm to block %s" + }, + "confirm_unblock_user": { "title": "Unblock Account", "message": "Confirm to unblock %s" } @@ -461,12 +489,14 @@ "Everything": "Everything", "Mentions": "Mentions" }, - "user_followed_you": "%s followed you", - "user_favorited your post": "%s favorited your post", - "user_reblogged_your_post": "%s reblogged your post", - "user_mentioned_you": "%s mentioned you", - "user_requested_to_follow_you": "%s requested to follow you", - "user_your_poll_has_ended": "%s Your poll has ended", + "notification_description": { + "followed_you": "followed you", + "favorited_your_post": "favorited your post", + "reblogged_your_post": "reblogged your post", + "mentioned_you": "mentioned you", + "request_to_follow_you": "request to follow you", + "poll_has_ended": "poll has ended" + }, "keyobard": { "show_everything": "Show Everything", "show_mentions": "Show Mentions" @@ -485,6 +515,13 @@ "light": "Always Light", "dark": "Always Dark" }, + "look_and_feel": { + "title": "Look and Feel", + "use_system": "Use System", + "really_dark": "Really Dark", + "sorta_dark": "Sorta Dark", + "light": "Light" + }, "notifications": { "title": "Notifications", "favorites": "Favorites my post", @@ -526,14 +563,17 @@ } }, "report": { + "title_report": "Report", "title": "Report %s", "step1": "Step 1 of 2", "step2": "Step 2 of 2", "content1": "Are there any other posts you’d like to add to the report?", "content2": "Is there anything the moderators should know about this report?", + "report_sent_title": "Thanks for reporting, we’ll look into this.", "send": "Send Report", "skip_to_send": "Send without comment", - "text_placeholder": "Type or paste additional comments" + "text_placeholder": "Type or paste additional comments", + "reported": "REPORTED" }, "preview": { "keyboard": { diff --git a/Localization/StringsConvertor/input/ro_RO/app.json b/Localization/StringsConvertor/input/ro_RO/app.json index 3927247e..b9ef116d 100644 --- a/Localization/StringsConvertor/input/ro_RO/app.json +++ b/Localization/StringsConvertor/input/ro_RO/app.json @@ -45,8 +45,8 @@ "message": "Please enable the photo library access permission to save the photo." }, "delete_post": { - "title": "Are you sure you want to delete this post?", - "delete": "Delete" + "title": "Delete Post", + "message": "Are you sure you want to delete this post?" }, "clean_cache": { "title": "Clean Cache", @@ -82,6 +82,7 @@ "share_user": "Share %s", "share_post": "Share Post", "open_in_safari": "Open in Safari", + "open_in_browser": "Open in Browser", "find_people": "Find people to follow", "manually_search": "Manually search instead", "skip": "Skip", @@ -139,7 +140,8 @@ "unreblog": "Undo reblog", "favorite": "Favorite", "unfavorite": "Unfavorite", - "menu": "Menu" + "menu": "Menu", + "hide": "Hide" }, "tag": { "url": "URL", @@ -148,6 +150,12 @@ "hashtag": "Hashtag", "email": "Email", "emoji": "Emoji" + }, + "visibility": { + "unlisted": "Everyone can see this post but not display in the public timeline.", + "private": "Only their followers can see this post.", + "private_from_me": "Only my followers can see this post.", + "direct": "Only mentioned user can see this post." } }, "friendship": { @@ -192,10 +200,14 @@ }, "scene": { "welcome": { - "slogan": "Social networking\nback in your hands." + "slogan": "Social networking\nback in your hands.", + "get_started": "Get Started", + "log_in": "Log In" }, "server_picker": { - "title": "Pick a server,\nany server.", + "title": "Mastodon is made of users in different communities.", + "subtitle": "Pick a community based on your interests, region, or a general purpose one.", + "subtitle_extend": "Pick a community based on your interests, region, or a general purpose one. Each community is operated by an entirely independent organization or individual.", "button": { "category": { "all": "All", @@ -222,7 +234,7 @@ "category": "CATEGORY" }, "input": { - "placeholder": "Find a server or join your own..." + "placeholder": "Search communities" }, "empty_state": { "finding_servers": "Finding available servers...", @@ -231,7 +243,7 @@ } }, "register": { - "title": "Tell us about you.", + "title": "Let’s get you set up on %s", "input": { "avatar": { "delete": "Delete" @@ -248,6 +260,12 @@ }, "password": { "placeholder": "password", + "require": "Your password needs at least:", + "character_limit": "8 characters", + "accessibility": { + "checked": "checked", + "unchecked": "unchecked" + }, "hint": "Your password needs at least eight characters" }, "invite": { @@ -285,7 +303,7 @@ }, "server_rules": { "title": "Some ground rules.", - "subtitle": "These rules are set by the admins of %s.", + "subtitle": "These are set and enforced by the %s moderators.", "prompt": "By continuing, you’re subject to the terms of service and privacy policy for %s.", "terms_of_service": "terms of service", "privacy_policy": "privacy policy", @@ -295,10 +313,10 @@ }, "confirm_email": { "title": "One last thing.", - "subtitle": "We just sent an email to %s,\ntap the link to confirm your account.", + "subtitle": "Tap the link we emailed to you to verify your account.", "button": { "open_email_app": "Open Email App", - "dont_receive_email": "I never got an email" + "resend": "Resend" }, "dont_receive_email": { "title": "Check your email", @@ -401,14 +419,24 @@ "segmented_control": { "posts": "Posts", "replies": "Replies", - "media": "Media" + "posts_and_replies": "Posts and Replies", + "media": "Media", + "about": "About" }, "relationship_action_alert": { + "confirm_mute_user": { + "title": "Mute Account", + "message": "Confirm to mute %s" + }, "confirm_unmute_user": { "title": "Unmute Account", "message": "Confirm to unmute %s" }, - "confirm_unblock_usre": { + "confirm_block_user": { + "title": "Block Account", + "message": "Confirm to block %s" + }, + "confirm_unblock_user": { "title": "Unblock Account", "message": "Confirm to unblock %s" } @@ -461,12 +489,14 @@ "Everything": "Everything", "Mentions": "Mentions" }, - "user_followed_you": "%s followed you", - "user_favorited your post": "%s favorited your post", - "user_reblogged_your_post": "%s reblogged your post", - "user_mentioned_you": "%s mentioned you", - "user_requested_to_follow_you": "%s requested to follow you", - "user_your_poll_has_ended": "%s Your poll has ended", + "notification_description": { + "followed_you": "followed you", + "favorited_your_post": "favorited your post", + "reblogged_your_post": "reblogged your post", + "mentioned_you": "mentioned you", + "request_to_follow_you": "request to follow you", + "poll_has_ended": "poll has ended" + }, "keyobard": { "show_everything": "Show Everything", "show_mentions": "Show Mentions" @@ -485,6 +515,13 @@ "light": "Always Light", "dark": "Always Dark" }, + "look_and_feel": { + "title": "Look and Feel", + "use_system": "Use System", + "really_dark": "Really Dark", + "sorta_dark": "Sorta Dark", + "light": "Light" + }, "notifications": { "title": "Notifications", "favorites": "Favorites my post", @@ -526,14 +563,17 @@ } }, "report": { + "title_report": "Report", "title": "Report %s", "step1": "Step 1 of 2", "step2": "Step 2 of 2", "content1": "Are there any other posts you’d like to add to the report?", "content2": "Is there anything the moderators should know about this report?", + "report_sent_title": "Thanks for reporting, we’ll look into this.", "send": "Send Report", "skip_to_send": "Send without comment", - "text_placeholder": "Type or paste additional comments" + "text_placeholder": "Type or paste additional comments", + "reported": "REPORTED" }, "preview": { "keyboard": { diff --git a/Localization/StringsConvertor/input/ru_RU/app.json b/Localization/StringsConvertor/input/ru_RU/app.json index c1ad3ee4..58cedfc7 100644 --- a/Localization/StringsConvertor/input/ru_RU/app.json +++ b/Localization/StringsConvertor/input/ru_RU/app.json @@ -46,7 +46,7 @@ }, "delete_post": { "title": "Вы уверены, что хотите удалить этот пост?", - "delete": "Удалить" + "message": "Are you sure you want to delete this post?" }, "clean_cache": { "title": "Очистка кэша", @@ -67,7 +67,7 @@ "done": "Готово", "confirm": "Подтвердить", "continue": "Продолжить", - "compose": "Compose", + "compose": "Написать", "cancel": "Отмена", "discard": "Отмена", "try_again": "Попробовать снова", @@ -82,6 +82,7 @@ "share_user": "Поделиться %s", "share_post": "Поделиться постом", "open_in_safari": "Открыть в Safari", + "open_in_browser": "Открыть в браузере", "find_people": "Подпишитесь на людей", "manually_search": "Найти вручную", "skip": "Пропустить", @@ -139,7 +140,8 @@ "unreblog": "Убрать продвижение", "favorite": "Добавить в избранное", "unfavorite": "Убрать из избранного", - "menu": "Меню" + "menu": "Меню", + "hide": "Hide" }, "tag": { "url": "Ссылка", @@ -148,6 +150,12 @@ "hashtag": "Хэштег", "email": "E-mail", "emoji": "Эмодзи" + }, + "visibility": { + "unlisted": "Everyone can see this post but not display in the public timeline.", + "private": "Only their followers can see this post.", + "private_from_me": "Only my followers can see this post.", + "direct": "Only mentioned user can see this post." } }, "friendship": { @@ -192,10 +200,14 @@ }, "scene": { "welcome": { - "slogan": "Социальная сеть\nпод вашим контролем." + "slogan": "Социальная сеть\nпод вашим контролем.", + "get_started": "Get Started", + "log_in": "Вход" }, "server_picker": { "title": "Выберите сервер,\nлюбой сервер.", + "subtitle": "Выберите сообщество на основе своих интересов, региона или общей тематики.", + "subtitle_extend": "Pick a community based on your interests, region, or a general purpose one. Each community is operated by an entirely independent organization or individual.", "button": { "category": { "all": "Все", @@ -248,6 +260,12 @@ }, "password": { "placeholder": "пароль", + "require": "Your password needs at least:", + "character_limit": "8 characters", + "accessibility": { + "checked": "checked", + "unchecked": "unchecked" + }, "hint": "Пароль должен содержать не менее восьми символов" }, "invite": { @@ -298,7 +316,7 @@ "subtitle": "Мы только что отправили письмо на\n%s.\nНажмите на ссылку в нём, чтобы\nподтвердить свою учётную запись.", "button": { "open_email_app": "Открыть приложение почты", - "dont_receive_email": "Я не получил письма" + "resend": "Resend" }, "dont_receive_email": { "title": "Проверьте свой e-mail адрес", @@ -401,16 +419,26 @@ "segmented_control": { "posts": "Посты", "replies": "Ответы", - "media": "Медиа" + "posts_and_replies": "Posts and Replies", + "media": "Медиа", + "about": "About" }, "relationship_action_alert": { + "confirm_mute_user": { + "title": "Mute Account", + "message": "Confirm to mute %s" + }, "confirm_unmute_user": { "title": "Убрать из игнорируемых", "message": "Убрать %s из игнорируемых?" }, - "confirm_unblock_usre": { - "title": "Разблокировать", - "message": "Убрать %s из списка блокировки?" + "confirm_block_user": { + "title": "Block Account", + "message": "Confirm to block %s" + }, + "confirm_unblock_user": { + "title": "Unblock Account", + "message": "Confirm to unblock %s" } } }, @@ -461,12 +489,14 @@ "Everything": "Все", "Mentions": "Упоминания" }, - "user_followed_you": "%s подписался (-ась)", - "user_favorited your post": "%s favorited your post", - "user_reblogged_your_post": "%s reblogged your post", - "user_mentioned_you": "%s упомянул вас", - "user_requested_to_follow_you": "%s запрашивает подписку", - "user_your_poll_has_ended": "%s Your poll has ended", + "notification_description": { + "followed_you": "followed you", + "favorited_your_post": "favorited your post", + "reblogged_your_post": "reblogged your post", + "mentioned_you": "mentioned you", + "request_to_follow_you": "request to follow you", + "poll_has_ended": "poll has ended" + }, "keyobard": { "show_everything": "Показать все", "show_mentions": "Показать упоминания" @@ -485,6 +515,13 @@ "light": "Светлая тема", "dark": "Тёмная тема" }, + "look_and_feel": { + "title": "Look and Feel", + "use_system": "Use System", + "really_dark": "Really Dark", + "sorta_dark": "Sorta Dark", + "light": "Light" + }, "notifications": { "title": "Уведомления", "favorites": "Добавляет мой пост в избранное", @@ -526,14 +563,17 @@ } }, "report": { + "title_report": "Report", "title": "Пожаловаться на %s", "step1": "Шаг 1 из 2", "step2": "Шаг 2 из 2", "content1": "Есть ли другие сообщения, которые вы хотите добавить в отчёт?", "content2": "Есть ли что-то, что модераторы должны знать об этом сообщении?", + "report_sent_title": "Thanks for reporting, we’ll look into this.", "send": "Пожаловаться", "skip_to_send": "Отправить без комментария", - "text_placeholder": "Дополнительные комментарии" + "text_placeholder": "Дополнительные комментарии", + "reported": "REPORTED" }, "preview": { "keyboard": { diff --git a/Localization/StringsConvertor/input/sv_FI/Localizable.stringsdict b/Localization/StringsConvertor/input/sv_FI/Localizable.stringsdict index 65316e3d..eec977a6 100644 --- a/Localization/StringsConvertor/input/sv_FI/Localizable.stringsdict +++ b/Localization/StringsConvertor/input/sv_FI/Localizable.stringsdict @@ -13,15 +13,15 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 unread notification</string> + <string>1 lukematon ilmoitus</string> <key>other</key> - <string>%ld unread notification</string> + <string>%ld lukematonta ilmoitusta</string> </dict> </dict> <key>a11y.plural.count.input_limit_exceeds</key> <dict> <key>NSStringLocalizedFormatKey</key> - <string>Input limit exceeds %#@character_count@</string> + <string>Syöterajoitus ylittyy %#@character_count@</string> <key>character_count</key> <dict> <key>NSStringFormatSpecTypeKey</key> @@ -29,15 +29,15 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 character</string> + <string>1 merkki</string> <key>other</key> - <string>%ld characters</string> + <string>%ld merkkiä</string> </dict> </dict> <key>a11y.plural.count.input_limit_remains</key> <dict> <key>NSStringLocalizedFormatKey</key> - <string>Input limit remains %#@character_count@</string> + <string>Syöterajoitus ylittyy %#@character_count@ päästä</string> <key>character_count</key> <dict> <key>NSStringFormatSpecTypeKey</key> @@ -45,9 +45,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 character</string> + <string>1 merkki</string> <key>other</key> - <string>%ld characters</string> + <string>%ld merkkiä</string> </dict> </dict> <key>plural.count.metric_formatted.post</key> @@ -61,9 +61,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>post</string> + <string>julkaisu</string> <key>other</key> - <string>posts</string> + <string>julkaisut</string> </dict> </dict> <key>plural.count.post</key> @@ -77,9 +77,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 post</string> + <string>1 julkaisu</string> <key>other</key> - <string>%ld posts</string> + <string>%ld julkaisua</string> </dict> </dict> <key>plural.count.favorite</key> @@ -93,9 +93,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 favorite</string> + <string>1 suosikki</string> <key>other</key> - <string>%ld favorites</string> + <string>%ld suosikkia</string> </dict> </dict> <key>plural.count.reblog</key> @@ -109,9 +109,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 reblog</string> + <string>1 edelleen jako</string> <key>other</key> - <string>%ld reblogs</string> + <string>%ld edelleen jakoa</string> </dict> </dict> <key>plural.count.vote</key> @@ -125,9 +125,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 vote</string> + <string>1 ääni</string> <key>other</key> - <string>%ld votes</string> + <string>%ld ääntä</string> </dict> </dict> <key>plural.count.voter</key> @@ -141,9 +141,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 voter</string> + <string>1 vastaaja</string> <key>other</key> - <string>%ld voters</string> + <string>%ld vastaajaa</string> </dict> </dict> <key>plural.people_talking</key> @@ -157,9 +157,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 people talking</string> + <string>1 ihminen puhuu</string> <key>other</key> - <string>%ld people talking</string> + <string>%ld ihmistä puhuu</string> </dict> </dict> <key>plural.count.following</key> @@ -173,9 +173,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 following</string> + <string>1 seurataan</string> <key>other</key> - <string>%ld following</string> + <string>%ld seurataan</string> </dict> </dict> <key>plural.count.follower</key> @@ -189,9 +189,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 följare</string> + <string>1 seuraaja</string> <key>other</key> - <string>%ld följare</string> + <string>%ld seuraajaa</string> </dict> </dict> <key>date.year.left</key> @@ -205,9 +205,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 year left</string> + <string>1 vuosi jäljellä</string> <key>other</key> - <string>%ld years left</string> + <string>%ld vuotta jäljellä</string> </dict> </dict> <key>date.month.left</key> @@ -221,9 +221,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 months left</string> + <string>1 kuukausi jäljellä</string> <key>other</key> - <string>%ld months left</string> + <string>%ld kuukautta jäljellä</string> </dict> </dict> <key>date.day.left</key> @@ -237,9 +237,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 day left</string> + <string>1 päivä jäljellä</string> <key>other</key> - <string>%ld days left</string> + <string>%ld päivää jäljellä</string> </dict> </dict> <key>date.hour.left</key> @@ -253,9 +253,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 hour left</string> + <string>1 tunti jäljellä</string> <key>other</key> - <string>%ld hours left</string> + <string>%ld tuntia jäljellä</string> </dict> </dict> <key>date.minute.left</key> @@ -269,9 +269,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 minute left</string> + <string>1 minuutti jäljellä</string> <key>other</key> - <string>%ld minutes left</string> + <string>%ld minuuttia jäljellä</string> </dict> </dict> <key>date.second.left</key> @@ -285,9 +285,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 second left</string> + <string>1 sekuntti</string> <key>other</key> - <string>%ld seconds left</string> + <string>%ld sekunttia jäljellä</string> </dict> </dict> <key>date.year.ago.abbr</key> @@ -301,9 +301,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1y ago</string> + <string>1v sitten</string> <key>other</key> - <string>%ldy ago</string> + <string>%ldv sitten</string> </dict> </dict> <key>date.month.ago.abbr</key> @@ -317,9 +317,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1M ago</string> + <string>1kk sitten</string> <key>other</key> - <string>%ldM ago</string> + <string>%ldkk sitten</string> </dict> </dict> <key>date.day.ago.abbr</key> @@ -333,9 +333,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1d ago</string> + <string>1pv sitten</string> <key>other</key> - <string>%ldd ago</string> + <string>%ldpv sitten</string> </dict> </dict> <key>date.hour.ago.abbr</key> @@ -349,9 +349,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1h ago</string> + <string>1t sitten</string> <key>other</key> - <string>%ldh ago</string> + <string>%ldt sitten</string> </dict> </dict> <key>date.minute.ago.abbr</key> @@ -365,9 +365,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1m ago</string> + <string>1min sitten</string> <key>other</key> - <string>%ldm ago</string> + <string>%ldmin sitten</string> </dict> </dict> <key>date.second.ago.abbr</key> @@ -381,9 +381,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1s ago</string> + <string>1s sitten</string> <key>other</key> - <string>%lds ago</string> + <string>%lds sitten</string> </dict> </dict> </dict> diff --git a/Localization/StringsConvertor/input/sv_FI/app.json b/Localization/StringsConvertor/input/sv_FI/app.json index 7acf4875..669ee437 100644 --- a/Localization/StringsConvertor/input/sv_FI/app.json +++ b/Localization/StringsConvertor/input/sv_FI/app.json @@ -2,555 +2,595 @@ "common": { "alerts": { "common": { - "please_try_again": "Var god försök igen.", - "please_try_again_later": "Var god försök igen senare." + "please_try_again": "Yritä uudelleen.", + "please_try_again_later": "Yritä uudelleen myöhemmin." }, "sign_up_failure": { - "title": "Sign Up Failure" + "title": "Rekisteröinti epäonnistui" }, "server_error": { - "title": "Serverfel" + "title": "Palvelinvirhe" }, "vote_failure": { "title": "Vote Failure", - "poll_ended": "Omröstningen har avslutats" + "poll_ended": "Kysely on päättynyt" }, "discard_post_content": { - "title": "Discard Draft", + "title": "Hylkää luonnos", "message": "Confirm to discard composed post content." }, "publish_post_failure": { - "title": "Publish Failure", - "message": "Failed to publish the post.\nPlease check your internet connection.", + "title": "Julkaiseminen epäonnistui", + "message": "Julkaisun julkaiseminen epäonnistui.\nTarkista internet-yhteytesi.", "attachments_message": { "video_attach_with_photo": "Cannot attach a video to a post that already contains images.", - "more_than_one_video": "Cannot attach more than one video." + "more_than_one_video": "Ei voi liittä yhtä videota enempää." } }, "edit_profile_failure": { - "title": "Edit Profile Error", - "message": "Cannot edit profile. Please try again." + "title": "Virhe profiilin muokkauksessa", + "message": "Profiilia ei voida muoka. Yritä uudelleen." }, "sign_out": { - "title": "Sign Out", - "message": "Är du säker på att du vill logga ut?", - "confirm": "Sign Out" + "title": "Kirjaudu ulos", + "message": "Haluatko varmasti kirjautua ulos?", + "confirm": "Kirjaudu ulos" }, "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.", - "block_entire_domain": "Block Domain" + "block_entire_domain": "Estä verkkotunnus" }, "save_photo_failure": { - "title": "Save Photo Failure", + "title": "Kuvan tallentaminen epäonnistui", "message": "Please enable the photo library access permission to save the photo." }, "delete_post": { - "title": "Are you sure you want to delete this post?", - "delete": "Radera" + "title": "Haluatko varmasti poistaa tämän julkaisun?", + "message": "Are you sure you want to delete this post?" }, "clean_cache": { - "title": "Clean Cache", - "message": "Successfully cleaned %s cache." + "title": "Puhdista välimuisti", + "message": "%s välimuisti tyhjennetty onnistuneesti." } }, "controls": { "actions": { - "back": "Back", - "next": "Next", - "previous": "Previous", - "open": "Open", - "add": "Add", - "remove": "Remove", - "edit": "Redigera", - "save": "Spara", + "back": "Takaisin", + "next": "Seuraava", + "previous": "Edellinen", + "open": "Avaa", + "add": "Lisää", + "remove": "Poista", + "edit": "Muokkaa", + "save": "Tallenna", "ok": "OK", - "done": "Done", - "confirm": "Confirm", - "continue": "Fortsätt", - "compose": "Compose", - "cancel": "Avbryt", - "discard": "Discard", - "try_again": "Försök igen", - "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": "Dela", - "share_user": "Dela %s", - "share_post": "Share Post", - "open_in_safari": "Öppna i Safari", - "find_people": "Find people to follow", + "done": "Valmis", + "confirm": "Vahvista", + "continue": "Jatka", + "compose": "Koosta", + "cancel": "Kumoa", + "discard": "Hylkää", + "try_again": "Yritä uudelleen", + "take_photo": "Ota kuva", + "save_photo": "Tallenna kuva", + "copy_photo": "Kopioi kuva", + "sign_in": "Kirjaudu sisään", + "sign_up": "Rekisteröidy", + "see_more": "Näytä lisää", + "preview": "Esikatselu", + "share": "Jaa", + "share_user": "Jaa %s", + "share_post": "Jaa julkaisu", + "open_in_safari": "Avaa Safarissa", + "open_in_browser": "Open in Browser", + "find_people": "Löydä tilejä seurattavaksi", "manually_search": "Manually search instead", - "skip": "Skip", - "reply": "Reply", - "report_user": "Rapportera %s", - "block_domain": "Block %s", - "unblock_domain": "Unblock %s", - "settings": "Inställningar", - "delete": "Radera" + "skip": "Ohita", + "reply": "Vastaa", + "report_user": "Ilmianna %s", + "block_domain": "Estä %s", + "unblock_domain": "Poista esto %s", + "settings": "Asetukset", + "delete": "Poista" }, "tabs": { - "home": "Home", - "search": "Search", - "notification": "Notification", - "profile": "Profil" + "home": "Koti", + "search": "Haku", + "notification": "Ilmoitus", + "profile": "Profiili" }, "keyboard": { "common": { - "switch_to_tab": "Switch to %s", - "compose_new_post": "Compose New Post", - "show_favorites": "Show Favorites", - "open_settings": "Open Settings" + "switch_to_tab": "Vaihda %s", + "compose_new_post": "Koosta uusi julkaisu", + "show_favorites": "Näytä suosikit", + "open_settings": "Avaa asetukset" }, "timeline": { - "previous_status": "Previous Post", - "next_status": "Next Post", - "open_status": "Open Post", - "open_author_profile": "Open Author's Profile", - "open_reblogger_profile": "Open Reblogger's Profile", - "reply_status": "Reply to Post", + "previous_status": "Edellinen julkaisu", + "next_status": "Seuraava julkaisu", + "open_status": "Avaa julkaisu", + "open_author_profile": "Avaa tekijän profiili", + "open_reblogger_profile": "Avaa edelleen jakajan profiili", + "reply_status": "Vastaa julkaisuun", "toggle_reblog": "Toggle Reblog on Post", "toggle_favorite": "Toggle Favorite on Post", - "toggle_content_warning": "Toggle Content Warning", + "toggle_content_warning": "Vaihda sisältövaroitus", "preview_image": "Preview Image" }, "segmented_control": { "previous_section": "Previous Section", - "next_section": "Next Section" + "next_section": "Seuraava lohko" } }, "status": { - "user_reblogged": "%s reblogged", - "user_replied_to": "Replied to %s", - "show_post": "Show Post", - "show_user_profile": "Show user profile", - "content_warning": "Content Warning", - "media_content_warning": "Tap anywhere to reveal", + "user_reblogged": "%s jakoi edelleen", + "user_replied_to": "Vastasi %s:lle", + "show_post": "Näytä julkaisu", + "show_user_profile": "Näytä tili", + "content_warning": "Sisältövaroitus", + "media_content_warning": "Napauta mistä tahansa paljastaaksesi", "poll": { "vote": "Vote", - "closed": "Closed" + "closed": "Suljettu" }, "actions": { - "reply": "Reply", - "reblog": "Reblog", - "unreblog": "Undo reblog", + "reply": "Vastaa", + "reblog": "Jaa edelleen", + "unreblog": "Peru edelleen jako", "favorite": "Favorite", "unfavorite": "Unfavorite", - "menu": "Meny" + "menu": "Valikko", + "hide": "Dölj" }, "tag": { "url": "URL", "mention": "Mention", - "link": "Link", - "hashtag": "Hashtag", - "email": "Email", + "link": "Linkki", + "hashtag": "Hashtagi", + "email": "Sähköposti", "emoji": "Emoji" + }, + "visibility": { + "unlisted": "Everyone can see this post but not display in the public timeline.", + "private": "Only their followers can see this post.", + "private_from_me": "Only my followers can see this post.", + "direct": "Only mentioned user can see this post." } }, "friendship": { - "follow": "Följ", - "following": "Följer", - "request": "Request", - "pending": "Pending", - "block": "Block", - "block_user": "Block %s", - "block_domain": "Block %s", - "unblock": "Unblock", + "follow": "Seuraa", + "following": "Seurataan", + "request": "Pyydä", + "pending": "Pyydetty", + "block": "Estä", + "block_user": "Estä %s", + "block_domain": "Estä %s", + "unblock": "Poista esto", "unblock_user": "Unblock %s", - "blocked": "Blocked", - "mute": "Mute", - "mute_user": "Mute %s", - "unmute": "Unmute", - "unmute_user": "Unmute %s", - "muted": "Muted", - "edit_info": "Edit Info" + "blocked": "Estetty", + "mute": "Mykistä", + "mute_user": "Mykistä %s", + "unmute": "Poista mykistys", + "unmute_user": "Poista mykistys tililtä %s", + "muted": "Mykistetty", + "edit_info": "Muokkaa profiilia" }, "timeline": { - "filtered": "Filtered", + "filtered": "Suodatettu", "timestamp": { - "now": "Now" + "now": "Nyt" }, "loader": { - "load_missing_posts": "Load missing posts", - "loading_missing_posts": "Loading missing posts...", - "show_more_replies": "Visa fler svar" + "load_missing_posts": "Lataa puuttuvat julkaisut", + "loading_missing_posts": "Ladataan puuttuvia julkaisuja...", + "show_more_replies": "Näytä lisää vastauksia" }, "header": { - "no_status_found": "No Post Found", - "blocking_warning": "You can’t view this user's profile\nuntil you unblock them.\nYour profile looks like this to them.", - "user_blocking_warning": "You can’t view %s’s profile\nuntil you unblock them.\nYour profile looks like this to them.", - "blocked_warning": "You can’t view this user’s profile\nuntil they unblock you.", - "user_blocked_warning": "You can’t view %s’s profile\nuntil they unblock you.", - "suspended_warning": "This user has been suspended.", - "user_suspended_warning": "%s’s account has been suspended." + "no_status_found": "Julkaisua ei löytynyt", + "blocking_warning": "Et voi tarkastella tämän tilin profiilia\nennen kuin poistat sen esto.\nProfiilisi näyttää tältä hänelle.", + "user_blocking_warning": "Et voi tarkastella tilin %s profiilia\nennen kuin poistat sen esto.\nProfiilisi näyttää tältä hänelle.", + "blocked_warning": "Et voi tarkastella tämän tilin profiilia\nennen kuin hän poistaa eston.", + "user_blocked_warning": "Et voi tarkastella tilin %s profiilia\nennen kuin hän poistaa eston.", + "suspended_warning": "Tämä tili on lakkautettu.", + "user_suspended_warning": "Tili %s on lakkautettu." } } } }, "scene": { "welcome": { - "slogan": "Social networking\nback in your hands." + "slogan": "Sosiaalinen verkostoituminen\ntakaisin käsissäsi.", + "get_started": "Kom igång", + "log_in": "Logga in" }, "server_picker": { - "title": "Pick a server,\nany server.", + "title": "Valitse palvelin,\nmikä tahansa palvelin.", + "subtitle": "Pick a community based on your interests, region, or a general purpose one.", + "subtitle_extend": "Pick a community based on your interests, region, or a general purpose one. Each community is operated by an entirely independent organization or individual.", "button": { "category": { - "all": "All", - "all_accessiblity_description": "Kategori: Alla", - "academia": "academia", - "activism": "activism", - "food": "food", - "furry": "furry", - "games": "games", - "general": "general", - "journalism": "journalism", - "lgbt": "lgbt", - "regional": "regional", - "art": "art", - "music": "music", - "tech": "tech" + "all": "Kaikki", + "all_accessiblity_description": "Kategoria: Kaikki", + "academia": "akateeminen", + "activism": "aktivismi", + "food": "ruoka", + "furry": "turri", + "games": "pelit", + "general": "yleinen", + "journalism": "journalismi", + "lgbt": "hlbt", + "regional": "alueellinen", + "art": "taide", + "music": "musiikki", + "tech": "tekniikka" }, - "see_less": "See Less", - "see_more": "See More" + "see_less": "Näytä vähemmän", + "see_more": "Näytä lisää" }, "label": { - "language": "SPRÅK", - "users": "ANVÄNDARE", - "category": "KATEGORI" + "language": "KIELI", + "users": "TILIÄ", + "category": "KATEGORIA" }, "input": { - "placeholder": "Find a server or join your own..." + "placeholder": "Etsi palvelin tai liity omaan..." }, "empty_state": { - "finding_servers": "Finding available servers...", - "bad_network": "Something went wrong while loading the data. Check your internet connection.", - "no_results": "Inga resultat" + "finding_servers": "Etsistään saatavilla olevia palvelimia...", + "bad_network": "Jokin meni pieleen dataa ladatessa. Tarkista internet-yhteytesi.", + "no_results": "Ei hakutuloksia" } }, "register": { - "title": "Tell us about you.", + "title": "Kerro meille sinusta.", "input": { "avatar": { - "delete": "Radera" + "delete": "Poista" }, "username": { - "placeholder": "username", - "duplicate_prompt": "This username is taken." + "placeholder": "käyttäjänimi", + "duplicate_prompt": "Tämä käyttäjänimi on varattu." }, "display_name": { - "placeholder": "display name" + "placeholder": "näyttönimi" }, "email": { - "placeholder": "email" + "placeholder": "sähköposti" }, "password": { - "placeholder": "password", - "hint": "Your password needs at least eight characters" + "placeholder": "salasana", + "require": "Your password needs at least:", + "character_limit": "8 characters", + "accessibility": { + "checked": "checked", + "unchecked": "unchecked" + }, + "hint": "Salasanassasi on oltava vähintään kahdeksan merkkiä" }, "invite": { - "registration_user_invite_request": "Why do you want to join?" + "registration_user_invite_request": "Miksi haluat liittyä?" } }, "error": { "item": { - "username": "Användarnamn", - "email": "Email", - "password": "Password", - "agreement": "Agreement", + "username": "Käyttäjänimi", + "email": "Sähköposti", + "password": "Salasana", + "agreement": "Hyväksy", "locale": "Locale", - "reason": "Reason" + "reason": "Syy" }, "reason": { - "blocked": "%s contains a disallowed email provider", - "unreachable": "%s does not seem to exist", - "taken": "%s is already in use", + "blocked": "%s sisältää estetyn sähköpostipalveluntarjoajan", + "unreachable": "%s ei näytä olevan olemassa", + "taken": "%s on jo käytössä", "reserved": "%s is a reserved keyword", - "accepted": "%s must be accepted", - "blank": "%s is required", - "invalid": "%s is invalid", - "too_long": "%s is too long", - "too_short": "%s is too short", - "inclusion": "%s is not a supported value" + "accepted": "%s täytyy hyväksyä", + "blank": "%s vaaditaan", + "invalid": "%s on virheellinen", + "too_long": "%s on liian pitkä", + "too_short": "%s on liian lyhyt", + "inclusion": "%s ei ole tuettu arvo" }, "special": { - "username_invalid": "Username must only contain alphanumeric characters and underscores", - "username_too_long": "Username is too long (can’t be longer than 30 characters)", - "email_invalid": "This is not a valid email address", - "password_too_short": "Password is too short (must be at least 8 characters)" + "username_invalid": "Käyttäjänimi voi sisältää ainoastaan aakkosnumerrisia merkkejä ja alaviivoja", + "username_too_long": "Käyttäjänimi on liian pitkä (ei voi olla pidempi kuin 30 merkkiä)", + "email_invalid": "Tämä ei ole kelvollinen sähköpostiosoite", + "password_too_short": "Salasana on liian lyhyt (täytyy olla vähintään 8 merkkiä)" } } }, "server_rules": { - "title": "Some ground rules.", - "subtitle": "These rules are set by the admins of %s.", - "prompt": "By continuing, you’re subject to the terms of service and privacy policy for %s.", - "terms_of_service": "terms of service", - "privacy_policy": "integritetspolicy", + "title": "Joitakin perussääntöjä.", + "subtitle": "Nämä säännöt ovat %s -palvelun asettamia.", + "prompt": "Jatkamalla, hyväksyt palvelun %s palveluehdot ja tietosuojakäytönnön.", + "terms_of_service": "käyttöehdot", + "privacy_policy": "tietosuojakäytäntö", "button": { - "confirm": "I Agree" + "confirm": "Hyväksyn" } }, "confirm_email": { - "title": "One last thing.", - "subtitle": "We just sent an email to %s,\ntap the link to confirm your account.", + "title": "Viimeinen asia.", + "subtitle": "Lähetimme juuri sähköpostin osoitteeseen %s, napauta siinä olevaa linkkiä vahvistaaksesi tilisi.", "button": { - "open_email_app": "Open Email App", - "dont_receive_email": "I never got an email" + "open_email_app": "Avaa sähköpostisovellus", + "resend": "Resend" }, "dont_receive_email": { - "title": "Check your email", - "description": "Check if your email address is correct as well as your junk folder if you haven’t.", - "resend_email": "Resend Email" + "title": "Tarkista sähköpostisi", + "description": "Tarkista, että sähköpostiosoitteesi on oikea, sekä roskapostikansiosi, jos et vielä ole.", + "resend_email": "Lähetä sähköposti uudelleen" }, "open_email_app": { - "title": "Check your inbox.", - "description": "We just sent you an email. Check your junk folder if you haven’t.", - "mail": "Mail", - "open_email_client": "Open Email Client" + "title": "Tarkasta postilaatikkosi.", + "description": "Lähetimme sinulle juuri sähköpostin. Tarkista myös roskapostikansiosi, jos et vielä ole.", + "mail": "Sähköposti", + "open_email_client": "Avaa sähköpostisovellus" } }, "home_timeline": { - "title": "Home", + "title": "Koti", "navigation_bar_state": { - "offline": "Offline", - "new_posts": "See new posts", - "published": "Published!", - "Publishing": "Publishing post..." + "offline": "Yhteydetön", + "new_posts": "Uusia julkaisuja", + "published": "Julkaistu!", + "Publishing": "Julkaistaan julkaisua..." } }, "suggestion_account": { - "title": "Find People to Follow", - "follow_explain": "When you follow someone, you’ll see their posts in your home feed." + "title": "Löydä tilejä seurattavaksi", + "follow_explain": "Kun seuraat jotakuta, näet hänen julkaisunsa kotisyötteessäsi." }, "compose": { "title": { - "new_post": "New Post", - "new_reply": "New Reply" + "new_post": "Uusi julkaisu", + "new_reply": "Uusi vastaus" }, "media_selection": { - "camera": "Take Photo", - "photo_library": "Photo Library", - "browse": "Bläddra" + "camera": "Ota kuva", + "photo_library": "Kuvakirjasto", + "browse": "Selaa" }, - "content_input_placeholder": "Type or paste what’s on your mind", - "compose_action": "Publicera", - "replying_to_user": "replying to %s", + "content_input_placeholder": "Kirjoita tai liitä, siitä mitä ajattelet", + "compose_action": "Julkaise", + "replying_to_user": "vastaamassa tilille %s", "attachment": { - "photo": "photo", + "photo": "kuva", "video": "video", "attachment_broken": "This %s is broken and can’t be\nuploaded to Mastodon.", - "description_photo": "Describe the photo for the visually-impaired...", - "description_video": "Describe the video for the visually-impaired..." + "description_photo": "Kuvaile kuva näkövammaisille...", + "description_video": "Kuvaile video näkövammaisille..." }, "poll": { - "duration_time": "Varaktighet: %s", - "thirty_minutes": "30 minuter", - "one_hour": "1 Hour", - "six_hours": "6 Hours", - "one_day": "1 Day", - "three_days": "3 Days", - "seven_days": "7 Days", - "option_number": "Option %ld" + "duration_time": "Kesto: %s", + "thirty_minutes": "30 minuuttia", + "one_hour": "1 tunti", + "six_hours": "6 tuntia", + "one_day": "1 päivä", + "three_days": "3 päivää", + "seven_days": "7 päivää", + "option_number": "Vaihtoehto %ld" }, "content_warning": { - "placeholder": "Write an accurate warning here..." + "placeholder": "Kirjoita tarkka varoitus tähän..." }, "visibility": { - "public": "Public", - "unlisted": "Unlisted", - "private": "Followers only", - "direct": "Only people I mention" + "public": "Julkinen", + "unlisted": "Listaamaton", + "private": "Vain seuraajat", + "direct": "Vain mainitsemani tilit" }, "auto_complete": { "space_to_add": "Space to add" }, "accessibility": { - "append_attachment": "Add Attachment", - "append_poll": "Add 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" + "append_attachment": "Lisää liite", + "append_poll": "Lisää kysely", + "remove_poll": "Poista kysely", + "custom_emoji_picker": "Mukautettu emojivalitsin", + "enable_content_warning": "Ota sisältövaroitus käyttöön", + "disable_content_warning": "Poista sisältövaroitus käytöstä", + "post_visibility_menu": "Julkaisun näkyvyysvalikko" }, "keyboard": { - "discard_post": "Discard Post", - "publish_post": "Publish Post", - "toggle_poll": "Toggle Poll", - "toggle_content_warning": "Toggle Content Warning", - "append_attachment_entry": "Add Attachment - %s", - "select_visibility_entry": "Select Visibility - %s" + "discard_post": "Hylkää julkaisu", + "publish_post": "Julkaise julkaisu", + "toggle_poll": "Vaihda kysely", + "toggle_content_warning": "Vaihda sisältövaroitus", + "append_attachment_entry": "Lisää liite - %s", + "select_visibility_entry": "Valitse näkyvyys - %s" } }, "profile": { "dashboard": { - "posts": "posts", - "following": "following", - "followers": "followers" + "posts": "julkaisut", + "following": "seurataan", + "followers": "seuraajat" }, "fields": { - "add_row": "Add Row", + "add_row": "Lisää rivi", "placeholder": { - "label": "Label", - "content": "Content" + "label": "Nimi", + "content": "Sisältö" } }, "segmented_control": { - "posts": "Posts", - "replies": "Replies", - "media": "Media" + "posts": "Julkaisut", + "replies": "Vastaukset", + "posts_and_replies": "Posts and Replies", + "media": "Media", + "about": "Om" }, "relationship_action_alert": { - "confirm_unmute_user": { - "title": "Unmute Account", - "message": "Confirm to unmute %s" + "confirm_mute_user": { + "title": "Mute Account", + "message": "Confirm to mute %s" }, - "confirm_unblock_usre": { + "confirm_unmute_user": { + "title": "Poista tilin mykistys", + "message": "Vahvista, että haluat poistaa mykistyksen tililtä %s" + }, + "confirm_block_user": { + "title": "Block Account", + "message": "Confirm to block %s" + }, + "confirm_unblock_user": { "title": "Unblock Account", "message": "Confirm to unblock %s" } } }, "follower": { - "footer": "Followers from other servers are not displayed." + "footer": "Seuraajia muilta palvelimilta ei näytetä." }, "following": { - "footer": "Follows from other servers are not displayed." + "footer": "Seurauksia muilta palvelimilta ei näytetä." }, "search": { - "title": "Search", + "title": "Haku", "search_bar": { - "placeholder": "Search hashtags and users", - "cancel": "Avbryt" + "placeholder": "Haku", + "cancel": "Kumoa" }, "recommend": { - "button_text": "See All", + "button_text": "Katso kaikki", "hash_tag": { - "title": "Trending on Mastodon", - "description": "Hashtags that are getting quite a bit of attention", - "people_talking": "%s people are talking" + "title": "Trendaavat Mastodonissa", + "description": "Hashtagit, jotka saavat melkoisesti huomiota", + "people_talking": "%s ihmistä puhuu" }, "accounts": { - "title": "Accounts you might like", - "description": "You may like to follow these accounts", - "follow": "Följ" + "title": "Saatat pitää näistä tileistä", + "description": "Haluta ehkä seurata näitä tilejä", + "follow": "Seuraa" } }, "searching": { "segment": { - "all": "All", - "people": "People", - "hashtags": "Hashtags", - "posts": "Posts" + "all": "Kaikki", + "people": "Tilit", + "hashtags": "Hashtagit", + "posts": "Julkaisut" }, "empty_state": { - "no_results": "Inga resultat" + "no_results": "Ei hakutuloksia" }, - "recent_search": "Recent searches", - "clear": "Clear" + "recent_search": "Viimeaikaiset", + "clear": "Tyhjennä" } }, "favorite": { - "title": "Your Favorites" + "title": "Omat suosikit" }, "notification": { "title": { - "Everything": "Everything", - "Mentions": "Mentions" + "Everything": "Kaikki", + "Mentions": "Maininnat" + }, + "notification_description": { + "followed_you": "followed you", + "favorited_your_post": "favorited your post", + "reblogged_your_post": "reblogged your post", + "mentioned_you": "nämnde dig", + "request_to_follow_you": "request to follow you", + "poll_has_ended": "poll has ended" }, - "user_followed_you": "%s följde dig", - "user_favorited your post": "%s favorited your post", - "user_reblogged_your_post": "%s reblogged your post", - "user_mentioned_you": "%s nämnde dig", - "user_requested_to_follow_you": "%s har begärt att följa dig", - "user_your_poll_has_ended": "%s Omröstningen har avslutats", "keyobard": { - "show_everything": "Show Everything", - "show_mentions": "Show Mentions" + "show_everything": "Näytä kaikki", + "show_mentions": "Näytä maininnat" } }, "thread": { - "back_title": "Post", - "title": "Post from %s" + "back_title": "Julkaisu", + "title": "Julkaisu tililtä %s" }, "settings": { - "title": "Inställningar", + "title": "Asetukset", "section": { "appearance": { - "title": "Appearance", - "automatic": "Automatic", - "light": "Always Light", - "dark": "Always Dark" + "title": "Ulkoasu", + "automatic": "Seuraa järjestelmää", + "light": "Vaalea", + "dark": "Tumma" + }, + "look_and_feel": { + "title": "Look and Feel", + "use_system": "Use System", + "really_dark": "Really Dark", + "sorta_dark": "Sorta Dark", + "light": "Ljust" }, "notifications": { - "title": "Notifications", + "title": "Ilmoitukset", "favorites": "Favorites my post", - "follows": "Follows me", - "boosts": "Reblogs my post", - "mentions": "Mentions me", + "follows": "Seuraa minua", + "boosts": "Omien julkaisujen edelleen jaot", + "mentions": "Mainitsee minut", "trigger": { - "anyone": "anyone", - "follower": "a follower", - "follow": "anyone I follow", - "noone": "no one", - "title": "Notify me when" + "anyone": "kuka tahansa", + "follower": "seuraaja", + "follow": "kuka tahansa, jota seuraan", + "noone": "ei kukaan", + "title": "Ilmoita minulle, kun" } }, "preference": { - "title": "Preferences", - "true_black_dark_mode": "True black dark mode", - "disable_avatar_animation": "Disable animated avatars", - "disable_emoji_animation": "Disable animated emojis", - "using_default_browser": "Use default browser to open links" + "title": "Lisäasetukset", + "true_black_dark_mode": "Todellinen mustan tumma tila", + "disable_avatar_animation": "Poista käytöstä animoidut avatarit", + "disable_emoji_animation": "Poista käytöstä animoidut emojit", + "using_default_browser": "Käytä oletusselainta linkkien avaamiseen" }, "boring_zone": { - "title": "The Boring Zone", - "account_settings": "Account Settings", - "terms": "Terms of Service", - "privacy": "Integritetspolicy" + "title": "Tylsä alue", + "account_settings": "Tiliasetukset", + "terms": "Palveluehdot", + "privacy": "Tietosuojakäytäntö" }, "spicy_zone": { - "title": "The Spicy Zone", - "clear": "Clear Media Cache", - "signout": "Logga ut" + "title": "Varovainen alue", + "clear": "Tyhjennä median välimuisti", + "signout": "Kirjaudu ulos" } }, "footer": { - "mastodon_description": "Mastodon is open source software. You can report issues on GitHub at %s (%s)" + "mastodon_description": "Mastodon on avoimen lähdekoodin ohjelmisto. Voit raportoida ongelmasta GitHubissa osoitteessa %s (%s)" }, "keyboard": { - "close_settings_window": "Close Settings Window" + "close_settings_window": "Sulje asetukset" } }, "report": { - "title": "Rapportera %s", - "step1": "Steg 1 av 2", - "step2": "Steg 2 av 2", - "content1": "Are there any other posts you’d like to add to the report?", - "content2": "Is there anything the moderators should know about this report?", - "send": "Send Report", - "skip_to_send": "Send without comment", - "text_placeholder": "Type or paste additional comments" + "title_report": "Report", + "title": "Ilmianna %s", + "step1": "Vaihe 1/2", + "step2": "Vaihe 2/2", + "content1": "Onko julkaisuja, joita haluaisit lisätä ilmiantoon?", + "content2": "Onko valvojien syytä tietää tästä ilmiannosta?", + "report_sent_title": "Thanks for reporting, we’ll look into this.", + "send": "Lähetä ilmianto", + "skip_to_send": "Lähetä ilman kommentteja", + "text_placeholder": "Kirjoita tai liitä lisäkommentteja", + "reported": "REPORTED" }, "preview": { "keyboard": { - "close_preview": "Close Preview", - "show_next": "Show Next", - "show_previous": "Show Previous" + "close_preview": "Sulje esikatselu", + "show_next": "Näytä seuraava", + "show_previous": "Näytä edellinen" } }, "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" + "tab_bar_hint": "Nykyinen valittu profiili: %s. Kaksoisnapauta ja pidä sitten painettuna näytääksesi tilin vaihtajan", + "dismiss_account_switcher": "Sulje tilin vaihtaja", + "add_account": "Lisää tili" }, "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" + "new_in_mastodon": "Uutta Mastodonissa", + "multiple_account_switch_intro_description": "Vaihda useiden tilien välillä pitämällä profiilipainiketta painettuna.", + "accessibility_hint": "Hylkää tämä ohjattu toiminto kaksoisnapauttamalla" } } } \ No newline at end of file diff --git a/Localization/StringsConvertor/input/sv_FI/ios-infoPlist.json b/Localization/StringsConvertor/input/sv_FI/ios-infoPlist.json index c6db73de..eb389f3b 100644 --- a/Localization/StringsConvertor/input/sv_FI/ios-infoPlist.json +++ b/Localization/StringsConvertor/input/sv_FI/ios-infoPlist.json @@ -1,6 +1,6 @@ { - "NSCameraUsageDescription": "Used to take photo for post status", - "NSPhotoLibraryAddUsageDescription": "Used to save photo into the Photo Library", - "NewPostShortcutItemTitle": "New Post", - "SearchShortcutItemTitle": "Search" + "NSCameraUsageDescription": "Käytetään kuvan ottamiseen julkaisua varten", + "NSPhotoLibraryAddUsageDescription": "Käytetään kuvan tallentamiseen kuvakirjastoon", + "NewPostShortcutItemTitle": "Uusi julkaisu", + "SearchShortcutItemTitle": "Haku" } diff --git a/Localization/StringsConvertor/input/sv_SE/Localizable.stringsdict b/Localization/StringsConvertor/input/sv_SE/Localizable.stringsdict index 65316e3d..f8da5e39 100644 --- a/Localization/StringsConvertor/input/sv_SE/Localizable.stringsdict +++ b/Localization/StringsConvertor/input/sv_SE/Localizable.stringsdict @@ -29,9 +29,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 character</string> + <string>1 tecken</string> <key>other</key> - <string>%ld characters</string> + <string>%ld tecken</string> </dict> </dict> <key>a11y.plural.count.input_limit_remains</key> @@ -45,9 +45,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 character</string> + <string>1 tecken</string> <key>other</key> - <string>%ld characters</string> + <string>%ld tecken</string> </dict> </dict> <key>plural.count.metric_formatted.post</key> @@ -125,9 +125,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 vote</string> + <string>1 röst</string> <key>other</key> - <string>%ld votes</string> + <string>%ld röster</string> </dict> </dict> <key>plural.count.voter</key> @@ -381,7 +381,7 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1s ago</string> + <string>1s sedan</string> <key>other</key> <string>%lds ago</string> </dict> diff --git a/Localization/StringsConvertor/input/sv_SE/app.json b/Localization/StringsConvertor/input/sv_SE/app.json index 7acf4875..59ad0d6e 100644 --- a/Localization/StringsConvertor/input/sv_SE/app.json +++ b/Localization/StringsConvertor/input/sv_SE/app.json @@ -45,11 +45,11 @@ "message": "Please enable the photo library access permission to save the photo." }, "delete_post": { - "title": "Are you sure you want to delete this post?", - "delete": "Radera" + "title": "Delete Post", + "message": "Are you sure you want to delete this post?" }, "clean_cache": { - "title": "Clean Cache", + "title": "Rensa cache", "message": "Successfully cleaned %s cache." } }, @@ -64,7 +64,7 @@ "edit": "Redigera", "save": "Spara", "ok": "OK", - "done": "Done", + "done": "Klar", "confirm": "Confirm", "continue": "Fortsätt", "compose": "Compose", @@ -72,8 +72,8 @@ "discard": "Discard", "try_again": "Försök igen", "take_photo": "Take Photo", - "save_photo": "Save Photo", - "copy_photo": "Copy Photo", + "save_photo": "Spara foto", + "copy_photo": "Kopiera foto", "sign_in": "Sign In", "sign_up": "Sign Up", "see_more": "See More", @@ -82,6 +82,7 @@ "share_user": "Dela %s", "share_post": "Share Post", "open_in_safari": "Öppna i Safari", + "open_in_browser": "Open in Browser", "find_people": "Find people to follow", "manually_search": "Manually search instead", "skip": "Skip", @@ -139,7 +140,8 @@ "unreblog": "Undo reblog", "favorite": "Favorite", "unfavorite": "Unfavorite", - "menu": "Meny" + "menu": "Meny", + "hide": "Dölj" }, "tag": { "url": "URL", @@ -148,6 +150,12 @@ "hashtag": "Hashtag", "email": "Email", "emoji": "Emoji" + }, + "visibility": { + "unlisted": "Everyone can see this post but not display in the public timeline.", + "private": "Only their followers can see this post.", + "private_from_me": "Only my followers can see this post.", + "direct": "Only mentioned user can see this post." } }, "friendship": { @@ -171,7 +179,7 @@ "timeline": { "filtered": "Filtered", "timestamp": { - "now": "Now" + "now": "Nu" }, "loader": { "load_missing_posts": "Load missing posts", @@ -192,10 +200,14 @@ }, "scene": { "welcome": { - "slogan": "Social networking\nback in your hands." + "slogan": "Social networking\nback in your hands.", + "get_started": "Kom igång", + "log_in": "Logga in" }, "server_picker": { - "title": "Pick a server,\nany server.", + "title": "Mastodon is made of users in different communities.", + "subtitle": "Pick a community based on your interests, region, or a general purpose one.", + "subtitle_extend": "Pick a community based on your interests, region, or a general purpose one. Each community is operated by an entirely independent organization or individual.", "button": { "category": { "all": "All", @@ -222,7 +234,7 @@ "category": "KATEGORI" }, "input": { - "placeholder": "Find a server or join your own..." + "placeholder": "Search communities" }, "empty_state": { "finding_servers": "Finding available servers...", @@ -231,7 +243,7 @@ } }, "register": { - "title": "Tell us about you.", + "title": "Let’s get you set up on %s", "input": { "avatar": { "delete": "Radera" @@ -248,6 +260,12 @@ }, "password": { "placeholder": "password", + "require": "Your password needs at least:", + "character_limit": "8 characters", + "accessibility": { + "checked": "checked", + "unchecked": "unchecked" + }, "hint": "Your password needs at least eight characters" }, "invite": { @@ -258,7 +276,7 @@ "item": { "username": "Användarnamn", "email": "Email", - "password": "Password", + "password": "Lösenord", "agreement": "Agreement", "locale": "Locale", "reason": "Reason" @@ -285,7 +303,7 @@ }, "server_rules": { "title": "Some ground rules.", - "subtitle": "These rules are set by the admins of %s.", + "subtitle": "These are set and enforced by the %s moderators.", "prompt": "By continuing, you’re subject to the terms of service and privacy policy for %s.", "terms_of_service": "terms of service", "privacy_policy": "integritetspolicy", @@ -295,10 +313,10 @@ }, "confirm_email": { "title": "One last thing.", - "subtitle": "We just sent an email to %s,\ntap the link to confirm your account.", + "subtitle": "Tap the link we emailed to you to verify your account.", "button": { "open_email_app": "Open Email App", - "dont_receive_email": "I never got an email" + "resend": "Resend" }, "dont_receive_email": { "title": "Check your email", @@ -332,7 +350,7 @@ }, "media_selection": { "camera": "Take Photo", - "photo_library": "Photo Library", + "photo_library": "Fotobibliotek", "browse": "Bläddra" }, "content_input_placeholder": "Type or paste what’s on your mind", @@ -401,14 +419,24 @@ "segmented_control": { "posts": "Posts", "replies": "Replies", - "media": "Media" + "posts_and_replies": "Posts and Replies", + "media": "Media", + "about": "Om" }, "relationship_action_alert": { + "confirm_mute_user": { + "title": "Mute Account", + "message": "Confirm to mute %s" + }, "confirm_unmute_user": { "title": "Unmute Account", "message": "Confirm to unmute %s" }, - "confirm_unblock_usre": { + "confirm_block_user": { + "title": "Block Account", + "message": "Confirm to block %s" + }, + "confirm_unblock_user": { "title": "Unblock Account", "message": "Confirm to unblock %s" } @@ -450,7 +478,7 @@ "no_results": "Inga resultat" }, "recent_search": "Recent searches", - "clear": "Clear" + "clear": "Rensa" } }, "favorite": { @@ -461,12 +489,14 @@ "Everything": "Everything", "Mentions": "Mentions" }, - "user_followed_you": "%s följde dig", - "user_favorited your post": "%s favorited your post", - "user_reblogged_your_post": "%s reblogged your post", - "user_mentioned_you": "%s nämnde dig", - "user_requested_to_follow_you": "%s har begärt att följa dig", - "user_your_poll_has_ended": "%s Omröstningen har avslutats", + "notification_description": { + "followed_you": "followed you", + "favorited_your_post": "favorited your post", + "reblogged_your_post": "reblogged your post", + "mentioned_you": "nämnde dig", + "request_to_follow_you": "request to follow you", + "poll_has_ended": "poll has ended" + }, "keyobard": { "show_everything": "Show Everything", "show_mentions": "Show Mentions" @@ -485,6 +515,13 @@ "light": "Always Light", "dark": "Always Dark" }, + "look_and_feel": { + "title": "Look and Feel", + "use_system": "Use System", + "really_dark": "Really Dark", + "sorta_dark": "Sorta Dark", + "light": "Ljust" + }, "notifications": { "title": "Notifications", "favorites": "Favorites my post", @@ -502,14 +539,14 @@ "preference": { "title": "Preferences", "true_black_dark_mode": "True black dark mode", - "disable_avatar_animation": "Disable animated avatars", - "disable_emoji_animation": "Disable animated emojis", + "disable_avatar_animation": "Inaktivera animerade avatarer", + "disable_emoji_animation": "Inaktivera animerade emojis", "using_default_browser": "Use default browser to open links" }, "boring_zone": { "title": "The Boring Zone", - "account_settings": "Account Settings", - "terms": "Terms of Service", + "account_settings": "Kontoinställningar", + "terms": "Användarvillkor", "privacy": "Integritetspolicy" }, "spicy_zone": { @@ -526,14 +563,17 @@ } }, "report": { + "title_report": "Report", "title": "Rapportera %s", "step1": "Steg 1 av 2", "step2": "Steg 2 av 2", "content1": "Are there any other posts you’d like to add to the report?", "content2": "Is there anything the moderators should know about this report?", - "send": "Send Report", + "report_sent_title": "Thanks for reporting, we’ll look into this.", + "send": "Skicka rapport", "skip_to_send": "Send without comment", - "text_placeholder": "Type or paste additional comments" + "text_placeholder": "Type or paste additional comments", + "reported": "REPORTED" }, "preview": { "keyboard": { diff --git a/Localization/StringsConvertor/input/th_TH/app.json b/Localization/StringsConvertor/input/th_TH/app.json index 7852b5d0..001075b1 100644 --- a/Localization/StringsConvertor/input/th_TH/app.json +++ b/Localization/StringsConvertor/input/th_TH/app.json @@ -45,8 +45,8 @@ "message": "โปรดเปิดใช้งานสิทธิอนุญาตการเข้าถึงคลังรูปภาพเพื่อบันทึกรูปภาพ" }, "delete_post": { - "title": "คุณแน่ใจหรือไม่ว่าต้องการลบโพสต์นี้?", - "delete": "ลบ" + "title": "ลบโพสต์", + "message": "คุณแน่ใจหรือไม่ว่าต้องการลบโพสต์นี้?" }, "clean_cache": { "title": "ล้างแคช", @@ -82,6 +82,7 @@ "share_user": "แบ่งปัน %s", "share_post": "แบ่งปันโพสต์", "open_in_safari": "เปิดใน Safari", + "open_in_browser": "เปิดในเบราว์เซอร์", "find_people": "ค้นหาผู้คนที่จะติดตาม", "manually_search": "ค้นหาด้วยตนเองแทน", "skip": "ข้าม", @@ -139,7 +140,8 @@ "unreblog": "เลิกทำการดัน", "favorite": "ชื่นชอบ", "unfavorite": "เลิกชื่นชอบ", - "menu": "เมนู" + "menu": "เมนู", + "hide": "ซ่อน" }, "tag": { "url": "URL", @@ -148,6 +150,12 @@ "hashtag": "แฮชแท็ก", "email": "อีเมล", "emoji": "อีโมจิ" + }, + "visibility": { + "unlisted": "ทุกคนสามารถเห็นโพสต์นี้แต่ไม่แสดงในเส้นเวลาสาธารณะ", + "private": "เฉพาะผู้ติดตามของเขาเท่านั้นที่สามารถเห็นโพสต์นี้", + "private_from_me": "เฉพาะผู้ติดตามของฉันเท่านั้นที่สามารถเห็นโพสต์นี้", + "direct": "เฉพาะผู้ใช้ที่กล่าวถึงเท่านั้นที่สามารถเห็นโพสต์นี้" } }, "friendship": { @@ -180,10 +188,10 @@ }, "header": { "no_status_found": "ไม่พบโพสต์", - "blocking_warning": "คุณไม่สามารถดูโปรไฟล์ของผู้ใช้นี้\nจนกว่าคุณจะเลิกปิดกั้นผู้ใช้นี้\nผู้ใช้นี้เห็นโปรไฟล์ของคุณเหมือนกับที่คุณเห็น", - "user_blocking_warning": "คุณไม่สามารถดูโปรไฟล์ของ %s\nจนกว่าคุณจะเลิกปิดกั้นผู้ใช้นี้\nผู้ใช้นี้เห็นโปรไฟล์ของคุณเหมือนกับที่คุณเห็น", - "blocked_warning": "คุณไม่สามารถดูโปรไฟล์ของผู้ใช้นี้\nจนกว่าผู้ใช้นี้จะเลิกปิดกั้นคุณ", - "user_blocked_warning": "คุณไม่สามารถดูโปรไฟล์ของ %s\nจนกว่าผู้ใช้นี้จะเลิกปิดกั้นคุณ", + "blocking_warning": "คุณไม่สามารถดูโปรไฟล์ของผู้ใช้นี้\nจนกว่าคุณจะเลิกปิดกั้นเขา\nโปรไฟล์ของคุณมีลักษณะเช่นนี้สำหรับเขา", + "user_blocking_warning": "คุณไม่สามารถดูโปรไฟล์ของ %s\nจนกว่าคุณจะเลิกปิดกั้นเขา\nโปรไฟล์ของคุณมีลักษณะเช่นนี้สำหรับเขา", + "blocked_warning": "คุณไม่สามารถดูโปรไฟล์ของผู้ใช้นี้\nจนกว่าเขาจะเลิกปิดกั้นคุณ", + "user_blocked_warning": "คุณไม่สามารถดูโปรไฟล์ของ %s\nจนกว่าเขาจะเลิกปิดกั้นคุณ", "suspended_warning": "ผู้ใช้นี้ถูกระงับการใช้งาน", "user_suspended_warning": "บัญชีของ %s ถูกระงับการใช้งาน" } @@ -192,10 +200,14 @@ }, "scene": { "welcome": { - "slogan": "ให้เครือข่ายสังคม\nกลับมาอยู่ในมือของคุณ" + "slogan": "ให้เครือข่ายสังคม\nกลับมาอยู่ในมือของคุณ", + "get_started": "เริ่มต้นใช้งาน", + "log_in": "เข้าสู่ระบบ" }, "server_picker": { - "title": "เลือกเซิร์ฟเวอร์\nอันไหนก็ได้", + "title": "Mastodon ประกอบด้วยผู้ใช้ในชุมชนต่าง ๆ", + "subtitle": "เลือกชุมชนตามความสนใจ, ภูมิภาค หรือวัตถุประสงค์ทั่วไปของคุณ", + "subtitle_extend": "เลือกชุมชนตามความสนใจ, ภูมิภาค หรือวัตถุประสงค์ทั่วไปของคุณ แต่ละชุมชนดำเนินการโดยองค์กรหรือบุคคลที่เป็นอิสระโดยสิ้นเชิง", "button": { "category": { "all": "ทั้งหมด", @@ -222,7 +234,7 @@ "category": "หมวดหมู่" }, "input": { - "placeholder": "ค้นหาเซิร์ฟเวอร์หรือเข้าร่วมของคุณเอง..." + "placeholder": "ค้นหาชุมชน" }, "empty_state": { "finding_servers": "กำลังค้นหาเซิร์ฟเวอร์ที่พร้อมใช้งาน...", @@ -231,7 +243,7 @@ } }, "register": { - "title": "บอกเราเกี่ยวกับคุณ", + "title": "มาตั้งค่าของคุณใน %s กันเลย", "input": { "avatar": { "delete": "ลบ" @@ -248,6 +260,12 @@ }, "password": { "placeholder": "รหัสผ่าน", + "require": "รหัสผ่านของคุณต้องมีอย่างน้อย:", + "character_limit": "8 ตัวอักษร", + "accessibility": { + "checked": "กาเครื่องหมายแล้ว", + "unchecked": "ไม่ได้กาเครื่องหมาย" + }, "hint": "รหัสผ่านของคุณต้องมีอย่างน้อยแปดตัวอักษร" }, "invite": { @@ -285,7 +303,7 @@ }, "server_rules": { "title": "กฎพื้นฐานบางประการ", - "subtitle": "กฎเหล่านี้ถูกตั้งโดยผู้ดูแลของ %s", + "subtitle": "มีการตั้งและบังคับใช้กฎเหล่านี้โดยผู้ควบคุมของ %s", "prompt": "เมื่อคุณดำเนินการต่อ คุณอยู่ภายใต้เงื่อนไขการให้บริการและนโยบายความเป็นส่วนตัวสำหรับ %s", "terms_of_service": "เงื่อนไขการให้บริการ", "privacy_policy": "นโยบายความเป็นส่วนตัว", @@ -295,10 +313,10 @@ }, "confirm_email": { "title": "หนึ่งสิ่งสุดท้าย", - "subtitle": "เราเพิ่งส่งอีเมลไปยัง %s\nแตะที่ลิงก์เพื่อยืนยันบัญชีของคุณ", + "subtitle": "แตะลิงก์ที่เราส่งอีเมลถึงคุณเพื่อยืนยันบัญชีของคุณ", "button": { "open_email_app": "เปิดแอปอีเมล", - "dont_receive_email": "ฉันไม่เคยได้รับอีเมล" + "resend": "ส่งใหม่" }, "dont_receive_email": { "title": "ตรวจสอบอีเมลของคุณ", @@ -401,14 +419,24 @@ "segmented_control": { "posts": "โพสต์", "replies": "การตอบกลับ", - "media": "สื่อ" + "posts_and_replies": "โพสต์และการตอบกลับ", + "media": "สื่อ", + "about": "เกี่ยวกับ" }, "relationship_action_alert": { + "confirm_mute_user": { + "title": "ซ่อนบัญชี", + "message": "ยืนยันเพื่อซ่อน %s" + }, "confirm_unmute_user": { "title": "เลิกซ่อนบัญชี", "message": "ยืนยันเพื่อเลิกซ่อน %s" }, - "confirm_unblock_usre": { + "confirm_block_user": { + "title": "ปิดกั้นบัญชี", + "message": "ยืนยันเพื่อปิดกั้น %s" + }, + "confirm_unblock_user": { "title": "เลิกปิดกั้นบัญชี", "message": "ยืนยันเพื่อเลิกปิดกั้น %s" } @@ -461,12 +489,14 @@ "Everything": "ทุกอย่าง", "Mentions": "การกล่าวถึง" }, - "user_followed_you": "%s ได้ติดตามคุณ", - "user_favorited your post": "%s ได้ชื่นชอบโพสต์ของคุณ", - "user_reblogged_your_post": "%s ได้ดันโพสต์ของคุณ", - "user_mentioned_you": "%s ได้กล่าวถึงคุณ", - "user_requested_to_follow_you": "%s ได้ขอติดตามคุณ", - "user_your_poll_has_ended": "%s โพลของคุณได้สิ้นสุดแล้ว", + "notification_description": { + "followed_you": "ได้ติดตามคุณ", + "favorited_your_post": "ได้ชื่นชอบโพสต์ของคุณ", + "reblogged_your_post": "ได้ดันโพสต์ของคุณ", + "mentioned_you": "ได้กล่าวถึงคุณ", + "request_to_follow_you": "ขอติดตามคุณ", + "poll_has_ended": "การสำรวจความคิดเห็นได้สิ้นสุดแล้ว" + }, "keyobard": { "show_everything": "แสดงทุกอย่าง", "show_mentions": "แสดงการกล่าวถึง" @@ -485,6 +515,13 @@ "light": "สว่างเสมอ", "dark": "มืดเสมอ" }, + "look_and_feel": { + "title": "ลักษณะที่แสดง", + "use_system": "ใช้ของระบบ", + "really_dark": "มืดมาก", + "sorta_dark": "ค่อนข้างมืด", + "light": "สว่าง" + }, "notifications": { "title": "การแจ้งเตือน", "favorites": "ชื่นชอบโพสต์ของฉัน", @@ -526,14 +563,17 @@ } }, "report": { + "title_report": "รายงาน", "title": "รายงาน %s", "step1": "ขั้นตอนที่ 1 จาก 2", "step2": "ขั้นตอนที่ 2 จาก 2", "content1": "มีโพสต์อื่นใดที่คุณต้องการเพิ่มไปยังรายงานหรือไม่?", "content2": "มีสิ่งใดที่ผู้ควบคุมควรทราบเกี่ยวกับรายงานนี้หรือไม่?", + "report_sent_title": "ขอบคุณสำหรับการรายงาน เราจะตรวจสอบสิ่งนี้", "send": "ส่งรายงาน", "skip_to_send": "ส่งโดยไม่มีความคิดเห็น", - "text_placeholder": "พิมพ์หรือวางความคิดเห็นเพิ่มเติม" + "text_placeholder": "พิมพ์หรือวางความคิดเห็นเพิ่มเติม", + "reported": "รายงานแล้ว" }, "preview": { "keyboard": { diff --git a/Localization/StringsConvertor/input/zh_CN/app.json b/Localization/StringsConvertor/input/zh_CN/app.json index 905afdd8..74ea0529 100644 --- a/Localization/StringsConvertor/input/zh_CN/app.json +++ b/Localization/StringsConvertor/input/zh_CN/app.json @@ -46,7 +46,7 @@ }, "delete_post": { "title": "确定要删除这条消息吗?", - "delete": "删除" + "message": "确定要删除这个帖子吗?" }, "clean_cache": { "title": "清除缓存", @@ -82,6 +82,7 @@ "share_user": "分享 %s", "share_post": "分享帖子", "open_in_safari": "在 Safari 中打开", + "open_in_browser": "在浏览器中打开", "find_people": "查看推荐关注的用户", "manually_search": "手动搜索用户", "skip": "跳过", @@ -139,7 +140,8 @@ "unreblog": "取消转发", "favorite": "喜欢", "unfavorite": "取消喜欢", - "menu": "菜单" + "menu": "菜单", + "hide": "隐藏" }, "tag": { "url": "URL", @@ -148,6 +150,12 @@ "hashtag": "标签", "email": "电子邮箱", "emoji": "表情" + }, + "visibility": { + "unlisted": "任何人都可以看到这个帖子,但不会在公开的时间线中显示。", + "private": "只有作者的关注者才能看到此帖子。", + "private_from_me": "只有我的关注者才能看到此帖子。", + "direct": "只有提到的用户才能看到此帖子。" } }, "friendship": { @@ -192,10 +200,14 @@ }, "scene": { "welcome": { - "slogan": "社交网络\n回到你的手中。" + "slogan": "社交网络\n回到你的手中。", + "get_started": "开始使用", + "log_in": "登录" }, "server_picker": { "title": "挑选一个服务器,\n任意服务器。", + "subtitle": "根据你的兴趣、区域或一般目的选择一个社区。", + "subtitle_extend": "根据你的兴趣、区域或一般目的选择一个社区。每个社区都由完全独立的组织或个人管理。", "button": { "category": { "all": "全部", @@ -248,6 +260,12 @@ }, "password": { "placeholder": "密码", + "require": "您的密码至少需要:", + "character_limit": "8 个字符", + "accessibility": { + "checked": "已选中", + "unchecked": "未选中" + }, "hint": "密码长度至少为 8 个字符" }, "invite": { @@ -298,7 +316,7 @@ "subtitle": "我们刚刚向 %s 发送了一封电子邮件,\n点击链接确认你的帐户。", "button": { "open_email_app": "打开电子邮件应用", - "dont_receive_email": "我还没有收到电子邮件" + "resend": "重新发送" }, "dont_receive_email": { "title": "请检查你的邮箱。", @@ -401,14 +419,24 @@ "segmented_control": { "posts": "帖子", "replies": "回复", - "media": "媒体" + "posts_and_replies": "帖子与回复", + "media": "媒体", + "about": "关于" }, "relationship_action_alert": { + "confirm_mute_user": { + "title": "静音账户", + "message": "确认静音 %s" + }, "confirm_unmute_user": { "title": "取消静音账户", "message": "确认取消静音 %s" }, - "confirm_unblock_usre": { + "confirm_block_user": { + "title": "屏蔽帐户", + "message": "确认屏蔽 %s" + }, + "confirm_unblock_user": { "title": "解除屏蔽帐户", "message": "确认取消屏蔽 %s" } @@ -461,12 +489,14 @@ "Everything": "全部", "Mentions": "提及" }, - "user_followed_you": "%s 关注了你", - "user_favorited your post": "%s 喜欢了你的帖子", - "user_reblogged_your_post": "%s 转发了你的帖子", - "user_mentioned_you": "%s 提及了你", - "user_requested_to_follow_you": "%s 向你发送了关注请求", - "user_your_poll_has_ended": "%s 你的投票已经结束", + "notification_description": { + "followed_you": "关注了你", + "favorited_your_post": "喜欢了你的帖子", + "reblogged_your_post": "转发了你的帖子", + "mentioned_you": "提及了你", + "request_to_follow_you": "关注请求", + "poll_has_ended": "投票已结束" + }, "keyobard": { "show_everything": "显示全部", "show_mentions": "显示提及" @@ -485,6 +515,13 @@ "light": "浅色", "dark": "深色" }, + "look_and_feel": { + "title": "外观和风格", + "use_system": "跟随系统", + "really_dark": "暗色", + "sorta_dark": "深色", + "light": "浅色" + }, "notifications": { "title": "通知", "favorites": "喜欢我的帖子", @@ -526,14 +563,17 @@ } }, "report": { + "title_report": "举报", "title": "举报 %s", "step1": "步骤 1 / 2", "step2": "步骤 2 / 2", "content1": "是否有帖子需要举报?", "content2": "是否有关于此举报的详细描述信息?", + "report_sent_title": "感谢提交举报,我们将会进行处理。", "send": "发送举报", "skip_to_send": "直接发送", - "text_placeholder": "输入或粘贴额外的注释" + "text_placeholder": "输入或粘贴额外的注释", + "reported": "已报告" }, "preview": { "keyboard": { diff --git a/Localization/StringsConvertor/input/zh_TW/app.json b/Localization/StringsConvertor/input/zh_TW/app.json index 5c01ae7e..be2442e4 100644 --- a/Localization/StringsConvertor/input/zh_TW/app.json +++ b/Localization/StringsConvertor/input/zh_TW/app.json @@ -2,21 +2,21 @@ "common": { "alerts": { "common": { - "please_try_again": "Please try again.", - "please_try_again_later": "Please try again later." + "please_try_again": "請再試一次。", + "please_try_again_later": "請稍候再試。" }, "sign_up_failure": { - "title": "Sign Up Failure" + "title": "註冊失敗" }, "server_error": { - "title": "Server Error" + "title": "伺服器錯誤" }, "vote_failure": { "title": "Vote Failure", "poll_ended": "The poll has ended" }, "discard_post_content": { - "title": "Discard Draft", + "title": "捨棄草稿", "message": "Confirm to discard composed post content." }, "publish_post_failure": { @@ -32,9 +32,9 @@ "message": "Cannot edit profile. Please try again." }, "sign_out": { - "title": "Sign Out", + "title": "登出", "message": "Are you sure you want to sign out?", - "confirm": "Sign Out" + "confirm": "登出" }, "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.", @@ -45,8 +45,8 @@ "message": "Please enable the photo library access permission to save the photo." }, "delete_post": { - "title": "Are you sure you want to delete this post?", - "delete": "Delete" + "title": "Delete Post", + "message": "Are you sure you want to delete this post?" }, "clean_cache": { "title": "Clean Cache", @@ -61,47 +61,48 @@ "open": "Open", "add": "Add", "remove": "Remove", - "edit": "Edit", + "edit": "編輯", "save": "Save", "ok": "OK", - "done": "Done", + "done": "完成", "confirm": "Confirm", - "continue": "Continue", + "continue": "繼續", "compose": "Compose", - "cancel": "Cancel", + "cancel": "取消", "discard": "Discard", "try_again": "Try Again", "take_photo": "Take Photo", - "save_photo": "Save Photo", + "save_photo": "儲存照片", "copy_photo": "Copy Photo", - "sign_in": "Sign In", - "sign_up": "Sign Up", + "sign_in": "登入", + "sign_up": "註冊", "see_more": "See More", "preview": "Preview", - "share": "Share", + "share": "分享", "share_user": "Share %s", "share_post": "Share Post", "open_in_safari": "Open in Safari", + "open_in_browser": "Open in Browser", "find_people": "Find people to follow", "manually_search": "Manually search instead", - "skip": "Skip", - "reply": "Reply", + "skip": "跳過", + "reply": "回覆", "report_user": "Report %s", - "block_domain": "Block %s", - "unblock_domain": "Unblock %s", - "settings": "Settings", - "delete": "Delete" + "block_domain": "封鎖 %s", + "unblock_domain": "解除封鎖 %s", + "settings": "設定", + "delete": "刪除" }, "tabs": { - "home": "Home", - "search": "Search", - "notification": "Notification", - "profile": "Profile" + "home": "首頁", + "search": "搜尋", + "notification": "通知", + "profile": "個人檔案" }, "keyboard": { "common": { - "switch_to_tab": "Switch to %s", - "compose_new_post": "Compose New Post", + "switch_to_tab": "切換至 %s", + "compose_new_post": "發佈貼文", "show_favorites": "Show Favorites", "open_settings": "Open Settings" }, @@ -130,37 +131,44 @@ "content_warning": "Content Warning", "media_content_warning": "Tap anywhere to reveal", "poll": { - "vote": "Vote", + "vote": "投票", "closed": "Closed" }, "actions": { - "reply": "Reply", + "reply": "回覆", "reblog": "Reblog", "unreblog": "Undo reblog", "favorite": "Favorite", "unfavorite": "Unfavorite", - "menu": "Menu" + "menu": "Menu", + "hide": "Hide" }, "tag": { "url": "URL", "mention": "Mention", "link": "Link", "hashtag": "Hashtag", - "email": "Email", + "email": "電子郵件", "emoji": "Emoji" + }, + "visibility": { + "unlisted": "Everyone can see this post but not display in the public timeline.", + "private": "Only their followers can see this post.", + "private_from_me": "Only my followers can see this post.", + "direct": "Only mentioned user can see this post." } }, "friendship": { - "follow": "Follow", + "follow": "追蹤", "following": "Following", "request": "Request", "pending": "Pending", "block": "Block", - "block_user": "Block %s", - "block_domain": "Block %s", - "unblock": "Unblock", - "unblock_user": "Unblock %s", - "blocked": "Blocked", + "block_user": "封鎖 %s", + "block_domain": "封鎖 %s", + "unblock": "解除封鎖", + "unblock_user": "解除封鎖 %s", + "blocked": "已封鎖", "mute": "Mute", "mute_user": "Mute %s", "unmute": "Unmute", @@ -192,10 +200,14 @@ }, "scene": { "welcome": { - "slogan": "Social networking\nback in your hands." + "slogan": "Social networking\nback in your hands.", + "get_started": "Get Started", + "log_in": "登入" }, "server_picker": { - "title": "Pick a server,\nany server.", + "title": "Mastodon is made of users in different communities.", + "subtitle": "Pick a community based on your interests, region, or a general purpose one.", + "subtitle_extend": "Pick a community based on your interests, region, or a general purpose one. Each community is operated by an entirely independent organization or individual.", "button": { "category": { "all": "All", @@ -222,7 +234,7 @@ "category": "CATEGORY" }, "input": { - "placeholder": "Find a server or join your own..." + "placeholder": "Search communities" }, "empty_state": { "finding_servers": "Finding available servers...", @@ -231,10 +243,10 @@ } }, "register": { - "title": "Tell us about you.", + "title": "Let’s get you set up on %s", "input": { "avatar": { - "delete": "Delete" + "delete": "刪除" }, "username": { "placeholder": "username", @@ -247,7 +259,13 @@ "placeholder": "email" }, "password": { - "placeholder": "password", + "placeholder": "密碼", + "require": "Your password needs at least:", + "character_limit": "8 個字元", + "accessibility": { + "checked": "checked", + "unchecked": "unchecked" + }, "hint": "Your password needs at least eight characters" }, "invite": { @@ -257,8 +275,8 @@ "error": { "item": { "username": "Username", - "email": "Email", - "password": "Password", + "email": "電子郵件", + "password": "密碼", "agreement": "Agreement", "locale": "Locale", "reason": "Reason" @@ -285,7 +303,7 @@ }, "server_rules": { "title": "Some ground rules.", - "subtitle": "These rules are set by the admins of %s.", + "subtitle": "These are set and enforced by the %s moderators.", "prompt": "By continuing, you’re subject to the terms of service and privacy policy for %s.", "terms_of_service": "terms of service", "privacy_policy": "privacy policy", @@ -295,10 +313,10 @@ }, "confirm_email": { "title": "One last thing.", - "subtitle": "We just sent an email to %s,\ntap the link to confirm your account.", + "subtitle": "Tap the link we emailed to you to verify your account.", "button": { "open_email_app": "Open Email App", - "dont_receive_email": "I never got an email" + "resend": "Resend" }, "dont_receive_email": { "title": "Check your email", @@ -340,14 +358,14 @@ "replying_to_user": "replying to %s", "attachment": { "photo": "photo", - "video": "video", + "video": "影片", "attachment_broken": "This %s is broken and can’t be\nuploaded to Mastodon.", "description_photo": "Describe the photo for the visually-impaired...", "description_video": "Describe the video for the visually-impaired..." }, "poll": { "duration_time": "Duration: %s", - "thirty_minutes": "30 minutes", + "thirty_minutes": "30 分鐘", "one_hour": "1 Hour", "six_hours": "6 Hours", "one_day": "1 Day", @@ -399,16 +417,26 @@ } }, "segmented_control": { - "posts": "Posts", + "posts": "貼文", "replies": "Replies", - "media": "Media" + "posts_and_replies": "Posts and Replies", + "media": "Media", + "about": "About" }, "relationship_action_alert": { + "confirm_mute_user": { + "title": "Mute Account", + "message": "Confirm to mute %s" + }, "confirm_unmute_user": { "title": "Unmute Account", "message": "Confirm to unmute %s" }, - "confirm_unblock_usre": { + "confirm_block_user": { + "title": "Block Account", + "message": "Confirm to block %s" + }, + "confirm_unblock_user": { "title": "Unblock Account", "message": "Confirm to unblock %s" } @@ -421,10 +449,10 @@ "footer": "Follows from other servers are not displayed." }, "search": { - "title": "Search", + "title": "搜尋", "search_bar": { "placeholder": "Search hashtags and users", - "cancel": "Cancel" + "cancel": "取消" }, "recommend": { "button_text": "See All", @@ -436,7 +464,7 @@ "accounts": { "title": "Accounts you might like", "description": "You may like to follow these accounts", - "follow": "Follow" + "follow": "追蹤" } }, "searching": { @@ -444,7 +472,7 @@ "all": "All", "people": "People", "hashtags": "Hashtags", - "posts": "Posts" + "posts": "貼文" }, "empty_state": { "no_results": "No results" @@ -461,12 +489,14 @@ "Everything": "Everything", "Mentions": "Mentions" }, - "user_followed_you": "%s followed you", - "user_favorited your post": "%s favorited your post", - "user_reblogged_your_post": "%s reblogged your post", - "user_mentioned_you": "%s mentioned you", - "user_requested_to_follow_you": "%s requested to follow you", - "user_your_poll_has_ended": "%s Your poll has ended", + "notification_description": { + "followed_you": "followed you", + "favorited_your_post": "favorited your post", + "reblogged_your_post": "reblogged your post", + "mentioned_you": "mentioned you", + "request_to_follow_you": "request to follow you", + "poll_has_ended": "poll has ended" + }, "keyobard": { "show_everything": "Show Everything", "show_mentions": "Show Mentions" @@ -477,14 +507,21 @@ "title": "Post from %s" }, "settings": { - "title": "Settings", + "title": "設定", "section": { "appearance": { "title": "Appearance", - "automatic": "Automatic", + "automatic": "自動", "light": "Always Light", "dark": "Always Dark" }, + "look_and_feel": { + "title": "Look and Feel", + "use_system": "Use System", + "really_dark": "Really Dark", + "sorta_dark": "Sorta Dark", + "light": "Light" + }, "notifications": { "title": "Notifications", "favorites": "Favorites my post", @@ -515,7 +552,7 @@ "spicy_zone": { "title": "The Spicy Zone", "clear": "Clear Media Cache", - "signout": "Sign Out" + "signout": "登出" } }, "footer": { @@ -526,14 +563,17 @@ } }, "report": { + "title_report": "Report", "title": "Report %s", "step1": "Step 1 of 2", "step2": "Step 2 of 2", "content1": "Are there any other posts you’d like to add to the report?", "content2": "Is there anything the moderators should know about this report?", + "report_sent_title": "Thanks for reporting, we’ll look into this.", "send": "Send Report", "skip_to_send": "Send without comment", - "text_placeholder": "Type or paste additional comments" + "text_placeholder": "Type or paste additional comments", + "reported": "REPORTED" }, "preview": { "keyboard": { diff --git a/Localization/app.json b/Localization/app.json index ad99e178..f0dc0ebf 100644 --- a/Localization/app.json +++ b/Localization/app.json @@ -130,6 +130,7 @@ "show_user_profile": "Show user profile", "content_warning": "Content Warning", "media_content_warning": "Tap anywhere to reveal", + "tap_to_reveal": "Tap to reveal", "poll": { "vote": "Vote", "closed": "Closed" @@ -141,7 +142,11 @@ "favorite": "Favorite", "unfavorite": "Unfavorite", "menu": "Menu", - "hide": "Hide" + "hide": "Hide", + "show_image": "Show image", + "show_gif": "Show GIF", + "show_video_player": "Show video player", + "tap_then_hold_to_show_menu": "Tap then hold to show menu" }, "tag": { "url": "URL", @@ -440,6 +445,12 @@ "title": "Unblock Account", "message": "Confirm to unblock %s" } + }, + "accessibility": { + "show_avatar_image": "Show avatar image", + "edit_avatar_image": "Edit avatar image", + "show_banner_image": "Show banner image", + "double_tap_to_open_the_list": "Double tap to open the list" } }, "follower": { @@ -541,7 +552,8 @@ "true_black_dark_mode": "True black dark mode", "disable_avatar_animation": "Disable animated avatars", "disable_emoji_animation": "Disable animated emojis", - "using_default_browser": "Use default browser to open links" + "using_default_browser": "Use default browser to open links", + "open_links_in_mastodon": "Open links in Mastodon" }, "boring_zone": { "title": "The Boring Zone", diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj index fa1a0259..69596a20 100644 --- a/Mastodon.xcodeproj/project.pbxproj +++ b/Mastodon.xcodeproj/project.pbxproj @@ -37,7 +37,6 @@ 2D35237A26256D920031AF25 /* NotificationSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D35237926256D920031AF25 /* NotificationSection.swift */; }; 2D364F7225E66D7500204FDC /* MastodonResendEmailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D364F7125E66D7500204FDC /* MastodonResendEmailViewController.swift */; }; 2D364F7825E66D8300204FDC /* MastodonResendEmailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D364F7725E66D8300204FDC /* MastodonResendEmailViewModel.swift */; }; - 2D38F1C625CD37F400561493 /* ContentOffsetAdjustableTimelineViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D38F1C525CD37F400561493 /* ContentOffsetAdjustableTimelineViewControllerDelegate.swift */; }; 2D38F1D525CD465300561493 /* HomeTimelineViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D38F1D425CD465300561493 /* HomeTimelineViewController.swift */; }; 2D38F1E525CD46C100561493 /* HomeTimelineViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D38F1E425CD46C100561493 /* HomeTimelineViewModel.swift */; }; 2D38F1EB25CD477000561493 /* HomeTimelineViewModel+LoadLatestState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D38F1EA25CD477000561493 /* HomeTimelineViewModel+LoadLatestState.swift */; }; @@ -245,6 +244,7 @@ DB45FB0F25CA87D0005A8AC7 /* AuthenticationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB45FB0E25CA87D0005A8AC7 /* AuthenticationService.swift */; }; DB45FB1D25CA9D23005A8AC7 /* APIService+HomeTimeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB45FB1C25CA9D23005A8AC7 /* APIService+HomeTimeline.swift */; }; DB47229725F9EFAD00DA7F53 /* NSManagedObjectContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB47229625F9EFAD00DA7F53 /* NSManagedObjectContext.swift */; }; + DB47AB6227CF752B00CD73C7 /* MastodonUISnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB47AB6127CF752B00CD73C7 /* MastodonUISnapshotTests.swift */; }; DB482A3F261331E8008AE74C /* UserTimelineViewModel+State.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB482A3E261331E8008AE74C /* UserTimelineViewModel+State.swift */; }; DB482A4B261340A7008AE74C /* APIService+UserTimeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB482A4A261340A7008AE74C /* APIService+UserTimeline.swift */; }; DB4924E226312AB200E9DB22 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB4924E126312AB200E9DB22 /* NotificationService.swift */; }; @@ -255,6 +255,7 @@ DB49A61F25FF32AA00B98345 /* EmojiService+CustomEmojiViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB49A61E25FF32AA00B98345 /* EmojiService+CustomEmojiViewModel.swift */; }; DB49A62525FF334C00B98345 /* EmojiService+CustomEmojiViewModel+LoadState.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB49A62425FF334C00B98345 /* EmojiService+CustomEmojiViewModel+LoadState.swift */; }; DB49A62B25FF36C700B98345 /* APIService+CustomEmoji.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB49A62A25FF36C700B98345 /* APIService+CustomEmoji.swift */; }; + DB4AA6B327BA34B6009EC082 /* CellFrameCacheContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB4AA6B227BA34B6009EC082 /* CellFrameCacheContainer.swift */; }; DB4F0963269ED06300D62E92 /* SearchResultViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB4F0962269ED06300D62E92 /* SearchResultViewController.swift */; }; DB4F0966269ED52200D62E92 /* SearchResultViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB4F0965269ED52200D62E92 /* SearchResultViewModel.swift */; }; DB4F0968269ED8AD00D62E92 /* SearchHistoryTableHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB4F0967269ED8AD00D62E92 /* SearchHistoryTableHeaderView.swift */; }; @@ -482,7 +483,6 @@ DBB45B5627B39FC9002DC5A7 /* MediaPreviewVideoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB45B5527B39FC9002DC5A7 /* MediaPreviewVideoViewController.swift */; }; DBB45B5927B39FE4002DC5A7 /* MediaPreviewVideoViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB45B5827B39FE4002DC5A7 /* MediaPreviewVideoViewModel.swift */; }; DBB45B5B27B3A109002DC5A7 /* MediaPreviewTransitionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB45B5A27B3A109002DC5A7 /* MediaPreviewTransitionViewController.swift */; }; - DBB45B5E27B4EB22002DC5A7 /* AdaptiveMarginStatusTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB45B5D27B4EB22002DC5A7 /* AdaptiveMarginStatusTableViewCell.swift */; }; DBB45B6027B50A4F002DC5A7 /* RecommendAccountItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB45B5F27B50A4F002DC5A7 /* RecommendAccountItem.swift */; }; DBB45B6227B51112002DC5A7 /* SuggestionAccountViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB45B6127B51112002DC5A7 /* SuggestionAccountViewModel+Diffable.swift */; }; DBB525082611EAC0002F1F29 /* Tabman in Frameworks */ = {isa = PBXBuildFile; productRef = DBB525072611EAC0002F1F29 /* Tabman */; }; @@ -546,6 +546,9 @@ DBCCC71E25F73297007E1AB6 /* APIService+Reblog.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCCC71D25F73297007E1AB6 /* APIService+Reblog.swift */; }; DBD376AC2692ECDB007FEC24 /* ThemePreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBD376AB2692ECDB007FEC24 /* ThemePreference.swift */; }; DBD376B2269302A4007FEC24 /* UITableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBD376B1269302A4007FEC24 /* UITableViewCell.swift */; }; + DBD5B1F627BCD3D200BD6B38 /* SuggestionAccountTableViewCell+ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBD5B1F527BCD3D200BD6B38 /* SuggestionAccountTableViewCell+ViewModel.swift */; }; + DBD5B1F827BCFD9D00BD6B38 /* DataSourceProvider+TableViewControllerNavigateable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBD5B1F727BCFD9D00BD6B38 /* DataSourceProvider+TableViewControllerNavigateable.swift */; }; + DBD5B1FA27BD013700BD6B38 /* DataSourceProvider+StatusTableViewControllerNavigateable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBD5B1F927BD013700BD6B38 /* DataSourceProvider+StatusTableViewControllerNavigateable.swift */; }; DBD9149025DF6D8D00903DFD /* APIService+Onboarding.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBD9148F25DF6D8D00903DFD /* APIService+Onboarding.swift */; }; DBE0821525CD382600FD6BBD /* MastodonRegisterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBE0821425CD382600FD6BBD /* MastodonRegisterViewController.swift */; }; DBE0822425CD3F1E00FD6BBD /* MastodonRegisterViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBE0822325CD3F1E00FD6BBD /* MastodonRegisterViewModel.swift */; }; @@ -558,7 +561,6 @@ DBE3CDFB261C6CA500430CC6 /* FavoriteViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBE3CDFA261C6CA500430CC6 /* FavoriteViewModel.swift */; }; DBE3CE01261D623D00430CC6 /* FavoriteViewModel+State.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBE3CE00261D623D00430CC6 /* FavoriteViewModel+State.swift */; }; DBE3CE07261D6A0E00430CC6 /* FavoriteViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBE3CE06261D6A0E00430CC6 /* FavoriteViewModel+Diffable.swift */; }; - DBE3CE13261D7D4200430CC6 /* StatusTableViewControllerAspect.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBE3CE12261D7D4200430CC6 /* StatusTableViewControllerAspect.swift */; }; DBE54AC62636C89F004E7C0B /* NotificationPreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBE54AC52636C89F004E7C0B /* NotificationPreference.swift */; }; DBE54ACC2636C8FD004E7C0B /* NotificationPreference.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBE54AC52636C89F004E7C0B /* NotificationPreference.swift */; }; DBF156DF2701B17600EC00B7 /* SidebarAddAccountCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBF156DE2701B17600EC00B7 /* SidebarAddAccountCollectionViewCell.swift */; }; @@ -698,6 +700,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 0655B257371274BEB7EB1C19 /* Pods-Mastodon.release snapshot.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon.release snapshot.xcconfig"; path = "Target Support Files/Pods-Mastodon/Pods-Mastodon.release snapshot.xcconfig"; sourceTree = "<group>"; }; + 0827D1674B2523503E8605F6 /* Pods-Mastodon-MastodonUITests.release snapshot.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-MastodonUITests.release snapshot.xcconfig"; path = "Target Support Files/Pods-Mastodon-MastodonUITests/Pods-Mastodon-MastodonUITests.release snapshot.xcconfig"; sourceTree = "<group>"; }; 0F1E2D0A2615C39400C38565 /* DoubleTitleLabelNavigationBarTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoubleTitleLabelNavigationBarTitleView.swift; sourceTree = "<group>"; }; 0F2021FA2613262F000C64BF /* HashtagTimelineViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HashtagTimelineViewController.swift; sourceTree = "<group>"; }; 0F202200261326E6000C64BF /* HashtagTimelineViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HashtagTimelineViewModel.swift; sourceTree = "<group>"; }; @@ -717,6 +721,7 @@ 159AC43EFE0A1F95FCB358A4 /* Pods-MastodonIntent.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonIntent.release.xcconfig"; path = "Target Support Files/Pods-MastodonIntent/Pods-MastodonIntent.release.xcconfig"; sourceTree = "<group>"; }; 164F0EBB267D4FE400249499 /* BoopSound.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = BoopSound.caf; sourceTree = "<group>"; }; 1D6D967E77A5357E2C6110D9 /* Pods-Mastodon.asdk - debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon.asdk - debug.xcconfig"; path = "Target Support Files/Pods-Mastodon/Pods-Mastodon.asdk - debug.xcconfig"; sourceTree = "<group>"; }; + 2C12EB4B3699D5D597027962 /* Pods-MastodonIntent.release snapshot.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonIntent.release snapshot.xcconfig"; path = "Target Support Files/Pods-MastodonIntent/Pods-MastodonIntent.release snapshot.xcconfig"; sourceTree = "<group>"; }; 2D198642261BF09500F0B013 /* SearchResultItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultItem.swift; sourceTree = "<group>"; }; 2D198648261C0B8500F0B013 /* SearchResultSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultSection.swift; sourceTree = "<group>"; }; 2D206B8525F5FB0900143C56 /* Double.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Double.swift; sourceTree = "<group>"; }; @@ -729,7 +734,6 @@ 2D35237926256D920031AF25 /* NotificationSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSection.swift; sourceTree = "<group>"; }; 2D364F7125E66D7500204FDC /* MastodonResendEmailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonResendEmailViewController.swift; sourceTree = "<group>"; }; 2D364F7725E66D8300204FDC /* MastodonResendEmailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonResendEmailViewModel.swift; sourceTree = "<group>"; }; - 2D38F1C525CD37F400561493 /* ContentOffsetAdjustableTimelineViewControllerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentOffsetAdjustableTimelineViewControllerDelegate.swift; sourceTree = "<group>"; }; 2D38F1D425CD465300561493 /* HomeTimelineViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeTimelineViewController.swift; sourceTree = "<group>"; }; 2D38F1E425CD46C100561493 /* HomeTimelineViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeTimelineViewModel.swift; sourceTree = "<group>"; }; 2D38F1EA25CD477000561493 /* HomeTimelineViewModel+LoadLatestState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "HomeTimelineViewModel+LoadLatestState.swift"; sourceTree = "<group>"; }; @@ -782,6 +786,7 @@ 374AA339A20E0FAC75BCDA6D /* Pods_NotificationService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NotificationService.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3B7FD8F28DDA8FBCE5562B78 /* Pods-NotificationService.asdk - debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.asdk - debug.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.asdk - debug.xcconfig"; sourceTree = "<group>"; }; 3C030226D3C73DCC23D67452 /* Pods_Mastodon_MastodonUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Mastodon_MastodonUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 3E08A432F40BA7B9CAA9DB68 /* Pods-AppShared.release snapshot.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AppShared.release snapshot.xcconfig"; path = "Target Support Files/Pods-AppShared/Pods-AppShared.release snapshot.xcconfig"; sourceTree = "<group>"; }; 452147B2903DF38070FE56A2 /* Pods_MastodonTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MastodonTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 459EA4F43058CAB47719E963 /* Pods-Mastodon-MastodonUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-MastodonUITests.debug.xcconfig"; path = "Target Support Files/Pods-Mastodon-MastodonUITests/Pods-Mastodon-MastodonUITests.debug.xcconfig"; sourceTree = "<group>"; }; 46DAB0EBDDFB678347CD96FF /* Pods-MastodonTests.asdk - release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonTests.asdk - release.xcconfig"; path = "Target Support Files/Pods-MastodonTests/Pods-MastodonTests.asdk - release.xcconfig"; sourceTree = "<group>"; }; @@ -813,6 +818,8 @@ 819CEC9DCAD8E8E7BD85A7BB /* Pods-Mastodon.asdk.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon.asdk.xcconfig"; path = "Target Support Files/Pods-Mastodon/Pods-Mastodon.asdk.xcconfig"; sourceTree = "<group>"; }; 861BE60ED27430771CFD578D /* Pods-MastodonIntent.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonIntent.debug.xcconfig"; path = "Target Support Files/Pods-MastodonIntent/Pods-MastodonIntent.debug.xcconfig"; sourceTree = "<group>"; }; 8850E70A1D5FF51432E43653 /* Pods-Mastodon-MastodonUITests.asdk - release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-MastodonUITests.asdk - release.xcconfig"; path = "Target Support Files/Pods-Mastodon-MastodonUITests/Pods-Mastodon-MastodonUITests.asdk - release.xcconfig"; sourceTree = "<group>"; }; + 8ADD558BE5B8255E5764A54F /* Pods-NotificationService.release snapshot.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.release snapshot.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.release snapshot.xcconfig"; sourceTree = "<group>"; }; + 8E79CCBE51FBC3F7FE8CF49F /* Pods-MastodonTests.release snapshot.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonTests.release snapshot.xcconfig"; path = "Target Support Files/Pods-MastodonTests/Pods-MastodonTests.release snapshot.xcconfig"; sourceTree = "<group>"; }; 8ED8C4B1F1BA2DCFF2926BB1 /* Pods-Mastodon-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Mastodon-NotificationService.debug.xcconfig"; path = "Target Support Files/Pods-Mastodon-NotificationService/Pods-Mastodon-NotificationService.debug.xcconfig"; sourceTree = "<group>"; }; 9553C689FFA9EBC880CAB78D /* Pods-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.debug.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.debug.xcconfig"; sourceTree = "<group>"; }; 95AD0663479892A2109EEFD0 /* Pods-ShareActionExtension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShareActionExtension.release.xcconfig"; path = "Target Support Files/Pods-ShareActionExtension/Pods-ShareActionExtension.release.xcconfig"; sourceTree = "<group>"; }; @@ -969,6 +976,8 @@ DB45FB0E25CA87D0005A8AC7 /* AuthenticationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationService.swift; sourceTree = "<group>"; }; DB45FB1C25CA9D23005A8AC7 /* APIService+HomeTimeline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+HomeTimeline.swift"; sourceTree = "<group>"; }; DB47229625F9EFAD00DA7F53 /* NSManagedObjectContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSManagedObjectContext.swift; sourceTree = "<group>"; }; + DB47AB6127CF752B00CD73C7 /* MastodonUISnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonUISnapshotTests.swift; sourceTree = "<group>"; }; + DB47AB6327CF858400CD73C7 /* AppStoreSnapshotTestPlan.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = AppStoreSnapshotTestPlan.xctestplan; sourceTree = "<group>"; }; DB482A3E261331E8008AE74C /* UserTimelineViewModel+State.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserTimelineViewModel+State.swift"; sourceTree = "<group>"; }; DB482A4A261340A7008AE74C /* APIService+UserTimeline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+UserTimeline.swift"; sourceTree = "<group>"; }; DB4924E126312AB200E9DB22 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = "<group>"; }; @@ -978,6 +987,7 @@ DB49A61E25FF32AA00B98345 /* EmojiService+CustomEmojiViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EmojiService+CustomEmojiViewModel.swift"; sourceTree = "<group>"; }; DB49A62425FF334C00B98345 /* EmojiService+CustomEmojiViewModel+LoadState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "EmojiService+CustomEmojiViewModel+LoadState.swift"; sourceTree = "<group>"; }; DB49A62A25FF36C700B98345 /* APIService+CustomEmoji.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+CustomEmoji.swift"; sourceTree = "<group>"; }; + DB4AA6B227BA34B6009EC082 /* CellFrameCacheContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellFrameCacheContainer.swift; sourceTree = "<group>"; }; DB4B777F26CA4EFA00B087B3 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Intents.strings; sourceTree = "<group>"; }; DB4B778226CA4EFA00B087B3 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/InfoPlist.strings; sourceTree = "<group>"; }; DB4B778326CA4EFA00B087B3 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ru; path = ru.lproj/Intents.stringsdict; sourceTree = "<group>"; }; @@ -1228,7 +1238,6 @@ DBB45B5527B39FC9002DC5A7 /* MediaPreviewVideoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreviewVideoViewController.swift; sourceTree = "<group>"; }; DBB45B5827B39FE4002DC5A7 /* MediaPreviewVideoViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreviewVideoViewModel.swift; sourceTree = "<group>"; }; DBB45B5A27B3A109002DC5A7 /* MediaPreviewTransitionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaPreviewTransitionViewController.swift; sourceTree = "<group>"; }; - DBB45B5D27B4EB22002DC5A7 /* AdaptiveMarginStatusTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdaptiveMarginStatusTableViewCell.swift; sourceTree = "<group>"; }; DBB45B5F27B50A4F002DC5A7 /* RecommendAccountItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecommendAccountItem.swift; sourceTree = "<group>"; }; DBB45B6127B51112002DC5A7 /* SuggestionAccountViewModel+Diffable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SuggestionAccountViewModel+Diffable.swift"; sourceTree = "<group>"; }; DBB5250D2611EBAF002F1F29 /* ProfileSegmentedViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileSegmentedViewController.swift; sourceTree = "<group>"; }; @@ -1280,10 +1289,10 @@ DBCCC71D25F73297007E1AB6 /* APIService+Reblog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Reblog.swift"; sourceTree = "<group>"; }; DBD376AB2692ECDB007FEC24 /* ThemePreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemePreference.swift; sourceTree = "<group>"; }; DBD376B1269302A4007FEC24 /* UITableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITableViewCell.swift; sourceTree = "<group>"; }; + DBD5B1F527BCD3D200BD6B38 /* SuggestionAccountTableViewCell+ViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SuggestionAccountTableViewCell+ViewModel.swift"; sourceTree = "<group>"; }; + DBD5B1F727BCFD9D00BD6B38 /* DataSourceProvider+TableViewControllerNavigateable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DataSourceProvider+TableViewControllerNavigateable.swift"; sourceTree = "<group>"; }; + DBD5B1F927BD013700BD6B38 /* DataSourceProvider+StatusTableViewControllerNavigateable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DataSourceProvider+StatusTableViewControllerNavigateable.swift"; sourceTree = "<group>"; }; DBD9148F25DF6D8D00903DFD /* APIService+Onboarding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Onboarding.swift"; sourceTree = "<group>"; }; - DBDC1CF9272C0FD600055C3D /* ku-TR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ku-TR"; path = "ku-TR.lproj/Intents.strings"; sourceTree = "<group>"; }; - DBDC1CFC272C0FD600055C3D /* ku-TR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "ku-TR"; path = "ku-TR.lproj/InfoPlist.strings"; sourceTree = "<group>"; }; - DBDC1CFD272C0FD600055C3D /* ku-TR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "ku-TR"; path = "ku-TR.lproj/Intents.stringsdict"; sourceTree = "<group>"; }; DBE0821425CD382600FD6BBD /* MastodonRegisterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonRegisterViewController.swift; sourceTree = "<group>"; }; DBE0822325CD3F1E00FD6BBD /* MastodonRegisterViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonRegisterViewModel.swift; sourceTree = "<group>"; }; DBE3CDBA261C427900430CC6 /* TimelineHeaderTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineHeaderTableViewCell.swift; sourceTree = "<group>"; }; @@ -1292,8 +1301,10 @@ DBE3CDFA261C6CA500430CC6 /* FavoriteViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoriteViewModel.swift; sourceTree = "<group>"; }; DBE3CE00261D623D00430CC6 /* FavoriteViewModel+State.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FavoriteViewModel+State.swift"; sourceTree = "<group>"; }; DBE3CE06261D6A0E00430CC6 /* FavoriteViewModel+Diffable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FavoriteViewModel+Diffable.swift"; sourceTree = "<group>"; }; - DBE3CE12261D7D4200430CC6 /* StatusTableViewControllerAspect.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusTableViewControllerAspect.swift; sourceTree = "<group>"; }; DBE54AC52636C89F004E7C0B /* NotificationPreference.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPreference.swift; sourceTree = "<group>"; }; + DBEB19E927E4F37B00B0E80E /* ku */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ku; path = ku.lproj/Intents.strings; sourceTree = "<group>"; }; + DBEB19EA27E4F37B00B0E80E /* ku */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ku; path = ku.lproj/InfoPlist.strings; sourceTree = "<group>"; }; + DBEB19EB27E4F37B00B0E80E /* ku */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ku; path = ku.lproj/Intents.stringsdict; sourceTree = "<group>"; }; DBF156DE2701B17600EC00B7 /* SidebarAddAccountCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarAddAccountCollectionViewCell.swift; sourceTree = "<group>"; }; DBF156E02702DA6800EC00B7 /* Mastodon-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Mastodon-Bridging-Header.h"; sourceTree = "<group>"; }; DBF156E12702DA6900EC00B7 /* UIStatusBarManager+HandleTapAction.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIStatusBarManager+HandleTapAction.m"; sourceTree = "<group>"; }; @@ -1335,6 +1346,7 @@ ECA373ABA86BE3C2D7ED878E /* Pods-AppShared.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AppShared.release.xcconfig"; path = "Target Support Files/Pods-AppShared/Pods-AppShared.release.xcconfig"; sourceTree = "<group>"; }; EE13214BC0246BE5210CCC10 /* Pods-AppShared.asdk.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AppShared.asdk.xcconfig"; path = "Target Support Files/Pods-AppShared/Pods-AppShared.asdk.xcconfig"; sourceTree = "<group>"; }; F31E7502A7E3945B98C6CBAF /* Pods-NotificationService.asdk.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.asdk.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.asdk.xcconfig"; sourceTree = "<group>"; }; + F43DF6E8AB8C87914A64FC48 /* Pods-ShareActionExtension.release snapshot.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ShareActionExtension.release snapshot.xcconfig"; path = "Target Support Files/Pods-ShareActionExtension/Pods-ShareActionExtension.release snapshot.xcconfig"; sourceTree = "<group>"; }; F4A2A2D7000E477CA459ADA9 /* Pods_AppShared.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AppShared.framework; sourceTree = BUILT_PRODUCTS_DIR; }; F4C94BD75C96D0EFF5F6D961 /* Pods_MastodonIntent.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MastodonIntent.framework; sourceTree = BUILT_PRODUCTS_DIR; }; F920AD4EC23B0D00F5CCA58E /* Pods-MastodonIntent.asdk - release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MastodonIntent.asdk - release.xcconfig"; path = "Target Support Files/Pods-MastodonIntent/Pods-MastodonIntent.asdk - release.xcconfig"; sourceTree = "<group>"; }; @@ -1536,6 +1548,13 @@ C3789232A52F43529CA67E95 /* Pods-MastodonIntent.asdk - debug.xcconfig */, F920AD4EC23B0D00F5CCA58E /* Pods-MastodonIntent.asdk - release.xcconfig */, 159AC43EFE0A1F95FCB358A4 /* Pods-MastodonIntent.release.xcconfig */, + 3E08A432F40BA7B9CAA9DB68 /* Pods-AppShared.release snapshot.xcconfig */, + 0655B257371274BEB7EB1C19 /* Pods-Mastodon.release snapshot.xcconfig */, + 0827D1674B2523503E8605F6 /* Pods-Mastodon-MastodonUITests.release snapshot.xcconfig */, + 2C12EB4B3699D5D597027962 /* Pods-MastodonIntent.release snapshot.xcconfig */, + 8E79CCBE51FBC3F7FE8CF49F /* Pods-MastodonTests.release snapshot.xcconfig */, + 8ADD558BE5B8255E5764A54F /* Pods-NotificationService.release snapshot.xcconfig */, + F43DF6E8AB8C87914A64FC48 /* Pods-ShareActionExtension.release snapshot.xcconfig */, ); path = Pods; sourceTree = "<group>"; @@ -1668,14 +1687,13 @@ isa = PBXGroup; children = ( DB697DD7278F4C34004EF2F7 /* Provider */, + DB0FCB7127952986006C02E2 /* NamingState.swift */, 2D5A3D3725CF8D9F002347D6 /* ScrollViewContainer.swift */, - 2D38F1C525CD37F400561493 /* ContentOffsetAdjustableTimelineViewControllerDelegate.swift */, + DB4AA6B227BA34B6009EC082 /* CellFrameCacheContainer.swift */, 2D38F20725CD491300561493 /* DisposeBagCollectable.swift */, - DBE3CE12261D7D4200430CC6 /* StatusTableViewControllerAspect.swift */, DB1D84372657B275000346B3 /* SegmentedControlNavigateable.swift */, DB1D843326579931000346B3 /* TableViewControllerNavigateable.swift */, DB1D842D26552C4D000346B3 /* StatusTableViewControllerNavigateable.swift */, - DB0FCB7127952986006C02E2 /* NamingState.swift */, ); path = Protocol; sourceTree = "<group>"; @@ -1742,7 +1760,6 @@ DBE3CDBA261C427900430CC6 /* TimelineHeaderTableViewCell.swift */, DB6B750327300B4000C70B6E /* TimelineFooterTableViewCell.swift */, DB02CDAA26256A9500D0A2AF /* ThreadReplyLoaderTableViewCell.swift */, - DBB45B5D27B4EB22002DC5A7 /* AdaptiveMarginStatusTableViewCell.swift */, ); path = TableviewCell; sourceTree = "<group>"; @@ -1771,6 +1788,7 @@ isa = PBXGroup; children = ( 2DAC9E45262FC9FD0062E1A6 /* SuggestionAccountTableViewCell.swift */, + DBD5B1F527BCD3D200BD6B38 /* SuggestionAccountTableViewCell+ViewModel.swift */, ); path = TableViewCell; sourceTree = "<group>"; @@ -2078,6 +2096,7 @@ children = ( DBF53F5F25C14E88008AAC7B /* Mastodon.xctestplan */, DBF53F6025C14E9D008AAC7B /* MastodonSDK.xctestplan */, + DB47AB6327CF858400CD73C7 /* AppStoreSnapshotTestPlan.xctestplan */, DB3D0FED25BAA42200EAA174 /* MastodonSDK */, DB427DD425BAA00100D1B89D /* Mastodon */, DB427DEB25BAA00100D1B89D /* MastodonTests */, @@ -2144,6 +2163,7 @@ isa = PBXGroup; children = ( DB427DF725BAA00100D1B89D /* MastodonUITests.swift */, + DB47AB6127CF752B00CD73C7 /* MastodonUISnapshotTests.swift */, DB427DF925BAA00100D1B89D /* Info.plist */, ); path = MastodonUITests; @@ -2494,6 +2514,8 @@ DB697DDA278F4DE3004EF2F7 /* DataSourceProvider+StatusTableViewCellDelegate.swift */, DB023D2927A0FE5C005AC798 /* DataSourceProvider+NotificationTableViewCellDelegate.swift */, DB0FCB7727957678006C02E2 /* DataSourceProvider+UITableViewDelegate.swift */, + DBD5B1F727BCFD9D00BD6B38 /* DataSourceProvider+TableViewControllerNavigateable.swift */, + DBD5B1F927BD013700BD6B38 /* DataSourceProvider+StatusTableViewControllerNavigateable.swift */, ); path = Provider; sourceTree = "<group>"; @@ -2649,11 +2671,11 @@ DB9D6BFD25E4F57B0051B173 /* Notification */, DB938EEB2623F52600E5B6C1 /* Thread */, 5B24BBD6262DB14800A9381B /* Report */, - DB9D6BEE25E4F5370051B173 /* Search */, DB789A1025F9F29B0071ACA0 /* Compose */, DB6180DE263919350018D199 /* MediaPreview */, 2DAC9E36262FC20B0062E1A6 /* SuggestionAccount */, DB9D6C0825E4F5A60051B173 /* Profile */, + DB9D6BEE25E4F5370051B173 /* Search */, 5B90C455262599800002E742 /* Settings */, ); path = Scene; @@ -3416,9 +3438,9 @@ ru, "gd-GB", th, - "ku-TR", "eu-ES", "sv-FI", + ku, ); mainGroup = DB427DC925BAA00100D1B89D; packageReferences = ( @@ -3835,9 +3857,9 @@ DBA465952696E387002B41DB /* AppPreference.swift in Sources */, 2D8434F525FF465D00EECE90 /* HomeTimelineNavigationBarTitleViewModel.swift in Sources */, DB938F0F2624119800E5B6C1 /* ThreadViewModel+LoadThreadState.swift in Sources */, - DBB45B5E27B4EB22002DC5A7 /* AdaptiveMarginStatusTableViewCell.swift in Sources */, DB6180F226391CF40018D199 /* MediaPreviewImageViewModel.swift in Sources */, DBA5E7A3263AD0A3004598BB /* PhotoLibraryService.swift in Sources */, + DBD5B1F627BCD3D200BD6B38 /* SuggestionAccountTableViewCell+ViewModel.swift in Sources */, 5DDDF1932617442700311060 /* Mastodon+Entity+Account.swift in Sources */, DB63F767279A5EB300455B82 /* NotificationTimelineViewModel.swift in Sources */, 2D607AD826242FC500B70763 /* NotificationViewModel.swift in Sources */, @@ -4049,7 +4071,6 @@ DB8AF55025C13703002E6C99 /* MainTabBarController.swift in Sources */, DB023D2C27A10464005AC798 /* NotificationTimelineViewController+DataSourceProvider.swift in Sources */, DB9D6BE925E4F5340051B173 /* SearchViewController.swift in Sources */, - 2D38F1C625CD37F400561493 /* ContentOffsetAdjustableTimelineViewControllerDelegate.swift in Sources */, DBF1D257269DBAC600C1C08A /* SearchDetailViewModel.swift in Sources */, DB03F7F52689B782007B274C /* ComposeTableView.swift in Sources */, DBB45B5927B39FE4002DC5A7 /* MediaPreviewVideoViewModel.swift in Sources */, @@ -4064,6 +4085,7 @@ DB73BF4B27140C0800781945 /* UITableViewDiffableDataSource.swift in Sources */, DBB525642612C988002F1F29 /* MeProfileViewModel.swift in Sources */, DB6B74EF272FB55000C70B6E /* FollowerListViewController.swift in Sources */, + DB4AA6B327BA34B6009EC082 /* CellFrameCacheContainer.swift in Sources */, DB0FCB942797E2B0006C02E2 /* SearchResultViewModel+Diffable.swift in Sources */, DB63F752279944AA00455B82 /* SearchHistorySectionHeaderCollectionReusableView.swift in Sources */, DBBC24C426A544B900398BB9 /* Theme.swift in Sources */, @@ -4127,6 +4149,7 @@ DB1FD45025F26FA1004CFCFC /* MastodonPickServerViewModel+Diffable.swift in Sources */, DBD376AC2692ECDB007FEC24 /* ThemePreference.swift in Sources */, DB4F097D26A03A5B00D62E92 /* SearchHistoryItem.swift in Sources */, + DBD5B1FA27BD013700BD6B38 /* DataSourceProvider+StatusTableViewControllerNavigateable.swift in Sources */, DB68046C2636DC9E00430867 /* MastodonNotification.swift in Sources */, DBAE3F9E2616E308004B8251 /* APIService+Mute.swift in Sources */, DB427DD625BAA00100D1B89D /* AppDelegate.swift in Sources */, @@ -4240,6 +4263,7 @@ DB0FCB962797E6C2006C02E2 /* SearchResultViewController+DataSourceProvider.swift in Sources */, DB66729C25F9F91F00D60309 /* ComposeStatusItem.swift in Sources */, DB6180E326391A4C0018D199 /* ViewControllerAnimatedTransitioning.swift in Sources */, + DBD5B1F827BCFD9D00BD6B38 /* DataSourceProvider+TableViewControllerNavigateable.swift in Sources */, 0FB3D31E25E534C700AAD544 /* PickServerCategoryCollectionViewCell.swift in Sources */, DB0FCB882796BDA9006C02E2 /* SearchItem.swift in Sources */, DB336F3D278D80040031E64B /* FeedFetchedResultsController.swift in Sources */, @@ -4250,7 +4274,6 @@ 2D6DE40026141DF600A63F6A /* SearchViewModel.swift in Sources */, DB51D172262832380062B7A1 /* BlurHashDecode.swift in Sources */, DBCCC71E25F73297007E1AB6 /* APIService+Reblog.swift in Sources */, - DBE3CE13261D7D4200430CC6 /* StatusTableViewControllerAspect.swift in Sources */, DB0617FD27855BFE0030EE79 /* ServerRuleItem.swift in Sources */, 5BB04FD5262E7AFF0043BFF6 /* ReportViewController.swift in Sources */, DBAE3F942616E28B004B8251 /* APIService+Follow.swift in Sources */, @@ -4269,6 +4292,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + DB47AB6227CF752B00CD73C7 /* MastodonUISnapshotTests.swift in Sources */, DB427DF825BAA00100D1B89D /* MastodonUITests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -4415,9 +4439,9 @@ DB4B777F26CA4EFA00B087B3 /* ru */, DB4B778426CA500E00B087B3 /* gd-GB */, DB4B779226CA50BA00B087B3 /* th */, - DBDC1CF9272C0FD600055C3D /* ku-TR */, DB126A4C278C063F005726EE /* eu-ES */, DB126A56278C088D005726EE /* sv-FI */, + DBEB19E927E4F37B00B0E80E /* ku */, ); name = Intents.intentdefinition; sourceTree = "<group>"; @@ -4438,9 +4462,9 @@ DB4B778226CA4EFA00B087B3 /* ru */, DB4B778726CA500E00B087B3 /* gd-GB */, DB4B779526CA50BA00B087B3 /* th */, - DBDC1CFC272C0FD600055C3D /* ku-TR */, DB126A4F278C063F005726EE /* eu-ES */, DB126A59278C088D005726EE /* sv-FI */, + DBEB19EA27E4F37B00B0E80E /* ku */, ); name = InfoPlist.strings; sourceTree = "<group>"; @@ -4477,9 +4501,9 @@ DB4B779026CA504900B087B3 /* fr */, DB4B779126CA504A00B087B3 /* ja */, DB4B779626CA50BA00B087B3 /* th */, - DBDC1CFD272C0FD600055C3D /* ku-TR */, DB126A50278C063F005726EE /* eu-ES */, DB126A5A278C088D005726EE /* sv-FI */, + DBEB19EB27E4F37B00B0E80E /* ku */, ); name = Intents.stringsdict; sourceTree = "<group>"; @@ -4624,7 +4648,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 96; + CURRENT_PROJECT_VERSION = 109; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -4653,7 +4677,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 96; + CURRENT_PROJECT_VERSION = 109; DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = Mastodon/Info.plist; @@ -4761,11 +4785,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 96; + CURRENT_PROJECT_VERSION = 109; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 96; + DYLIB_CURRENT_VERSION = 109; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -4792,11 +4816,11 @@ APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 96; + CURRENT_PROJECT_VERSION = 109; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = 5Z4GVSS33P; DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 96; + DYLIB_CURRENT_VERSION = 109; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = AppShared/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; @@ -4821,7 +4845,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 96; + CURRENT_PROJECT_VERSION = 109; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -4846,7 +4870,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 96; + CURRENT_PROJECT_VERSION = 109; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = MastodonIntent/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -4871,7 +4895,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 96; + CURRENT_PROJECT_VERSION = 109; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -4896,7 +4920,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 96; + CURRENT_PROJECT_VERSION = 109; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = ShareActionExtension/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -4915,13 +4939,244 @@ }; name = Release; }; + DBEB19E127E4658E00B0E80E /* Release Snapshot */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INTENTS_CODEGEN_LANGUAGE = Swift; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = SNAPSHOT; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = "Release Snapshot"; + }; + DBEB19E227E4658E00B0E80E /* Release Snapshot */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0655B257371274BEB7EB1C19 /* Pods-Mastodon.release snapshot.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Mastodon/Mastodon.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 109; + DEVELOPMENT_ASSET_PATHS = "Mastodon/Resources/Preview\\ Assets.xcassets"; + DEVELOPMENT_TEAM = 5Z4GVSS33P; + INFOPLIST_FILE = Mastodon/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0.7; + PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "Mastodon/Vender/Mastodon-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = "Release Snapshot"; + }; + DBEB19E327E4658E00B0E80E /* Release Snapshot */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8E79CCBE51FBC3F7FE8CF49F /* Pods-MastodonTests.release snapshot.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 5Z4GVSS33P; + INFOPLIST_FILE = MastodonTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.MastodonTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Mastodon.app/Mastodon"; + }; + name = "Release Snapshot"; + }; + DBEB19E427E4658E00B0E80E /* Release Snapshot */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 0827D1674B2523503E8605F6 /* Pods-Mastodon-MastodonUITests.release snapshot.xcconfig */; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 5Z4GVSS33P; + INFOPLIST_FILE = MastodonUITests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.MastodonUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = Mastodon; + }; + name = "Release Snapshot"; + }; + DBEB19E527E4658E00B0E80E /* Release Snapshot */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3E08A432F40BA7B9CAA9DB68 /* Pods-AppShared.release snapshot.xcconfig */; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 109; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = 5Z4GVSS33P; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 109; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = AppShared/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.AppShared; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = "Release Snapshot"; + }; + DBEB19E627E4658E00B0E80E /* Release Snapshot */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 8ADD558BE5B8255E5764A54F /* Pods-NotificationService.release snapshot.xcconfig */; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 109; + DEVELOPMENT_TEAM = 5Z4GVSS33P; + INFOPLIST_FILE = NotificationService/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 1.0.7; + PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.NotificationService; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = "Release Snapshot"; + }; + DBEB19E727E4658E00B0E80E /* Release Snapshot */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F43DF6E8AB8C87914A64FC48 /* Pods-ShareActionExtension.release snapshot.xcconfig */; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = ShareActionExtension/ShareActionExtension.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 109; + DEVELOPMENT_TEAM = 5Z4GVSS33P; + INFOPLIST_FILE = ShareActionExtension/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 1.0.7; + PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.ShareActionExtension; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = "Release Snapshot"; + }; + DBEB19E827E4658E00B0E80E /* Release Snapshot */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 2C12EB4B3699D5D597027962 /* Pods-MastodonIntent.release snapshot.xcconfig */; + buildSettings = { + CODE_SIGN_ENTITLEMENTS = MastodonIntent/MastodonIntent.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 109; + DEVELOPMENT_TEAM = 5Z4GVSS33P; + INFOPLIST_FILE = MastodonIntent/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 1.0.7; + PRODUCT_BUNDLE_IDENTIFIER = org.joinmastodon.app.MastodonIntent; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "APP_EXTENSION $(inherited)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = "Release Snapshot"; + }; DBF8AE1C263293E400C9C23C /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 9553C689FFA9EBC880CAB78D /* Pods-NotificationService.debug.xcconfig */; buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 96; + CURRENT_PROJECT_VERSION = 109; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -4945,7 +5200,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = NotificationService/NotificationService.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 96; + CURRENT_PROJECT_VERSION = 109; DEVELOPMENT_TEAM = 5Z4GVSS33P; INFOPLIST_FILE = NotificationService/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( @@ -4971,6 +5226,7 @@ buildConfigurations = ( DB427DFA25BAA00100D1B89D /* Debug */, DB427DFB25BAA00100D1B89D /* Release */, + DBEB19E127E4658E00B0E80E /* Release Snapshot */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -4980,6 +5236,7 @@ buildConfigurations = ( DB427DFD25BAA00100D1B89D /* Debug */, DB427DFE25BAA00100D1B89D /* Release */, + DBEB19E227E4658E00B0E80E /* Release Snapshot */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -4989,6 +5246,7 @@ buildConfigurations = ( DB427E0025BAA00100D1B89D /* Debug */, DB427E0125BAA00100D1B89D /* Release */, + DBEB19E327E4658E00B0E80E /* Release Snapshot */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -4998,6 +5256,7 @@ buildConfigurations = ( DB427E0325BAA00100D1B89D /* Debug */, DB427E0425BAA00100D1B89D /* Release */, + DBEB19E427E4658E00B0E80E /* Release Snapshot */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -5007,6 +5266,7 @@ buildConfigurations = ( DB6804892637CD4C00430867 /* Debug */, DB68048A2637CD4C00430867 /* Release */, + DBEB19E527E4658E00B0E80E /* Release Snapshot */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -5016,6 +5276,7 @@ buildConfigurations = ( DB8FABD026AEC7B2008E5AF4 /* Debug */, DB8FABD326AEC7B2008E5AF4 /* Release */, + DBEB19E827E4658E00B0E80E /* Release Snapshot */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -5025,6 +5286,7 @@ buildConfigurations = ( DBC6461D26A170AB00B0E31B /* Debug */, DBC6462026A170AB00B0E31B /* Release */, + DBEB19E727E4658E00B0E80E /* Release Snapshot */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -5034,6 +5296,7 @@ buildConfigurations = ( DBF8AE1C263293E400C9C23C /* Debug */, DBF8AE1D263293E400C9C23C /* Release */, + DBEB19E627E4658E00B0E80E /* Release Snapshot */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon - Release.xcscheme b/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon - Release.xcscheme index 15ecdcbe..d5959cea 100644 --- a/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon - Release.xcscheme +++ b/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon - Release.xcscheme @@ -48,16 +48,6 @@ ReferencedContainer = "container:Mastodon.xcodeproj"> </BuildableReference> </TestableReference> - <TestableReference - skipped = "NO"> - <BuildableReference - BuildableIdentifier = "primary" - BlueprintIdentifier = "DB89B9F525C10FD0008580ED" - BuildableName = "CoreDataStackTests.xctest" - BlueprintName = "CoreDataStackTests" - ReferencedContainer = "container:Mastodon.xcodeproj"> - </BuildableReference> - </TestableReference> </Testables> </TestAction> <LaunchAction diff --git a/Mastodon.xcodeproj/xcshareddata/xcschemes/NotificationService.xcscheme b/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon - Snapshot.xcscheme similarity index 63% rename from Mastodon.xcodeproj/xcshareddata/xcschemes/NotificationService.xcscheme rename to Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon - Snapshot.xcscheme index d372229c..96cbba56 100644 --- a/Mastodon.xcodeproj/xcshareddata/xcschemes/NotificationService.xcscheme +++ b/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon - Snapshot.xcscheme @@ -1,26 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <Scheme LastUpgradeVersion = "1250" - wasCreatedForAppExtension = "YES" - version = "2.0"> + version = "1.7"> <BuildAction parallelizeBuildables = "YES" buildImplicitDependencies = "YES"> <BuildActionEntries> - <BuildActionEntry - buildForTesting = "YES" - buildForRunning = "YES" - buildForProfiling = "YES" - buildForArchiving = "YES" - buildForAnalyzing = "YES"> - <BuildableReference - BuildableIdentifier = "primary" - BlueprintIdentifier = "DBF8AE12263293E400C9C23C" - BuildableName = "NotificationService.appex" - BlueprintName = "NotificationService" - ReferencedContainer = "container:Mastodon.xcodeproj"> - </BuildableReference> - </BuildActionEntry> <BuildActionEntry buildForTesting = "YES" buildForRunning = "YES" @@ -35,28 +20,60 @@ ReferencedContainer = "container:Mastodon.xcodeproj"> </BuildableReference> </BuildActionEntry> + <BuildActionEntry + buildForTesting = "NO" + buildForRunning = "NO" + buildForProfiling = "NO" + buildForArchiving = "NO" + buildForAnalyzing = "NO"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "DB427DE725BAA00100D1B89D" + BuildableName = "MastodonTests.xctest" + BlueprintName = "MastodonTests" + ReferencedContainer = "container:Mastodon.xcodeproj"> + </BuildableReference> + </BuildActionEntry> + <BuildActionEntry + buildForTesting = "NO" + buildForRunning = "NO" + buildForProfiling = "NO" + buildForArchiving = "NO" + buildForAnalyzing = "NO"> + <BuildableReference + BuildableIdentifier = "primary" + BlueprintIdentifier = "DB427DF225BAA00100D1B89D" + BuildableName = "MastodonUITests.xctest" + BlueprintName = "MastodonUITests" + ReferencedContainer = "container:Mastodon.xcodeproj"> + </BuildableReference> + </BuildActionEntry> </BuildActionEntries> </BuildAction> <TestAction - buildConfiguration = "Debug" + buildConfiguration = "Release Snapshot" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" shouldUseLaunchSchemeArgsEnv = "YES"> - <Testables> - </Testables> + <TestPlans> + <TestPlanReference + reference = "container:AppStoreSnapshotTestPlan.xctestplan" + default = "YES"> + </TestPlanReference> + </TestPlans> </TestAction> <LaunchAction - buildConfiguration = "Debug" - selectedDebuggerIdentifier = "" - selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn" + buildConfiguration = "Release Snapshot" + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + disableMainThreadChecker = "YES" launchStyle = "0" - askForAppToLaunch = "Yes" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" debugServiceExtension = "internal" - allowLocationSimulation = "YES" - launchAutomaticallySubstyle = "2"> + enableGPUValidationMode = "1" + allowLocationSimulation = "YES"> <BuildableProductRunnable runnableDebuggingMode = "0"> <BuildableReference @@ -73,9 +90,7 @@ shouldUseLaunchSchemeArgsEnv = "YES" savedToolIdentifier = "" useCustomWorkingDirectory = "NO" - debugDocumentVersioning = "YES" - askForAppToLaunch = "Yes" - launchAutomaticallySubstyle = "2"> + debugDocumentVersioning = "YES"> <BuildableProductRunnable runnableDebuggingMode = "0"> <BuildableReference diff --git a/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon.xcscheme b/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon.xcscheme index de059787..488d5a2d 100644 --- a/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon.xcscheme +++ b/Mastodon.xcodeproj/xcshareddata/xcschemes/Mastodon.xcscheme @@ -32,6 +32,9 @@ reference = "container:Mastodon/Mastodon.xctestplan" default = "YES"> </TestPlanReference> + <TestPlanReference + reference = "container:AppStoreSnapshotTestPlan copy.xctestplan"> + </TestPlanReference> </TestPlans> <Testables> <TestableReference diff --git a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist index 7e7b5bef..a90323e9 100644 --- a/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/Mastodon.xcodeproj/xcuserdata/mainasuk.xcuserdatad/xcschemes/xcschememanagement.plist @@ -6,8 +6,10 @@ <dict> <key>AppShared.xcscheme_^#shared#^_</key> <dict> + <key>isShown</key> + <true/> <key>orderHint</key> - <integer>33</integer> + <integer>3</integer> </dict> <key>CoreDataStack.xcscheme_^#shared#^_</key> <dict> @@ -17,13 +19,18 @@ <key>Mastodon - RTL.xcscheme_^#shared#^_</key> <dict> <key>orderHint</key> - <integer>17</integer> + <integer>18</integer> </dict> <key>Mastodon - Release.xcscheme_^#shared#^_</key> <dict> <key>orderHint</key> <integer>1</integer> </dict> + <key>Mastodon - Snapshot.xcscheme_^#shared#^_</key> + <dict> + <key>orderHint</key> + <integer>2</integer> + </dict> <key>Mastodon - ar.xcscheme_^#shared#^_</key> <dict> <key>orderHint</key> @@ -97,7 +104,7 @@ <key>MastodonIntent.xcscheme_^#shared#^_</key> <dict> <key>orderHint</key> - <integer>32</integer> + <integer>49</integer> </dict> <key>MastodonIntents.xcscheme_^#shared#^_</key> <dict> @@ -112,12 +119,12 @@ <key>NotificationService.xcscheme_^#shared#^_</key> <dict> <key>orderHint</key> - <integer>2</integer> + <integer>51</integer> </dict> <key>ShareActionExtension.xcscheme_^#shared#^_</key> <dict> <key>orderHint</key> - <integer>31</integer> + <integer>50</integer> </dict> </dict> <key>SuppressBuildableAutocreation</key> @@ -137,6 +144,11 @@ <key>primary</key> <true/> </dict> + <key>DB68047E2637CD4C00430867</key> + <dict> + <key>primary</key> + <true/> + </dict> <key>DB89B9F525C10FD0008580ED</key> <dict> <key>primary</key> diff --git a/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved index a1034488..11d45388 100644 --- a/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Mastodon.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -55,6 +55,15 @@ "version": "1.2.0" } }, + { + "package": "FLAnimatedImage", + "repositoryURL": "https://github.com/Flipboard/FLAnimatedImage.git", + "state": { + "branch": null, + "revision": "e7f9fd4681ae41bf6f3056db08af4f401d61da52", + "version": "1.0.16" + } + }, { "package": "FPSIndicator", "repositoryURL": "https://github.com/MainasuK/FPSIndicator.git", @@ -207,6 +216,15 @@ "revision": "d0470491f56e734731bbf77991944c0dfdee3e0e", "version": "2.6.1" } + }, + { + "package": "UITextView+Placeholder", + "repositoryURL": "https://github.com/MainasuK/UITextView-Placeholder.git", + "state": { + "branch": null, + "revision": "20f513ded04a040cdf5467f0891849b1763ede3b", + "version": "1.4.1" + } } ] }, diff --git a/Mastodon/Activity/SafariActivity.swift b/Mastodon/Activity/SafariActivity.swift index d2c7b924..62a193ea 100644 --- a/Mastodon/Activity/SafariActivity.swift +++ b/Mastodon/Activity/SafariActivity.swift @@ -24,7 +24,7 @@ final class SafariActivity: UIActivity { } override var activityTitle: String? { - return L10n.Common.Controls.Actions.openInSafari + return UserDefaults.shared.preferredUsingDefaultBrowser ? L10n.Common.Controls.Actions.openInBrowser : L10n.Common.Controls.Actions.openInSafari } override var activityImage: UIImage? { diff --git a/Mastodon/Diffiable/FetchedResultsController/UserFetchedResultsController.swift b/Mastodon/Diffiable/FetchedResultsController/UserFetchedResultsController.swift index 2230e04b..c0922afc 100644 --- a/Mastodon/Diffiable/FetchedResultsController/UserFetchedResultsController.swift +++ b/Mastodon/Diffiable/FetchedResultsController/UserFetchedResultsController.swift @@ -22,12 +22,17 @@ final class UserFetchedResultsController: NSObject { // input @Published var domain: String? = nil @Published var userIDs: [Mastodon.Entity.Account.ID] = [] + @Published var additionalPredicate: NSPredicate? // output let _objectIDs = CurrentValueSubject<[NSManagedObjectID], Never>([]) @Published var records: [ManagedObjectRecord<MastodonUser>] = [] - init(managedObjectContext: NSManagedObjectContext, domain: String?, additionalTweetPredicate: NSPredicate?) { + init( + managedObjectContext: NSManagedObjectContext, + domain: String?, + additionalPredicate: NSPredicate? + ) { self.domain = domain ?? "" self.fetchedResultsController = { let fetchRequest = MastodonUser.sortedFetchRequest @@ -43,6 +48,7 @@ final class UserFetchedResultsController: NSObject { return controller }() + self.additionalPredicate = additionalPredicate super.init() // debounce output to prevent UI update issues @@ -53,15 +59,16 @@ final class UserFetchedResultsController: NSObject { fetchedResultsController.delegate = self - Publishers.CombineLatest( + Publishers.CombineLatest3( self.$domain.removeDuplicates(), - self.$userIDs.removeDuplicates() + self.$userIDs.removeDuplicates(), + self.$additionalPredicate.removeDuplicates() ) .receive(on: DispatchQueue.main) - .sink { [weak self] domain, ids in + .sink { [weak self] domain, ids, additionalPredicate in guard let self = self else { return } var predicates = [MastodonUser.predicate(domain: domain ?? "", ids: ids)] - if let additionalPredicate = additionalTweetPredicate { + if let additionalPredicate = additionalPredicate { predicates.append(additionalPredicate) } self.fetchedResultsController.fetchRequest.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: predicates) diff --git a/Mastodon/Diffiable/Notification/NotificationSection.swift b/Mastodon/Diffiable/Notification/NotificationSection.swift index 7cca0c0e..97cf8ada 100644 --- a/Mastodon/Diffiable/Notification/NotificationSection.swift +++ b/Mastodon/Diffiable/Notification/NotificationSection.swift @@ -24,6 +24,8 @@ extension NotificationSection { struct Configuration { weak var notificationTableViewCellDelegate: NotificationTableViewCellDelegate? + let filterContext: Mastodon.Entity.Filter.Context? + let activeFilters: Published<[Mastodon.Entity.Filter]>.Publisher? } static func diffableDataSource( @@ -58,57 +60,6 @@ extension NotificationSection { cell.activityIndicatorView.startAnimating() return cell } -// switch notificationItem { -// case .notification(let objectID, let attribute): -// guard let notification = try? managedObjectContext.existingObject(with: objectID) as? MastodonNotification, -// !notification.isDeleted -// else { return UITableViewCell() } -// -// let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: NotificationStatusTableViewCell.self), for: indexPath) as! NotificationStatusTableViewCell -// configure( -// tableView: tableView, -// cell: cell, -// notification: notification, -// dependency: dependency, -// attribute: attribute -// ) -// cell.delegate = delegate -// cell.isAccessibilityElement = true -// NotificationSection.configureStatusAccessibilityLabel(cell: cell) -// return cell -// -// case .notificationStatus(objectID: let objectID, attribute: let attribute): -// guard let notification = try? managedObjectContext.existingObject(with: objectID) as? MastodonNotification, -// !notification.isDeleted, -// let status = notification.status, -// let requestUserID = dependency.context.authenticationService.activeMastodonAuthenticationBox.value?.userID -// else { return UITableViewCell() } -// let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: StatusTableViewCell.self), for: indexPath) as! StatusTableViewCell -// -// // configure cell -// StatusSection.configureStatusTableViewCell( -// cell: cell, -// tableView: tableView, -// timelineContext: .notifications, -// dependency: dependency, -// readableLayoutFrame: tableView.readableContentGuide.layoutFrame, -// status: status, -// requestUserID: requestUserID, -// statusItemAttribute: attribute -// ) -// cell.statusView.headerContainerView.isHidden = true // set header hide -// cell.statusView.actionToolbarContainer.isHidden = true // set toolbar hide -// cell.statusView.actionToolbarPlaceholderPaddingView.isHidden = false -// cell.delegate = statusTableViewCellDelegate -// cell.isAccessibilityElement = true -// StatusSection.configureStatusAccessibilityLabel(cell: cell) -// return cell -// -// case .bottomLoader: -// let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self)) as! TimelineBottomLoaderTableViewCell -// cell.startAnimating() -// return cell -// } } } } @@ -142,163 +93,17 @@ extension NotificationSection { viewModel: viewModel, delegate: configuration.notificationTableViewCellDelegate ) + + cell.notificationView.statusView.viewModel.filterContext = configuration.filterContext + cell.notificationView.quoteStatusView.viewModel.filterContext = configuration.filterContext + + configuration.activeFilters? + .assign(to: \.activeFilters, on: cell.notificationView.statusView.viewModel) + .store(in: &cell.disposeBag) + configuration.activeFilters? + .assign(to: \.activeFilters, on: cell.notificationView.quoteStatusView.viewModel) + .store(in: &cell.disposeBag) } -// 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: " ") -// }() -// } } diff --git a/Mastodon/Diffiable/Onboarding/RegisterItem.swift b/Mastodon/Diffiable/Onboarding/RegisterItem.swift index 0fb0aead..d54981b6 100644 --- a/Mastodon/Diffiable/Onboarding/RegisterItem.swift +++ b/Mastodon/Diffiable/Onboarding/RegisterItem.swift @@ -8,7 +8,7 @@ import Foundation enum RegisterItem: Hashable { - case header + case header(domain: String) case avatar case name case username diff --git a/Mastodon/Diffiable/Profile/ProfileFieldItem.swift b/Mastodon/Diffiable/Profile/ProfileFieldItem.swift index 60651d72..47848cc0 100644 --- a/Mastodon/Diffiable/Profile/ProfileFieldItem.swift +++ b/Mastodon/Diffiable/Profile/ProfileFieldItem.swift @@ -14,6 +14,7 @@ enum ProfileFieldItem: Hashable { case field(field: FieldValue) case editField(field: FieldValue) case addEntry + case noResult } extension ProfileFieldItem { diff --git a/Mastodon/Diffiable/Profile/ProfileFieldSection.swift b/Mastodon/Diffiable/Profile/ProfileFieldSection.swift index fc2dee15..e1b0d649 100644 --- a/Mastodon/Diffiable/Profile/ProfileFieldSection.swift +++ b/Mastodon/Diffiable/Profile/ProfileFieldSection.swift @@ -107,6 +107,22 @@ extension ProfileFieldSection { cell.backgroundConfiguration = backgroundConfiguration } + let noResultCellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, ProfileFieldItem> { cell, indexPath, item in + guard case .noResult = item else { return } + + var contentConfiguration = cell.defaultContentConfiguration() + contentConfiguration.text = L10n.Scene.Search.Searching.EmptyState.noResults // FIXME: + contentConfiguration.textProperties.alignment = .center + cell.contentConfiguration = contentConfiguration + + + var backgroundConfiguration = UIBackgroundConfiguration.listPlainCell() + backgroundConfiguration.backgroundColorTransformer = .init { _ in + return .secondarySystemBackground + } + cell.backgroundConfiguration = backgroundConfiguration + } + let dataSource = UICollectionViewDiffableDataSource<ProfileFieldSection, ProfileFieldItem>(collectionView: collectionView) { collectionView, indexPath, item in switch item { case .field: @@ -127,6 +143,12 @@ extension ProfileFieldSection { for: indexPath, item: item ) + case .noResult: + return collectionView.dequeueConfiguredReusableCell( + using: noResultCellRegistration, + for: indexPath, + item: item + ) } } diff --git a/Mastodon/Diffiable/RecommandAccount/RecommendAccountSection.swift b/Mastodon/Diffiable/RecommandAccount/RecommendAccountSection.swift index c6d4897a..f59164f3 100644 --- a/Mastodon/Diffiable/RecommandAccount/RecommendAccountSection.swift +++ b/Mastodon/Diffiable/RecommandAccount/RecommendAccountSection.swift @@ -146,10 +146,15 @@ extension RecommendAccountSection { case .account(let record): context.managedObjectContext.performAndWait { guard let user = record.object(in: context.managedObjectContext) else { return } - cell.config(with: user) + cell.configure(user: user) } + + context.authenticationService.activeMastodonAuthenticationBox + .map { $0 as UserIdentifier? } + .assign(to: \.userIdentifier, on: cell.viewModel) + .store(in: &cell.disposeBag) + cell.delegate = configuration.suggestionAccountTableViewCellDelegate } - cell.delegate = configuration.suggestionAccountTableViewCellDelegate return cell } } diff --git a/Mastodon/Diffiable/Search/SearchSection.swift b/Mastodon/Diffiable/Search/SearchSection.swift index 38c87a76..21f1d479 100644 --- a/Mastodon/Diffiable/Search/SearchSection.swift +++ b/Mastodon/Diffiable/Search/SearchSection.swift @@ -21,8 +21,11 @@ extension SearchSection { ) -> UICollectionViewDiffableDataSource<SearchSection, SearchItem> { let trendCellRegister = UICollectionView.CellRegistration<TrendCollectionViewCell, Mastodon.Entity.Tag> { cell, indexPath, item in - cell.primaryLabel.text = "#" + item.name - cell.secondaryLabel.text = L10n.Scene.Search.Recommend.HashTag.peopleTalking(item.talkingPeopleCount ?? 0) + let primaryLabelText = "#" + item.name + let secondaryLabelText = L10n.Scene.Search.Recommend.HashTag.peopleTalking(item.talkingPeopleCount ?? 0) + + cell.primaryLabel.text = primaryLabelText + cell.secondaryLabel.text = secondaryLabelText cell.lineChartView.data = (item.history ?? []) .sorted(by: { $0.day < $1.day }) // latest last @@ -32,6 +35,12 @@ extension SearchSection { } return CGFloat(point) } + + cell.isAccessibilityElement = true + cell.accessibilityLabel = [ + primaryLabelText, + secondaryLabelText + ].joined(separator: ", ") } let dataSource = UICollectionViewDiffableDataSource<SearchSection, SearchItem>( diff --git a/Mastodon/Diffiable/Settings/SettingsItem.swift b/Mastodon/Diffiable/Settings/SettingsItem.swift index 50f0a761..00c88d16 100644 --- a/Mastodon/Diffiable/Settings/SettingsItem.swift +++ b/Mastodon/Diffiable/Settings/SettingsItem.swift @@ -13,6 +13,7 @@ import MastodonLocalization enum SettingsItem { case appearance(record: ManagedObjectRecord<Setting>) + case appearancePreference(record: ManagedObjectRecord<Setting>, appearanceType: AppearanceType) case preference(settingRecord: ManagedObjectRecord<Setting>, preferenceType: PreferenceType) case notification(settingRecord: ManagedObjectRecord<Setting>, switchMode: NotificationSwitchMode) case boringZone(item: Link) @@ -23,11 +24,18 @@ extension SettingsItem { enum AppearanceMode: String { case system - case reallyDark - case sortaDark + case dark case light } + enum AppearanceType: Hashable { + case preferredTrueDarkMode + + var title: String { + return L10n.Scene.Settings.Section.Preference.trueBlackDarkMode + } + } + enum NotificationSwitchMode: CaseIterable, Hashable { case favorite case follow @@ -94,9 +102,13 @@ extension SettingsItem { extension SettingsItem: Hashable { func hash(into hasher: inout Hasher) { switch self { - case .appearance(let settingObjectID): + case .appearance(let record): hasher.combine(String(describing: SettingsItem.AppearanceMode.self)) - hasher.combine(settingObjectID) + hasher.combine(record) + case .appearancePreference(let record, let appearanceType): + hasher.combine(String(describing: SettingsItem.AppearanceType.self)) + hasher.combine(record) + hasher.combine(appearanceType) case .notification(let settingObjectID, let switchMode): hasher.combine(String(describing: SettingsItem.notification.self)) hasher.combine(settingObjectID) diff --git a/Mastodon/Diffiable/Settings/SettingsSection.swift b/Mastodon/Diffiable/Settings/SettingsSection.swift index cc03ae05..adc7140b 100644 --- a/Mastodon/Diffiable/Settings/SettingsSection.swift +++ b/Mastodon/Diffiable/Settings/SettingsSection.swift @@ -13,6 +13,7 @@ import MastodonLocalization enum SettingsSection: Hashable { case appearance + case appearancePreference case preference case notifications case boringZone @@ -20,7 +21,8 @@ enum SettingsSection: Hashable { var title: String { switch self { - case .appearance: return "Look and Feel" // TODO: i18n + case .appearance: return L10n.Scene.Settings.Section.LookAndFeel.title + case .appearancePreference: return "" case .preference: return "" case .notifications: return L10n.Scene.Settings.Section.Notifications.title case .boringZone: return L10n.Scene.Settings.Section.BoringZone.title @@ -49,6 +51,26 @@ extension SettingsSection { } cell.delegate = settingsAppearanceTableViewCellDelegate return cell + case .appearancePreference(let record, let appearanceType): + let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: SettingsToggleTableViewCell.self), for: indexPath) as! SettingsToggleTableViewCell + cell.delegate = settingsToggleCellDelegate + managedObjectContext.performAndWait { + guard let setting = record.object(in: managedObjectContext) else { return } + SettingsSection.configureSettingToggle(cell: cell, item: item, setting: setting) + + ManagedObjectObserver.observe(object: setting) + .receive(on: DispatchQueue.main) + .sink(receiveCompletion: { _ in + // do nothing + }, receiveValue: { [weak cell] change in + guard let cell = cell else { return } + guard case .update(let object) = change.changeType, + let setting = object as? Setting else { return } + SettingsSection.configureSettingToggle(cell: cell, item: item, setting: setting) + }) + .store(in: &cell.disposeBag) + } + return cell case .preference(let record, _): let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: SettingsToggleTableViewCell.self), for: indexPath) as! SettingsToggleTableViewCell cell.delegate = settingsToggleCellDelegate @@ -107,17 +129,29 @@ extension SettingsSection { item: SettingsItem, setting: Setting ) { - guard case let .preference(_, preferenceType) = item else { return } - - cell.textLabel?.text = preferenceType.title - - switch preferenceType { - case .disableAvatarAnimation: - cell.switchButton.isOn = setting.preferredStaticAvatar - case .disableEmojiAnimation: - cell.switchButton.isOn = setting.preferredStaticEmoji - case .useDefaultBrowser: - cell.switchButton.isOn = setting.preferredUsingDefaultBrowser + switch item { + case .appearancePreference(_, let appearanceType): + cell.textLabel?.text = appearanceType.title + + switch appearanceType { + case .preferredTrueDarkMode: + cell.switchButton.isOn = setting.preferredTrueBlackDarkMode + } + + case .preference(_, let preferenceType): + cell.textLabel?.text = preferenceType.title + + switch preferenceType { + case .disableAvatarAnimation: + cell.switchButton.isOn = setting.preferredStaticAvatar + case .disableEmojiAnimation: + cell.switchButton.isOn = setting.preferredStaticEmoji + case .useDefaultBrowser: + cell.switchButton.isOn = setting.preferredUsingDefaultBrowser + } + + default: + assertionFailure() } } diff --git a/Mastodon/Diffiable/Status/StatusSection.swift b/Mastodon/Diffiable/Status/StatusSection.swift index 6eefdef7..40b7e535 100644 --- a/Mastodon/Diffiable/Status/StatusSection.swift +++ b/Mastodon/Diffiable/Status/StatusSection.swift @@ -28,6 +28,8 @@ extension StatusSection { struct Configuration { weak var statusTableViewCellDelegate: StatusTableViewCellDelegate? weak var timelineMiddleLoaderTableViewCellDelegate: TimelineMiddleLoaderTableViewCellDelegate? + let filterContext: Mastodon.Entity.Filter.Context? + let activeFilters: Published<[Mastodon.Entity.Filter]>.Publisher? } static func diffableDataSource( @@ -258,6 +260,11 @@ extension StatusSection { viewModel: viewModel, delegate: configuration.statusTableViewCellDelegate ) + + cell.statusView.viewModel.filterContext = configuration.filterContext + configuration.activeFilters? + .assign(to: \.activeFilters, on: cell.statusView.viewModel) + .store(in: &cell.disposeBag) } static func configure( @@ -282,6 +289,11 @@ extension StatusSection { viewModel: viewModel, delegate: configuration.statusTableViewCellDelegate ) + + cell.statusView.viewModel.filterContext = configuration.filterContext + configuration.activeFilters? + .assign(to: \.activeFilters, on: cell.statusView.viewModel) + .store(in: &cell.disposeBag) } static func configure( @@ -296,133 +308,3 @@ extension StatusSection { } } - -extension StatusSection { - - enum TimelineContext { - case home - case notifications - case `public` - case thread - case account - - case favorite - case hashtag - case report - case search - - var filterContext: Mastodon.Entity.Filter.Context? { - switch self { - case .home: return .home - case .notifications: return .notifications - case .public: return .public - case .thread: return .thread - case .account: return .account - default: return nil - } - } - } - - private static func needsFilterStatus( - content: MastodonMetaContent?, - filters: [Mastodon.Entity.Filter], - timelineContext: TimelineContext - ) -> AnyPublisher<Bool, Never> { - guard let content = content, - let currentFilterContext = timelineContext.filterContext, - !filters.isEmpty else { - return Just(false).eraseToAnyPublisher() - } - - return Future<Bool, Never> { promise in - DispatchQueue.global(qos: .userInteractive).async { - var wordFilters: [Mastodon.Entity.Filter] = [] - var nonWordFilters: [Mastodon.Entity.Filter] = [] - for filter in filters { - guard filter.context.contains(where: { $0 == currentFilterContext }) else { continue } - if filter.wholeWord { - wordFilters.append(filter) - } else { - nonWordFilters.append(filter) - } - } - - let text = content.original.lowercased() - - var needsFilter = false - for filter in nonWordFilters { - guard text.contains(filter.phrase.lowercased()) else { continue } - needsFilter = true - break - } - - if needsFilter { - DispatchQueue.main.async { - promise(.success(true)) - } - return - } - - let tokenizer = NLTokenizer(unit: .word) - tokenizer.string = text - let phraseWords = wordFilters.map { $0.phrase.lowercased() } - tokenizer.enumerateTokens(in: text.startIndex..<text.endIndex) { range, _ in - let word = String(text[range]) - if phraseWords.contains(word) { - needsFilter = true - return false - } else { - return true - } - } - - DispatchQueue.main.async { - promise(.success(needsFilter)) - } - } - } - .eraseToAnyPublisher() - } - -} - -class StatusContentOperation: Operation { - - let logger = Logger(subsystem: "StatusContentOperation", category: "logic") - - // input - let statusObjectID: NSManagedObjectID - let mastodonContent: MastodonContent - - // output - var result: Result<MastodonMetaContent, Error>? - - init( - statusObjectID: NSManagedObjectID, - mastodonContent: MastodonContent - ) { - self.statusObjectID = statusObjectID - self.mastodonContent = mastodonContent - super.init() - } - - override func main() { - guard !isCancelled else { return } - // logger.debug("\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): prcoess \(self.statusObjectID)…") - - do { - let content = try MastodonMetaContent.convert(document: mastodonContent) - result = .success(content) - // logger.debug("\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): process success \(self.statusObjectID)") - } catch { - result = .failure(error) - // logger.debug("\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): process fail \(self.statusObjectID)") - } - - } - - override func cancel() { - // logger.debug("\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): cancel \(self.statusObjectID.debugDescription)") - super.cancel() - } -} diff --git a/Mastodon/Generated/AutoGenerateTableViewDelegate.generated.swift b/Mastodon/Generated/AutoGenerateTableViewDelegate.generated.swift index b8c092f6..ebf86700 100644 --- a/Mastodon/Generated/AutoGenerateTableViewDelegate.generated.swift +++ b/Mastodon/Generated/AutoGenerateTableViewDelegate.generated.swift @@ -2,7 +2,13 @@ // DO NOT EDIT -// sourcery:inline:FollowingListViewController.AutoGenerateTableViewDelegate + + + + + + +// sourcery:inline:UserTimelineViewController.AutoGenerateTableViewDelegate // Generated using Sourcery // DO NOT EDIT @@ -10,11 +16,20 @@ func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { aspectTableView(tableView, didSelectRowAt: indexPath) } +func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? { + return aspectTableView(tableView, contextMenuConfigurationForRowAt: indexPath, point: point) +} + +func tableView(_ tableView: UITableView, previewForHighlightingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? { + return aspectTableView(tableView, previewForHighlightingContextMenuWithConfiguration: configuration) +} + +func tableView(_ tableView: UITableView, previewForDismissingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? { + return aspectTableView(tableView, previewForDismissingContextMenuWithConfiguration: configuration) +} + +func tableView(_ tableView: UITableView, willPerformPreviewActionForMenuWith configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionCommitAnimating) { + aspectTableView(tableView, willPerformPreviewActionForMenuWith: configuration, animator: animator) +} // sourcery:end - - - - - - diff --git a/Mastodon/Info.plist b/Mastodon/Info.plist index e86a4833..311ee390 100644 --- a/Mastodon/Info.plist +++ b/Mastodon/Info.plist @@ -2,6 +2,19 @@ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> + <key>NSAppTransportSecurity</key> + <dict> + <key>NSExceptionDomains</key> + <dict> + <key>onion</key> + <dict> + <key>NSExceptionAllowsInsecureHTTPLoads</key> + <true/> + <key>NSIncludesSubdomains</key> + <true/> + </dict> + </dict> + </dict> <key>CADisableMinimumFrameDurationOnPhone</key> <true/> <key>CFBundleDevelopmentRegion</key> @@ -30,7 +43,7 @@ </dict> </array> <key>CFBundleVersion</key> - <string>96</string> + <string>109</string> <key>ITSAppUsesNonExemptEncryption</key> <false/> <key>LSApplicationQueriesSchemes</key> diff --git a/Mastodon/Protocol/CellFrameCacheContainer.swift b/Mastodon/Protocol/CellFrameCacheContainer.swift new file mode 100644 index 00000000..b7cefe75 --- /dev/null +++ b/Mastodon/Protocol/CellFrameCacheContainer.swift @@ -0,0 +1,29 @@ +// +// CellFrameCacheContainer.swift +// TwidereX +// +// Created by Cirno MainasuK on 2021-10-13. +// Copyright © 2021 Twidere. All rights reserved. +// + +import UIKit + +protocol CellFrameCacheContainer { + var cellFrameCache: NSCache<NSNumber, NSValue> { get } + + func keyForCache(tableView: UITableView, indexPath: IndexPath) -> NSNumber? +} + +extension CellFrameCacheContainer { + func cacheCellFrame(tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) { + guard let key = keyForCache(tableView: tableView, indexPath: indexPath) else { return } + let value = NSValue(cgRect: cell.frame) + cellFrameCache.setObject(value, forKey: key) + } + + func retrieveCellFrame(tableView: UITableView, indexPath: IndexPath) -> CGRect? { + guard let key = keyForCache(tableView: tableView, indexPath: indexPath) else { return nil } + guard let frame = cellFrameCache.object(forKey: key)?.cgRectValue else { return nil } + return frame + } +} diff --git a/Mastodon/Protocol/ContentOffsetAdjustableTimelineViewControllerDelegate.swift b/Mastodon/Protocol/ContentOffsetAdjustableTimelineViewControllerDelegate.swift deleted file mode 100644 index 98160eb4..00000000 --- a/Mastodon/Protocol/ContentOffsetAdjustableTimelineViewControllerDelegate.swift +++ /dev/null @@ -1,13 +0,0 @@ -// -// ContentOffsetAdjustableTimelineViewControllerDelegate.swift -// Mastodon -// -// Created by sxiaojian on 2021/2/5. -// - -import UIKit - -protocol ContentOffsetAdjustableTimelineViewControllerDelegate: AnyObject { - func navigationBar() -> UINavigationBar? -} - diff --git a/Mastodon/Protocol/Provider/DataSourceFacade+Status.swift b/Mastodon/Protocol/Provider/DataSourceFacade+Status.swift index a98d34f3..eab85e95 100644 --- a/Mastodon/Protocol/Provider/DataSourceFacade+Status.swift +++ b/Mastodon/Protocol/Provider/DataSourceFacade+Status.swift @@ -10,6 +10,7 @@ import CoreDataStack import MastodonUI import MastodonLocalization +// Delete extension DataSourceFacade { static func responseToDeleteStatus( @@ -25,6 +26,7 @@ extension DataSourceFacade { } +// Share extension DataSourceFacade { @MainActor @@ -74,6 +76,7 @@ extension DataSourceFacade { } } +// ActionToolBar extension DataSourceFacade { @MainActor static func responseToActionToolbar( @@ -133,6 +136,7 @@ extension DataSourceFacade { } +// menu extension DataSourceFacade { struct MenuContext { diff --git a/Mastodon/Protocol/Provider/DataSourceProvider+NotificationTableViewCellDelegate.swift b/Mastodon/Protocol/Provider/DataSourceProvider+NotificationTableViewCellDelegate.swift index f062f01d..0924028f 100644 --- a/Mastodon/Protocol/Provider/DataSourceProvider+NotificationTableViewCellDelegate.swift +++ b/Mastodon/Protocol/Provider/DataSourceProvider+NotificationTableViewCellDelegate.swift @@ -102,6 +102,119 @@ extension NotificationTableViewCellDelegate where Self: DataSourceProvider { } } +private struct NotificationMediaTransitionContext { + let status: ManagedObjectRecord<Status> + let needsToggleMediaSensitive: Bool +} + +extension NotificationTableViewCellDelegate where Self: DataSourceProvider & MediaPreviewableViewController { + + func tableViewCell( + _ cell: UITableViewCell, + notificationView: NotificationView, + statusView: StatusView, + mediaGridContainerView: MediaGridContainerView, + mediaView: MediaView, + didSelectMediaViewAt index: Int + ) { + Task { + let source = DataSourceItem.Source(tableViewCell: cell, indexPath: nil) + guard let item = await item(from: source) else { + assertionFailure() + return + } + guard case let .notification(record) = item else { + assertionFailure("only works for status data provider") + return + } + + let managedObjectContext = self.context.managedObjectContext + let _mediaTransitionContext: NotificationMediaTransitionContext? = try await managedObjectContext.perform { + guard let notification = record.object(in: managedObjectContext) else { return nil } + guard let _status = notification.status else { return nil } + let status = _status.reblog ?? _status + return NotificationMediaTransitionContext( + status: .init(objectID: status.objectID), + needsToggleMediaSensitive: status.isMediaSensitiveToggled ? !status.sensitive : status.sensitive + ) + } + + guard let mediaTransitionContext = _mediaTransitionContext else { return } + + guard !mediaTransitionContext.needsToggleMediaSensitive else { + try await DataSourceFacade.responseToToggleSensitiveAction( + dependency: self, + status: mediaTransitionContext.status + ) + return + } + + try await DataSourceFacade.coordinateToMediaPreviewScene( + dependency: self, + status: mediaTransitionContext.status, + previewContext: DataSourceFacade.AttachmentPreviewContext( + containerView: .mediaGridContainerView(mediaGridContainerView), + mediaView: mediaView, + index: index + ) + ) + } // end Task + } + + func tableViewCell( + _ cell: UITableViewCell, + notificationView: NotificationView, + quoteStatusView: StatusView, + mediaGridContainerView: MediaGridContainerView, + mediaView: MediaView, + didSelectMediaViewAt index: Int + ) { + Task { + let source = DataSourceItem.Source(tableViewCell: cell, indexPath: nil) + guard let item = await item(from: source) else { + assertionFailure() + return + } + guard case let .notification(record) = item else { + assertionFailure("only works for status data provider") + return + } + + let managedObjectContext = self.context.managedObjectContext + let _mediaTransitionContext: NotificationMediaTransitionContext? = try await managedObjectContext.perform { + guard let notification = record.object(in: managedObjectContext) else { return nil } + guard let _status = notification.status else { return nil } + let status = _status.reblog ?? _status + return NotificationMediaTransitionContext( + status: .init(objectID: status.objectID), + needsToggleMediaSensitive: status.isMediaSensitiveToggled ? !status.sensitive : status.sensitive + ) + } + + guard let mediaTransitionContext = _mediaTransitionContext else { return } + + guard !mediaTransitionContext.needsToggleMediaSensitive else { + try await DataSourceFacade.responseToToggleSensitiveAction( + dependency: self, + status: mediaTransitionContext.status + ) + return + } + + try await DataSourceFacade.coordinateToMediaPreviewScene( + dependency: self, + status: mediaTransitionContext.status, + previewContext: DataSourceFacade.AttachmentPreviewContext( + containerView: .mediaGridContainerView(mediaGridContainerView), + mediaView: mediaView, + index: index + ) + ) + } // end Task + } + +} + // MARK: - Status Toolbar extension NotificationTableViewCellDelegate where Self: DataSourceProvider { func tableViewCell( @@ -142,7 +255,6 @@ extension NotificationTableViewCellDelegate where Self: DataSourceProvider { } } - // MARK: - Status Author Avatar extension NotificationTableViewCellDelegate where Self: DataSourceProvider { func tableViewCell( diff --git a/Mastodon/Protocol/Provider/DataSourceProvider+StatusTableViewCellDelegate.swift b/Mastodon/Protocol/Provider/DataSourceProvider+StatusTableViewCellDelegate.swift index a7afca8c..d14b5c34 100644 --- a/Mastodon/Protocol/Provider/DataSourceProvider+StatusTableViewCellDelegate.swift +++ b/Mastodon/Protocol/Provider/DataSourceProvider+StatusTableViewCellDelegate.swift @@ -28,11 +28,36 @@ extension StatusTableViewCellDelegate where Self: DataSourceProvider { assertionFailure("only works for status data provider") return } - await DataSourceFacade.coordinateToProfileScene( - provider: self, - target: .reblog, // keep the wrapper for header author - status: status - ) + + switch await statusView.viewModel.header { + case .none: + break + case .reply: + let _replyToAuthor: ManagedObjectRecord<MastodonUser>? = try? await context.managedObjectContext.perform { + guard let status = status.object(in: self.context.managedObjectContext) else { return nil } + guard let inReplyToAccountID = status.inReplyToAccountID else { return nil } + let request = MastodonUser.sortedFetchRequest + request.predicate = MastodonUser.predicate(domain: status.author.domain, id: inReplyToAccountID) + request.fetchLimit = 1 + guard let author = self.context.managedObjectContext.safeFetch(request).first else { return nil } + return .init(objectID: author.objectID) + } + guard let replyToAuthor = _replyToAuthor else { + return + } + + await DataSourceFacade.coordinateToProfileScene( + provider: self, + user: replyToAuthor + ) + + case .repost: + await DataSourceFacade.coordinateToProfileScene( + provider: self, + target: .reblog, // keep the wrapper for header author + status: status + ) + } } } diff --git a/Mastodon/Protocol/Provider/DataSourceProvider+StatusTableViewControllerNavigateable.swift b/Mastodon/Protocol/Provider/DataSourceProvider+StatusTableViewControllerNavigateable.swift new file mode 100644 index 00000000..fb4a7d84 --- /dev/null +++ b/Mastodon/Protocol/Provider/DataSourceProvider+StatusTableViewControllerNavigateable.swift @@ -0,0 +1,191 @@ +// +// DataSourceProvider+StatusTableViewControllerNavigateable.swift +// Mastodon +// +// Created by MainasuK on 2022-2-16. +// + +import os.log +import UIKit +import CoreDataStack + +extension StatusTableViewControllerNavigateableCore where Self: DataSourceProvider & StatusTableViewControllerNavigateableRelay { + + var statusNavigationKeyCommands: [UIKeyCommand] { + StatusTableViewNavigation.allCases.map { navigation in + UIKeyCommand( + title: navigation.title, + image: nil, + action: #selector(Self.statusKeyCommandHandlerRelay(_:)), + input: navigation.input, + modifierFlags: navigation.modifierFlags, + propertyList: navigation.propertyList, + alternates: [], + discoverabilityTitle: nil, + attributes: [], + state: .off + ) + } + } + +} + +extension StatusTableViewControllerNavigateableCore where Self: DataSourceProvider { + + func statusKeyCommandHandler(_ sender: UIKeyCommand) { + guard let rawValue = sender.propertyList as? String, + let navigation = StatusTableViewNavigation(rawValue: rawValue) else { return } + + os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: %s", ((#file as NSString).lastPathComponent), #line, #function, navigation.title) + Task { + switch navigation { + case .openAuthorProfile: await openAuthorProfile(target: .status) + case .openRebloggerProfile: await openAuthorProfile(target: .reblog) + case .replyStatus: await replyStatus() + case .toggleReblog: await toggleReblog() + case .toggleFavorite: await toggleFavorite() + case .toggleContentWarning: await toggleContentWarning() + case .previewImage: await previewImage() + } + } + } + +} + +// status coordinate +extension StatusTableViewControllerNavigateableCore where Self: DataSourceProvider { + + @MainActor + private func statusRecord() async -> ManagedObjectRecord<Status>? { + guard let indexPathForSelectedRow = tableView.indexPathForSelectedRow else { return nil } + let source = DataSourceItem.Source(indexPath: indexPathForSelectedRow) + guard let item = await item(from: source) else { return nil } + + switch item { + case .status(let record): + return record + case .notification(let record): + let _statusRecord: ManagedObjectRecord<Status>? = try? await context.managedObjectContext.perform { + guard let notification = record.object(in: self.context.managedObjectContext) else { return nil } + guard let status = notification.status else { return nil } + return .init(objectID: status.objectID) + } + guard let statusRecord = _statusRecord else { + return nil + } + return statusRecord + default: + return nil + } + } + + @MainActor + private func openAuthorProfile(target: DataSourceFacade.StatusTarget) async { + guard let status = await statusRecord() else { return } + await DataSourceFacade.coordinateToProfileScene( + provider: self, + target: target, + status: status + ) + } + + @MainActor + private func replyStatus() async { + guard let status = await statusRecord() else { return } + + guard let authenticationBox = self.context.authenticationService.activeMastodonAuthenticationBox.value else { return } + let selectionFeedbackGenerator = UISelectionFeedbackGenerator() + selectionFeedbackGenerator.selectionChanged() + + let composeViewModel = ComposeViewModel( + context: self.context, + composeKind: .reply(status: status), + authenticationBox: authenticationBox + ) + self.coordinator.present( + scene: .compose(viewModel: composeViewModel), + from: self, + transition: .modal(animated: true, completion: nil) + ) + } + + @MainActor + private func previewImage() async { + guard let status = await statusRecord() else { return } + + guard let provider = self as? (DataSourceProvider & MediaPreviewableViewController) else { return } + guard let indexPathForSelectedRow = tableView.indexPathForSelectedRow, + let cell = tableView.cellForRow(at: indexPathForSelectedRow) as? StatusTableViewCell + else { return } + + guard let mediaView = cell.statusView.mediaGridContainerView.mediaViews.first else { return } + + do { + try await DataSourceFacade.coordinateToMediaPreviewScene( + dependency: provider, + status: status, + previewContext: DataSourceFacade.AttachmentPreviewContext( + containerView: .mediaGridContainerView(cell.statusView.mediaGridContainerView), + mediaView: mediaView, + index: 0 + ) + ) + } catch { + assertionFailure() + } + } + +} + +// toggle +extension StatusTableViewControllerNavigateableCore where Self: DataSourceProvider { + + @MainActor + private func toggleReblog() async { + guard let status = await statusRecord() else { return } + + guard let authenticationBox = self.context.authenticationService.activeMastodonAuthenticationBox.value else { return } + + do { + try await DataSourceFacade.responseToStatusReblogAction( + provider: self, + status: status, + authenticationBox: authenticationBox + ) + } catch { + assertionFailure() + } + } + + @MainActor + private func toggleFavorite() async { + guard let status = await statusRecord() else { return } + + guard let authenticationBox = self.context.authenticationService.activeMastodonAuthenticationBox.value else { return } + + do { + try await DataSourceFacade.responseToStatusFavoriteAction( + provider: self, + status: status, + authenticationBox: authenticationBox + ) + } catch { + assertionFailure() + } + } + + @MainActor + private func toggleContentWarning() async { + guard let status = await statusRecord() else { return } + + do { + try await DataSourceFacade.responseToToggleSensitiveAction( + dependency: self, + status: status + ) + } catch { + assertionFailure() + } + } + +} diff --git a/Mastodon/Protocol/Provider/DataSourceProvider+TableViewControllerNavigateable.swift b/Mastodon/Protocol/Provider/DataSourceProvider+TableViewControllerNavigateable.swift new file mode 100644 index 00000000..f7e50cff --- /dev/null +++ b/Mastodon/Protocol/Provider/DataSourceProvider+TableViewControllerNavigateable.swift @@ -0,0 +1,156 @@ +// +// DataSourceProvider+TableViewControllerNavigateable.swift +// Mastodon +// +// Created by MainasuK on 2022-2-16. +// + +import os.log +import UIKit + +extension TableViewControllerNavigateableCore where Self: TableViewControllerNavigateableRelay { + var navigationKeyCommands: [UIKeyCommand] { + TableViewNavigation.allCases.map { navigation in + UIKeyCommand( + title: navigation.title, + image: nil, + action: #selector(Self.navigateKeyCommandHandlerRelay(_:)), + input: navigation.input, + modifierFlags: navigation.modifierFlags, + propertyList: navigation.propertyList, + alternates: [], + discoverabilityTitle: nil, + attributes: [], + state: .off + ) + } + } +} + +extension TableViewControllerNavigateableCore { + + func navigateKeyCommandHandler(_ sender: UIKeyCommand) { + guard let rawValue = sender.propertyList as? String, + let navigation = TableViewNavigation(rawValue: rawValue) else { return } + + os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: %s", ((#file as NSString).lastPathComponent), #line, #function, navigation.title) + switch navigation { + case .up: navigate(direction: .up) + case .down: navigate(direction: .down) + case .back: back() + case .open: open() + } + } + +} + + +// navigate status up/down +extension TableViewControllerNavigateableCore where Self: DataSourceProvider { + + func navigate(direction: TableViewNavigationDirection) { + if let indexPathForSelectedRow = tableView.indexPathForSelectedRow { + // navigate up/down on the current selected item + Task { + await navigateToStatus(direction: direction, indexPath: indexPathForSelectedRow) + } + } else { + // set first visible item selected + navigateToFirstVisibleStatus() + } + } + + @MainActor + private func navigateToStatus( + direction: TableViewNavigationDirection, + indexPath: IndexPath + ) async { + let row: Int = { + let index = indexPath.row + switch direction { + case .up: return index - 1 + case .down: return index + 1 + } + }() + let indexPath = IndexPath(row: row , section: indexPath.section) + guard indexPath.section >= 0, indexPath.section < tableView.numberOfSections, + indexPath.row >= 0, indexPath.row < tableView.numberOfRows(inSection: indexPath.section) + else { return } + + let scrollPosition: UITableView.ScrollPosition = overrideNavigationScrollPosition ?? Self.navigateScrollPosition(tableView: tableView, indexPath: indexPath) + tableView.selectRow(at: indexPath, animated: true, scrollPosition: scrollPosition) + } + + private func navigateToFirstVisibleStatus() { + guard var indexPathsForVisibleRows = tableView.indexPathsForVisibleRows?.sorted() else { return } + + if indexPathsForVisibleRows.first?.row != 0 { + // drop first when visible not the first cell of table + indexPathsForVisibleRows.removeFirst() + } + + guard let indexPath = indexPathsForVisibleRows.first else { return } + let scrollPosition: UITableView.ScrollPosition = overrideNavigationScrollPosition ?? Self.navigateScrollPosition(tableView: tableView, indexPath: indexPath) + tableView.selectRow(at: indexPath, animated: true, scrollPosition: scrollPosition) + } + + static func validNavigateableItem(_ item: DataSourceItem) -> Bool { + switch item { + case .status, + .notification: + return true + default: + return false + } + } + +} + +extension TableViewControllerNavigateableCore { + // check is visible and not the first and last + static func navigateScrollPosition(tableView: UITableView, indexPath: IndexPath) -> UITableView.ScrollPosition { + let middleVisibleIndexPaths = (tableView.indexPathsForVisibleRows ?? []) + .sorted() + .dropFirst() + .dropLast() + guard middleVisibleIndexPaths.contains(indexPath) else { + return .top + } + guard middleVisibleIndexPaths.count > 2 else { + return .middle + } + return .none + } + +} + +extension TableViewControllerNavigateableCore where Self: DataSourceProvider { + func open() { + guard let indexPathForSelectedRow = tableView.indexPathForSelectedRow else { return } + let source = DataSourceItem.Source(indexPath: indexPathForSelectedRow) + + Task { @MainActor in + guard let item = await item(from: source) else { return } + switch item { + case .status(let record): + await DataSourceFacade.coordinateToStatusThreadScene( + provider: self, + target: .status, + status: record + ) + case .notification(let record): + assertionFailure() + default: + assertionFailure() + } + } // end Task +// StatusProviderFacade.coordinateToStatusThreadScene(for: .primary, provider: self, indexPath: indexPathForSelectedRow) + } +} + +extension TableViewControllerNavigateableCore where Self: UIViewController { + func back() { + UserDefaults.shared.backKeyCommandPressDate = Date() + navigationController?.popViewController(animated: true) + } +} diff --git a/Mastodon/Protocol/ScrollViewContainer.swift b/Mastodon/Protocol/ScrollViewContainer.swift index ae79d0e0..c9f10ba3 100644 --- a/Mastodon/Protocol/ScrollViewContainer.swift +++ b/Mastodon/Protocol/ScrollViewContainer.swift @@ -8,12 +8,12 @@ import UIKit protocol ScrollViewContainer: UIViewController { - var scrollView: UIScrollView { get } + var scrollView: UIScrollView? { get } func scrollToTop(animated: Bool) } extension ScrollViewContainer { func scrollToTop(animated: Bool) { - scrollView.scrollRectToVisible(CGRect(origin: .zero, size: CGSize(width: 1, height: 1)), animated: animated) + scrollView?.scrollRectToVisible(CGRect(origin: .zero, size: CGSize(width: 1, height: 1)), animated: animated) } } diff --git a/Mastodon/Protocol/StatusTableViewControllerAspect.swift b/Mastodon/Protocol/StatusTableViewControllerAspect.swift deleted file mode 100644 index e0e9a8fd..00000000 --- a/Mastodon/Protocol/StatusTableViewControllerAspect.swift +++ /dev/null @@ -1,182 +0,0 @@ -//// -//// StatusTableViewControllerAspect.swift -//// Mastodon -//// -//// Created by MainasuK Cirno on 2021-4-7. -//// -// -//import UIKit -//import AVKit -//import GameController -// -//// Check List Last Updated -//// - HomeViewController: 2021/7/15 -//// - FavoriteViewController: 2021/4/30 -//// - HashtagTimelineViewController: 2021/4/30 -//// - UserTimelineViewController: 2021/4/30 -//// - ThreadViewController: 2021/4/30 -//// - SearchResultViewController: 2021/7/15 -//// * StatusTableViewControllerAspect: 2021/7/15 -// -//// (Fake) Aspect protocol to group common protocol extension implementations -//// Needs update related view controller when aspect interface changes -// -///// Status related operations aspect -///// Please check the aspect methods (Option+Click) and add hook to implement features -///// - UI -///// - Media -///// - Data Source -//protocol StatusTableViewControllerAspect: UIViewController { -// var tableView: UITableView { get } -//} -// -//// MARK: - UIViewController [A] -// -//// [A1] aspectViewWillAppear(_:) -//extension StatusTableViewControllerAspect { -// /// [UI] hook to deselect row in the transitioning for the table view -// func aspectViewWillAppear(_ animated: Bool) { -// if GCKeyboard.coalesced != nil, let backKeyCommandPressDate = UserDefaults.shared.backKeyCommandPressDate { -// guard backKeyCommandPressDate.timeIntervalSinceNow <= -0.5 else { -// // break if interval greater than 0.5s -// return -// } -// } -// tableView.deselectRow(with: transitionCoordinator, animated: animated) -// } -//} -// -//// [A2] aspectViewDidDisappear(_:) -//extension StatusTableViewControllerAspect where Self: NeedsDependency { -// /// [Media] hook to notify video service -// func aspectViewDidDisappear(_ animated: Bool) { -// context.videoPlaybackService.viewDidDisappear(from: self) -// context.audioPlaybackService.viewDidDisappear(from: self) -// } -//} -// -//// MARK: - UITableViewDelegate [B] -// -//// [B1] aspectTableView(_:estimatedHeightForRowAt:) -//extension StatusTableViewControllerAspect where Self: LoadMoreConfigurableTableViewContainer { -// /// [Data Source] hook to notify table view bottom loader -// func aspectScrollViewDidScroll(_ scrollView: UIScrollView) { -// handleScrollViewDidScroll(scrollView) -// } -//} -// -//// [B2] aspectTableView(_:estimatedHeightForRowAt:) -//extension StatusTableViewControllerAspect where Self: TableViewCellHeightCacheableContainer { -// /// [UI] hook to estimate table view cell height from cache -// func aspectTableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { -// handleTableView(tableView, estimatedHeightForRowAt: indexPath) -// } -//} -// -//// [B3] aspectTableView(_:willDisplay:forRowAt:) -//extension StatusTableViewControllerAspect where Self: StatusTableViewCellDelegate & StatusProvider { -// func aspectTableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { -// handleTableView(tableView, willDisplay: cell, forRowAt: indexPath) -// } -//} -// -//// [B4] aspectTableView(_:didEndDisplaying:forRowAt:) -//extension StatusTableViewControllerAspect where Self: StatusTableViewCellDelegate & StatusProvider { -// /// [Media] hook to notify video service -// func aspectTableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) { -// handleTableView(tableView, didEndDisplaying: cell, forRowAt: indexPath) -// } -//} -// -//extension StatusTableViewControllerAspect where Self: TableViewCellHeightCacheableContainer { -// /// [UI] hook to cache table view cell height -// func aspectTableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) { -// cacheTableView(tableView, didEndDisplaying: cell, forRowAt: indexPath) -// } -//} -// -//extension StatusTableViewControllerAspect where Self: StatusProvider & StatusTableViewCellDelegate & TableViewCellHeightCacheableContainer { -// /// [Media] hook to notify video service -// /// [UI] hook to cache table view cell height -// func aspectTableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) { -// handleTableView(tableView, didEndDisplaying: cell, forRowAt: indexPath) -// cacheTableView(tableView, didEndDisplaying: cell, forRowAt: indexPath) -// } -//} -// -//// [B5] aspectTableView(_:didSelectRowAt:) -//extension StatusTableViewControllerAspect where Self: StatusTableViewCellDelegate & StatusProvider { -// /// [UI] hook to coordinator to thread -// func aspectTableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { -// handleTableView(tableView, didSelectRowAt: indexPath) -// } -//} -// -//// [B6] aspectTableView(_:contextMenuConfigurationForRowAt:point:) -//extension StatusTableViewControllerAspect where Self: StatusTableViewCellDelegate & StatusProvider { -// // [UI] hook to display context menu for images -// func aspectTableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? { -// return handleTableView(tableView, contextMenuConfigurationForRowAt: indexPath, point: point) -// } -//} -// -//// [B7] aspectTableView(_:contextMenuConfigurationForRowAt:point:) -//extension StatusTableViewControllerAspect where Self: StatusTableViewCellDelegate & StatusProvider { -// // [UI] hook to configure context menu for images -// func aspectTableView(_ tableView: UITableView, previewForHighlightingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? { -// return handleTableView(tableView, previewForHighlightingContextMenuWithConfiguration: configuration) -// } -//} -// -//// [B8] aspectTableView(_:previewForDismissingContextMenuWithConfiguration:) -//extension StatusTableViewControllerAspect where Self: StatusTableViewCellDelegate & StatusProvider { -// // [UI] hook to configure context menu for images -// func aspectTableView(_ tableView: UITableView, previewForDismissingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? { -// return handleTableView(tableView, previewForDismissingContextMenuWithConfiguration: configuration) -// } -//} -// -//// [B9] aspectTableView(_:willPerformPreviewActionForMenuWith:animator:) -//extension StatusTableViewControllerAspect where Self: StatusTableViewCellDelegate & StatusProvider { -// // [UI] hook to configure context menu preview action -// func aspectTableView(_ tableView: UITableView, willPerformPreviewActionForMenuWith configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionCommitAnimating) { -// handleTableView(tableView, willPerformPreviewActionForMenuWith: configuration, animator: animator) -// } -//} -// -//// MARK: - UITableViewDataSourcePrefetching [C] -// -//// [C1] aspectTableView(:prefetchRowsAt) -//extension StatusTableViewControllerAspect where Self: UITableViewDataSourcePrefetching & StatusTableViewCellDelegate & StatusProvider { -// /// [Data Source] hook to prefetch status -// func aspectTableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) { -// handleTableView(tableView, prefetchRowsAt: indexPaths) -// } -//} -// -//// [C2] aspectTableView(:prefetchRowsAt) -//extension StatusTableViewControllerAspect where Self: UITableViewDataSourcePrefetching & StatusTableViewCellDelegate & StatusProvider { -// /// [Data Source] hook to cancel prefetch status -// func aspectTableView(_ tableView: UITableView, cancelPrefetchingForRowsAt indexPaths: [IndexPath]) { -// handleTableView(tableView, cancelPrefetchingForRowsAt: indexPaths) -// } -//} -// -//// MARK: - AVPlayerViewControllerDelegate & NeedsDependency [D] -// -//// [D1] aspectPlayerViewController(_:willBeginFullScreenPresentationWithAnimationCoordinator:) -//extension StatusTableViewControllerAspect where Self: AVPlayerViewControllerDelegate & NeedsDependency { -// /// [Media] hook to mark transitioning to video service -// func aspectPlayerViewController(_ playerViewController: AVPlayerViewController, willBeginFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) { -// handlePlayerViewController(playerViewController, willBeginFullScreenPresentationWithAnimationCoordinator: coordinator) -// } -//} -// -//// [D2] aspectPlayerViewController(_:willEndFullScreenPresentationWithAnimationCoordinator:) -//extension StatusTableViewControllerAspect where Self: AVPlayerViewControllerDelegate & NeedsDependency { -// /// [Media] hook to mark transitioning to video service -// func aspectPlayerViewController(_ playerViewController: AVPlayerViewController, willEndFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) { -// handlePlayerViewController(playerViewController, willEndFullScreenPresentationWithAnimationCoordinator: coordinator) -// } -//} -// diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/black.imageset/Contents.json b/Mastodon/Resources/Preview Assets.xcassets/Athens.imageset/Contents.json similarity index 76% rename from MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/black.imageset/Contents.json rename to Mastodon/Resources/Preview Assets.xcassets/Athens.imageset/Contents.json index 23975c38..786051dd 100644 --- a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/black.imageset/Contents.json +++ b/Mastodon/Resources/Preview Assets.xcassets/Athens.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "Home Black.png", + "filename" : "IMG_1010.jpg", "idiom" : "universal" } ], diff --git a/Mastodon/Resources/Preview Assets.xcassets/Athens.imageset/IMG_1010.jpg b/Mastodon/Resources/Preview Assets.xcassets/Athens.imageset/IMG_1010.jpg new file mode 100644 index 00000000..0fce96bd Binary files /dev/null and b/Mastodon/Resources/Preview Assets.xcassets/Athens.imageset/IMG_1010.jpg differ diff --git a/Mastodon/Resources/ku-TR.lproj/InfoPlist.strings b/Mastodon/Resources/ku-TR.lproj/InfoPlist.strings deleted file mode 100644 index 669ecfac..00000000 --- a/Mastodon/Resources/ku-TR.lproj/InfoPlist.strings +++ /dev/null @@ -1,4 +0,0 @@ -"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"; \ No newline at end of file diff --git a/Mastodon/Resources/ku.lproj/InfoPlist.strings b/Mastodon/Resources/ku.lproj/InfoPlist.strings new file mode 100644 index 00000000..71086557 --- /dev/null +++ b/Mastodon/Resources/ku.lproj/InfoPlist.strings @@ -0,0 +1,4 @@ +"NSCameraUsageDescription" = "Used to take photo for post status"; +"NSPhotoLibraryAddUsageDescription" = "Used to save photo into the Photo Library"; +"NewPostShortcutItemTitle" = "New Post"; +"SearchShortcutItemTitle" = "Search"; \ No newline at end of file diff --git a/Mastodon/Scene/Account/View/BadgeButton.swift b/Mastodon/Scene/Account/View/BadgeButton.swift index a0101ef5..785053be 100644 --- a/Mastodon/Scene/Account/View/BadgeButton.swift +++ b/Mastodon/Scene/Account/View/BadgeButton.swift @@ -26,10 +26,10 @@ final class BadgeButton: UIButton { extension BadgeButton { private func _init() { titleLabel?.font = UIFontMetrics(forTextStyle: .caption1).scaledFont(for: .systemFont(ofSize: 13, weight: .medium)) - setBackgroundColor(Asset.Colors.badgeBackground.color, for: .normal) - setTitleColor(.white, for: .normal) + setBackgroundColor(.systemBackground, for: .normal) + setTitleColor(.label, for: .normal) - contentEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5) + contentEdgeInsets = UIEdgeInsets(top: 6, left: 6, bottom: 6, right: 6) } override func layoutSubviews() { diff --git a/Mastodon/Scene/Compose/ComposeViewController.swift b/Mastodon/Scene/Compose/ComposeViewController.swift index 04687ca5..f5dfc8ba 100644 --- a/Mastodon/Scene/Compose/ComposeViewController.swift +++ b/Mastodon/Scene/Compose/ComposeViewController.swift @@ -381,7 +381,7 @@ extension ComposeViewController { // bind publish bar button state viewModel.$isPublishBarButtonItemEnabled .receive(on: DispatchQueue.main) - .assign(to: \.isEnabled, on: publishBarButtonItem) + .assign(to: \.isEnabled, on: publishButton) .store(in: &disposeBag) // bind media button toolbar state @@ -669,21 +669,30 @@ extension ComposeViewController { } private func setupBackgroundColor(theme: Theme) { - view.backgroundColor = theme.systemElevatedBackgroundColor - tableView.backgroundColor = theme.systemElevatedBackgroundColor + let backgroundColor = UIColor(dynamicProvider: { traitCollection in + switch traitCollection.userInterfaceStyle { + case .light: + return .systemBackground + default: + return theme.systemElevatedBackgroundColor + } + }) + view.backgroundColor = backgroundColor + tableView.backgroundColor = backgroundColor composeToolbarBackgroundView.backgroundColor = theme.composeToolbarBackgroundColor } // keyboard shortcutBar private func setupInputAssistantItem(item: UITextInputAssistantItem) { - let groups = [UIBarButtonItemGroup(barButtonItems: [ + let barButtonItems = [ composeToolbarView.mediaBarButtonItem, composeToolbarView.pollBarButtonItem, composeToolbarView.contentWarningBarButtonItem, composeToolbarView.visibilityBarButtonItem, - ], representativeItem: nil)] + ] + let group = UIBarButtonItemGroup(barButtonItems: barButtonItems, representativeItem: nil) - item.trailingBarButtonGroups = groups + item.trailingBarButtonGroups = [group] } private func configureToolbarDisplay(keyboardHasShortcutBar: Bool) { @@ -761,15 +770,6 @@ extension ComposeViewController: UITextViewDelegate { setupInputAssistantItem(item: textView.inputAssistantItem) return true } - - func textViewDidBeginEditing(_ textView: UITextView) { - switch textView { - case textEditorView.textView: - setupInputAssistantItem(item: textView.inputAssistantItem) - default: - assertionFailure() - } - } func textViewDidChange(_ textView: UITextView) { switch textView { @@ -915,14 +915,25 @@ extension ComposeViewController: UITextViewDelegate { // MARK: - ComposeToolbarViewDelegate extension ComposeViewController: ComposeToolbarViewDelegate { - func composeToolbarView(_ composeToolbarView: ComposeToolbarView, cameraButtonDidPressed sender: Any, mediaSelectionType type: ComposeToolbarView.MediaSelectionType) { + func composeToolbarView(_ composeToolbarView: ComposeToolbarView, mediaButtonDidPressed sender: Any, mediaSelectionType type: ComposeToolbarView.MediaSelectionType) { switch type { case .photoLibrary: present(photoLibraryPicker, animated: true, completion: nil) case .camera: present(imagePickerController, animated: true, completion: nil) case .browse: + #if SNAPSHOT + guard let image = UIImage(named: "Athens") else { return } + + let attachmentService = MastodonAttachmentService( + context: context, + image: image, + initialAuthenticationBox: viewModel.authenticationBox + ) + viewModel.attachmentServices = viewModel.attachmentServices + [attachmentService] + #else present(documentPickerController, animated: true, completion: nil) + #endif } } diff --git a/Mastodon/Scene/Compose/TableViewCell/ComposeStatusContentTableViewCell.swift b/Mastodon/Scene/Compose/TableViewCell/ComposeStatusContentTableViewCell.swift index 34f34f02..4c3d3716 100644 --- a/Mastodon/Scene/Compose/TableViewCell/ComposeStatusContentTableViewCell.swift +++ b/Mastodon/Scene/Compose/TableViewCell/ComposeStatusContentTableViewCell.swift @@ -131,14 +131,9 @@ extension ComposeStatusContentTableViewCell { metaText.textView.leadingAnchor.constraint(equalTo: textEditorViewContainerView.layoutMarginsGuide.leadingAnchor), metaText.textView.trailingAnchor.constraint(equalTo: textEditorViewContainerView.layoutMarginsGuide.trailingAnchor), metaText.textView.bottomAnchor.constraint(equalTo: textEditorViewContainerView.bottomAnchor), - metaText.textView.heightAnchor.constraint(greaterThanOrEqualToConstant: 88).priority(.defaultHigh), + metaText.textView.heightAnchor.constraint(greaterThanOrEqualToConstant: 64).priority(.defaultHigh), ]) statusContentWarningEditorView.textView.delegate = self - -// statusView.nameTrialingDotLabel.isHidden = true -// statusView.dateLabel.isHidden = true -// statusContentWarningEditorView.isHidden = true -// statusView.statusContainerStackView.isHidden = true } } @@ -166,7 +161,10 @@ extension ComposeStatusContentTableViewCell: UITextViewDelegate { logger.debug("\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): text: \(textView.text ?? "<nil>")") guard textView === statusContentWarningEditorView.textView else { return } // replace line break with space - textView.text = textView.text.replacingOccurrences(of: "\n", with: " ") + // needs check input state to prevent break the IME + if textView.markedTextRange == nil { + textView.text = textView.text.replacingOccurrences(of: "\n", with: " ") + } contentWarningContent.send(textView.text) } diff --git a/Mastodon/Scene/Compose/View/ComposeToolbarView.swift b/Mastodon/Scene/Compose/View/ComposeToolbarView.swift index 66bde158..4ed84be7 100644 --- a/Mastodon/Scene/Compose/View/ComposeToolbarView.swift +++ b/Mastodon/Scene/Compose/View/ComposeToolbarView.swift @@ -13,7 +13,7 @@ import MastodonAsset import MastodonLocalization protocol ComposeToolbarViewDelegate: AnyObject { - func composeToolbarView(_ composeToolbarView: ComposeToolbarView, cameraButtonDidPressed sender: Any, mediaSelectionType type: ComposeToolbarView.MediaSelectionType) + func composeToolbarView(_ composeToolbarView: ComposeToolbarView, mediaButtonDidPressed sender: Any, mediaSelectionType type: ComposeToolbarView.MediaSelectionType) func composeToolbarView(_ composeToolbarView: ComposeToolbarView, pollButtonDidPressed sender: Any) func composeToolbarView(_ composeToolbarView: ComposeToolbarView, emojiButtonDidPressed sender: Any) func composeToolbarView(_ composeToolbarView: ComposeToolbarView, contentWarningButtonDidPressed sender: Any) @@ -304,21 +304,21 @@ extension ComposeToolbarView { let photoLibraryAction = UIAction(title: L10n.Scene.Compose.MediaSelection.photoLibrary, image: UIImage(systemName: "rectangle.on.rectangle"), identifier: nil, discoverabilityTitle: nil, attributes: [], state: .off) { [weak self] _ in guard let self = self else { return } os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: mediaSelectionType: .photoLibrary", ((#file as NSString).lastPathComponent), #line, #function) - self.delegate?.composeToolbarView(self, cameraButtonDidPressed: self.mediaButton, mediaSelectionType: .photoLibrary) + self.delegate?.composeToolbarView(self, mediaButtonDidPressed: self.mediaButton, mediaSelectionType: .photoLibrary) } children.append(photoLibraryAction) if UIImagePickerController.isSourceTypeAvailable(.camera) { let cameraAction = UIAction(title: L10n.Scene.Compose.MediaSelection.camera, image: UIImage(systemName: "camera"), identifier: nil, discoverabilityTitle: nil, attributes: [], state: .off, handler: { [weak self] _ in guard let self = self else { return } os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: mediaSelectionType: .camera", ((#file as NSString).lastPathComponent), #line, #function) - self.delegate?.composeToolbarView(self, cameraButtonDidPressed: self.mediaButton, mediaSelectionType: .camera) + self.delegate?.composeToolbarView(self, mediaButtonDidPressed: self.mediaButton, mediaSelectionType: .camera) }) children.append(cameraAction) } let browseAction = UIAction(title: L10n.Scene.Compose.MediaSelection.browse, image: UIImage(systemName: "ellipsis"), identifier: nil, discoverabilityTitle: nil, attributes: [], state: .off) { [weak self] _ in guard let self = self else { return } os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: mediaSelectionType: .browse", ((#file as NSString).lastPathComponent), #line, #function) - self.delegate?.composeToolbarView(self, cameraButtonDidPressed: self.mediaButton, mediaSelectionType: .browse) + self.delegate?.composeToolbarView(self, mediaButtonDidPressed: self.mediaButton, mediaSelectionType: .browse) } children.append(browseAction) diff --git a/Mastodon/Scene/HashtagTimeline/HashtagTimelineViewModel+Diffable.swift b/Mastodon/Scene/HashtagTimeline/HashtagTimelineViewModel+Diffable.swift index 43add2d2..c71d195c 100644 --- a/Mastodon/Scene/HashtagTimeline/HashtagTimelineViewModel+Diffable.swift +++ b/Mastodon/Scene/HashtagTimeline/HashtagTimelineViewModel+Diffable.swift @@ -21,7 +21,9 @@ extension HashtagTimelineViewModel { context: context, configuration: StatusSection.Configuration( statusTableViewCellDelegate: statusTableViewCellDelegate, - timelineMiddleLoaderTableViewCellDelegate: nil + timelineMiddleLoaderTableViewCellDelegate: nil, + filterContext: .none, + activeFilters: nil ) ) diff --git a/Mastodon/Scene/HomeTimeline/HomeTimelineViewController+DebugAction.swift b/Mastodon/Scene/HomeTimeline/HomeTimelineViewController+DebugAction.swift index d4783045..8b1d390f 100644 --- a/Mastodon/Scene/HomeTimeline/HomeTimelineViewController+DebugAction.swift +++ b/Mastodon/Scene/HomeTimeline/HomeTimelineViewController+DebugAction.swift @@ -6,7 +6,7 @@ // -#if DEBUG +#if DEBUG || SNAPSHOT import os.log import UIKit import CoreData diff --git a/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift b/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift index 2af35707..7b7f35e5 100644 --- a/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift +++ b/Mastodon/Scene/HomeTimeline/HomeTimelineViewController.swift @@ -51,6 +51,7 @@ final class HomeTimelineViewController: UIViewController, NeedsDependency, Media let barButtonItem = UIBarButtonItem() barButtonItem.tintColor = ThemeService.tintColor barButtonItem.image = UIImage(systemName: "gear")?.withRenderingMode(.alwaysTemplate) + barButtonItem.accessibilityLabel = L10n.Common.Controls.Actions.settings return barButtonItem }() @@ -58,6 +59,7 @@ final class HomeTimelineViewController: UIViewController, NeedsDependency, Media let barButtonItem = UIBarButtonItem() barButtonItem.tintColor = ThemeService.tintColor barButtonItem.image = UIImage(systemName: "square.and.pencil")?.withRenderingMode(.alwaysTemplate) + barButtonItem.accessibilityLabel = L10n.Common.Controls.Actions.compose return barButtonItem }() @@ -125,6 +127,11 @@ extension HomeTimelineViewController { settingBarButtonItem.action = #selector(HomeTimelineViewController.settingBarButtonItemPressed(_:)) #endif + #if SNAPSHOT + titleView.logoButton.menu = self.debugMenu + titleView.button.menu = self.debugMenu + #endif + viewModel.$displayComposeBarButtonItem .receive(on: DispatchQueue.main) .sink { [weak self] displayComposeBarButtonItem in @@ -183,7 +190,6 @@ extension HomeTimelineViewController { ]) viewModel.tableView = tableView - viewModel.contentOffsetAdjustableTimelineViewControllerDelegate = self tableView.delegate = self viewModel.setupDiffableDataSource( tableView: tableView, @@ -541,26 +547,6 @@ extension HomeTimelineViewController: UITableViewDelegate, AutoGenerateTableView } // sourcery:end - -// func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { -// aspectTableView(tableView, estimatedHeightForRowAt: indexPath) -// } -// -// func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { -// aspectTableView(tableView, willDisplay: cell, forRowAt: indexPath) -// } -// -// func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) { -// aspectTableView(tableView, didEndDisplaying: cell, forRowAt: indexPath) -// } - -} - -// MARK: - ContentOffsetAdjustableTimelineViewControllerDelegate -extension HomeTimelineViewController: ContentOffsetAdjustableTimelineViewControllerDelegate { - func navigationBar() -> UINavigationBar? { - return navigationController?.navigationBar - } } // MARK: - TimelineMiddleLoaderTableViewCellDelegate @@ -579,9 +565,13 @@ extension HomeTimelineViewController: TimelineMiddleLoaderTableViewCellDelegate // MARK: - ScrollViewContainer extension HomeTimelineViewController: ScrollViewContainer { - var scrollView: UIScrollView { return tableView } + var scrollView: UIScrollView? { return tableView } func scrollToTop(animated: Bool) { + guard let scrollView = scrollView else { + return + } + if scrollView.contentOffset.y < scrollView.frame.height, viewModel.loadLatestStateMachine.canEnterState(HomeTimelineViewModel.LoadLatestState.Loading.self), (scrollView.contentOffset.y + scrollView.adjustedContentInset.top) == 0.0, @@ -637,19 +627,19 @@ extension HomeTimelineViewController: HomeTimelineNavigationBarTitleViewDelegate } } -//extension HomeTimelineViewController { -// override var keyCommands: [UIKeyCommand]? { -// return navigationKeyCommands + statusNavigationKeyCommands -// } -//} -// -//// MARK: - StatusTableViewControllerNavigateable -//extension HomeTimelineViewController: StatusTableViewControllerNavigateable { -// @objc func navigateKeyCommandHandlerRelay(_ sender: UIKeyCommand) { -// navigateKeyCommandHandler(sender) -// } -// -// @objc func statusKeyCommandHandlerRelay(_ sender: UIKeyCommand) { -// statusKeyCommandHandler(sender) -// } -//} +extension HomeTimelineViewController { + override var keyCommands: [UIKeyCommand]? { + return navigationKeyCommands + statusNavigationKeyCommands + } +} + +// MARK: - StatusTableViewControllerNavigateable +extension HomeTimelineViewController: StatusTableViewControllerNavigateable { + @objc func navigateKeyCommandHandlerRelay(_ sender: UIKeyCommand) { + navigateKeyCommandHandler(sender) + } + + @objc func statusKeyCommandHandlerRelay(_ sender: UIKeyCommand) { + statusKeyCommandHandler(sender) + } +} diff --git a/Mastodon/Scene/HomeTimeline/HomeTimelineViewModel+Diffable.swift b/Mastodon/Scene/HomeTimeline/HomeTimelineViewModel+Diffable.swift index 67f9e5b5..756a4b60 100644 --- a/Mastodon/Scene/HomeTimeline/HomeTimelineViewModel+Diffable.swift +++ b/Mastodon/Scene/HomeTimeline/HomeTimelineViewModel+Diffable.swift @@ -22,7 +22,9 @@ extension HomeTimelineViewModel { context: context, configuration: StatusSection.Configuration( statusTableViewCellDelegate: statusTableViewCellDelegate, - timelineMiddleLoaderTableViewCellDelegate: timelineMiddleLoaderTableViewCellDelegate + timelineMiddleLoaderTableViewCellDelegate: timelineMiddleLoaderTableViewCellDelegate, + filterContext: .home, + activeFilters: context.statusFilterService.$activeFilters ) ) diff --git a/Mastodon/Scene/HomeTimeline/HomeTimelineViewModel.swift b/Mastodon/Scene/HomeTimeline/HomeTimelineViewModel.swift index 488964ed..b2c280fb 100644 --- a/Mastodon/Scene/HomeTimeline/HomeTimelineViewModel.swift +++ b/Mastodon/Scene/HomeTimeline/HomeTimelineViewModel.swift @@ -35,7 +35,6 @@ final class HomeTimelineViewModel: NSObject { @Published var displaySettingBarButtonItem = true @Published var displayComposeBarButtonItem = true - weak var contentOffsetAdjustableTimelineViewControllerDelegate: ContentOffsetAdjustableTimelineViewControllerDelegate? weak var tableView: UITableView? weak var timelineMiddleLoaderTableViewCellDelegate: TimelineMiddleLoaderTableViewCellDelegate? diff --git a/Mastodon/Scene/HomeTimeline/View/HomeTimelineNavigationBarTitleView.swift b/Mastodon/Scene/HomeTimeline/View/HomeTimelineNavigationBarTitleView.swift index a1940640..e67ee010 100644 --- a/Mastodon/Scene/HomeTimeline/View/HomeTimelineNavigationBarTitleView.swift +++ b/Mastodon/Scene/HomeTimeline/View/HomeTimelineNavigationBarTitleView.swift @@ -65,6 +65,9 @@ extension HomeTimelineNavigationBarTitleView { configure(state: .logo) logoButton.addTarget(self, action: #selector(HomeTimelineNavigationBarTitleView.logoButtonDidPressed(_:)), for: .touchUpInside) button.addTarget(self, action: #selector(HomeTimelineNavigationBarTitleView.buttonDidPressed(_:)), for: .touchUpInside) + + logoButton.accessibilityIdentifier = "TitleButton" + button.accessibilityIdentifier = "TitleButton" } } diff --git a/Mastodon/Scene/MediaPreview/MediaPreviewViewController.swift b/Mastodon/Scene/MediaPreview/MediaPreviewViewController.swift index b8355c3a..ae55134c 100644 --- a/Mastodon/Scene/MediaPreview/MediaPreviewViewController.swift +++ b/Mastodon/Scene/MediaPreview/MediaPreviewViewController.swift @@ -222,7 +222,11 @@ extension MediaPreviewViewController: PageboyViewControllerDelegate { extension MediaPreviewViewController: MediaPreviewImageViewControllerDelegate { func mediaPreviewImageViewController(_ viewController: MediaPreviewImageViewController, tapGestureRecognizerDidTrigger tapGestureRecognizer: UITapGestureRecognizer) { - // do nothing + let location = tapGestureRecognizer.location(in: viewController.previewImageView.imageView) + let isContainsTap = viewController.previewImageView.imageView.frame.contains(location) + + guard !isContainsTap else { return } + dismiss(animated: true, completion: nil) } func mediaPreviewImageViewController(_ viewController: MediaPreviewImageViewController, longPressGestureRecognizerDidTrigger longPressGestureRecognizer: UILongPressGestureRecognizer) { diff --git a/Mastodon/Scene/Notification/Cell/NotificationTableViewCell+ViewModel.swift b/Mastodon/Scene/Notification/Cell/NotificationTableViewCell+ViewModel.swift index be230391..7b994076 100644 --- a/Mastodon/Scene/Notification/Cell/NotificationTableViewCell+ViewModel.swift +++ b/Mastodon/Scene/Notification/Cell/NotificationTableViewCell+ViewModel.swift @@ -36,7 +36,7 @@ extension NotificationTableViewCell { logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): did layout for new cell") notificationView.statusView.frame.size.width = tableView.frame.width - containerViewHorizontalMargin - notificationView.quoteStatusView.frame.size.width = tableView.frame.width - StatusView.containerLayoutMargin.left - StatusView.containerLayoutMargin.right - containerViewHorizontalMargin + notificationView.quoteStatusView.frame.size.width = tableView.frame.width - containerViewHorizontalMargin // the as same width as statusView } switch viewModel.value { diff --git a/Mastodon/Scene/Notification/Cell/NotificationTableViewCell.swift b/Mastodon/Scene/Notification/Cell/NotificationTableViewCell.swift index 17b1b9a1..bbdb2afa 100644 --- a/Mastodon/Scene/Notification/Cell/NotificationTableViewCell.swift +++ b/Mastodon/Scene/Notification/Cell/NotificationTableViewCell.swift @@ -16,6 +16,7 @@ final class NotificationTableViewCell: UITableViewCell { weak var delegate: NotificationTableViewCellDelegate? var disposeBag = Set<AnyCancellable>() + private var _disposeBag = Set<AnyCancellable>() let notificationView = NotificationView() @@ -49,13 +50,13 @@ extension NotificationTableViewCell { notificationView.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(notificationView) setupContainerViewMarginConstraints() - updateContainerViewMarginConstraints() NSLayoutConstraint.activate([ notificationView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 16), containerViewLeadingLayoutConstraint, containerViewTrailingLayoutConstraint, contentView.bottomAnchor.constraint(equalTo: notificationView.bottomAnchor), ]) + updateContainerViewMarginConstraints() separatorLine.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(separatorLine) @@ -66,9 +67,23 @@ extension NotificationTableViewCell { separatorLine.heightAnchor.constraint(equalToConstant: UIView.separatorLineHeight(of: contentView)).priority(.required - 1), ]) + notificationView.quoteBackgroundView.backgroundColor = ThemeService.shared.currentTheme.value.secondarySystemBackgroundColor + ThemeService.shared.currentTheme + .sink { [weak self] theme in + guard let self = self else { return } + self.notificationView.quoteBackgroundView.backgroundColor = theme.secondarySystemBackgroundColor + } + .store(in: &_disposeBag) + notificationView.delegate = self } + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + + updateContainerViewMarginConstraints() + } + } // MARK: - AdaptiveContainerMarginTableViewCell diff --git a/Mastodon/Scene/Notification/Cell/NotificationTableViewCellDelegate.swift b/Mastodon/Scene/Notification/Cell/NotificationTableViewCellDelegate.swift index 07bc5ff9..d13ce719 100644 --- a/Mastodon/Scene/Notification/Cell/NotificationTableViewCellDelegate.swift +++ b/Mastodon/Scene/Notification/Cell/NotificationTableViewCellDelegate.swift @@ -27,10 +27,12 @@ protocol NotificationTableViewCellDelegate: AnyObject, AutoGenerateProtocolDeleg func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, menuButton button: UIButton, didSelectAction action: MastodonMenu.Action) func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, statusView: StatusView, metaText: MetaText, didSelectMeta meta: Meta) func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, statusView: StatusView, spoilerOverlayViewDidPressed overlayView: SpoilerOverlayView) + func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, statusView: StatusView, mediaGridContainerView: MediaGridContainerView, mediaView: MediaView, didSelectMediaViewAt index: Int) func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, statusView: StatusView, actionToolbarContainer: ActionToolbarContainer, buttonDidPressed button: UIButton, action: ActionToolbarContainer.Action) func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, quoteStatusView: StatusView, authorAvatarButtonDidPressed button: AvatarButton) func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, quoteStatusView: StatusView, metaText: MetaText, didSelectMeta meta: Meta) func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, quoteStatusView: StatusView, spoilerOverlayViewDidPressed overlayView: SpoilerOverlayView) + func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, quoteStatusView: StatusView, mediaGridContainerView: MediaGridContainerView, mediaView: MediaView, didSelectMediaViewAt index: Int) func tableViewCell(_ cell: UITableViewCell, notificationView: NotificationView, accessibilityActivate: Void) // sourcery:end } @@ -55,6 +57,10 @@ extension NotificationViewDelegate where Self: NotificationViewContainerTableVie delegate?.tableViewCell(self, notificationView: notificationView, statusView: statusView, spoilerOverlayViewDidPressed: overlayView) } + func notificationView(_ notificationView: NotificationView, statusView: StatusView, mediaGridContainerView: MediaGridContainerView, mediaView: MediaView, didSelectMediaViewAt index: Int) { + delegate?.tableViewCell(self, notificationView: notificationView, statusView: statusView, mediaGridContainerView: mediaGridContainerView, mediaView: mediaView, didSelectMediaViewAt: index) + } + func notificationView(_ notificationView: NotificationView, statusView: StatusView, actionToolbarContainer: ActionToolbarContainer, buttonDidPressed button: UIButton, action: ActionToolbarContainer.Action) { delegate?.tableViewCell(self, notificationView: notificationView, statusView: statusView, actionToolbarContainer: actionToolbarContainer, buttonDidPressed: button, action: action) } @@ -71,6 +77,10 @@ extension NotificationViewDelegate where Self: NotificationViewContainerTableVie delegate?.tableViewCell(self, notificationView: notificationView, quoteStatusView: quoteStatusView, spoilerOverlayViewDidPressed: overlayView) } + func notificationView(_ notificationView: NotificationView, quoteStatusView: StatusView, mediaGridContainerView: MediaGridContainerView, mediaView: MediaView, didSelectMediaViewAt index: Int) { + delegate?.tableViewCell(self, notificationView: notificationView, quoteStatusView: quoteStatusView, mediaGridContainerView: mediaGridContainerView, mediaView: mediaView, didSelectMediaViewAt: index) + } + func notificationView(_ notificationView: NotificationView, accessibilityActivate: Void) { delegate?.tableViewCell(self, notificationView: notificationView, accessibilityActivate: accessibilityActivate) } diff --git a/Mastodon/Scene/Notification/NotificationTimeline/NotificationTimelineViewController.swift b/Mastodon/Scene/Notification/NotificationTimeline/NotificationTimelineViewController.swift index 301b2f37..bdb4d05c 100644 --- a/Mastodon/Scene/Notification/NotificationTimeline/NotificationTimelineViewController.swift +++ b/Mastodon/Scene/Notification/NotificationTimeline/NotificationTimelineViewController.swift @@ -9,6 +9,7 @@ import os.log import UIKit import Combine import CoreDataStack +import MastodonLocalization final class NotificationTimelineViewController: UIViewController, NeedsDependency, MediaPreviewableViewController { @@ -176,3 +177,130 @@ extension NotificationTimelineViewController: UITableViewDelegate, AutoGenerateT // MARK: - NotificationTableViewCellDelegate extension NotificationTimelineViewController: NotificationTableViewCellDelegate { } + +// MARK: - ScrollViewContainer +extension NotificationTimelineViewController: ScrollViewContainer { + + var scrollView: UIScrollView? { tableView } + +} + +extension NotificationTimelineViewController { + override var keyCommands: [UIKeyCommand]? { + return navigationKeyCommands + } +} + +extension NotificationTimelineViewController: TableViewControllerNavigateable { + + func navigate(direction: TableViewNavigationDirection) { + if let indexPathForSelectedRow = tableView.indexPathForSelectedRow { + // navigate up/down on the current selected item + navigateToStatus(direction: direction, indexPath: indexPathForSelectedRow) + } else { + // set first visible item selected + navigateToFirstVisibleStatus() + } + } + + private func navigateToStatus(direction: TableViewNavigationDirection, indexPath: IndexPath) { + guard let diffableDataSource = viewModel.diffableDataSource else { return } + let items = diffableDataSource.snapshot().itemIdentifiers + guard let selectedItem = diffableDataSource.itemIdentifier(for: indexPath), + let selectedItemIndex = items.firstIndex(of: selectedItem) else { + return + } + + let _navigateToItem: NotificationItem? = { + var index = selectedItemIndex + while 0..<items.count ~= index { + index = { + switch direction { + case .up: return index - 1 + case .down: return index + 1 + } + }() + guard 0..<items.count ~= index else { return nil } + let item = items[index] + + guard Self.validNavigateableItem(item) else { continue } + return item + } + return nil + }() + + guard let item = _navigateToItem, let indexPath = diffableDataSource.indexPath(for: item) else { return } + let scrollPosition: UITableView.ScrollPosition = overrideNavigationScrollPosition ?? Self.navigateScrollPosition(tableView: tableView, indexPath: indexPath) + tableView.selectRow(at: indexPath, animated: true, scrollPosition: scrollPosition) + } + + private func navigateToFirstVisibleStatus() { + guard let indexPathsForVisibleRows = tableView.indexPathsForVisibleRows else { return } + guard let diffableDataSource = viewModel.diffableDataSource else { return } + + var visibleItems: [NotificationItem] = indexPathsForVisibleRows.sorted().compactMap { indexPath in + guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return nil } + guard Self.validNavigateableItem(item) else { return nil } + return item + } + if indexPathsForVisibleRows.first?.row != 0, visibleItems.count > 1 { + // drop first when visible not the first cell of table + visibleItems.removeFirst() + } + guard let item = visibleItems.first, let indexPath = diffableDataSource.indexPath(for: item) else { return } + let scrollPosition: UITableView.ScrollPosition = overrideNavigationScrollPosition ?? Self.navigateScrollPosition(tableView: tableView, indexPath: indexPath) + tableView.selectRow(at: indexPath, animated: true, scrollPosition: scrollPosition) + } + + static func validNavigateableItem(_ item: NotificationItem) -> Bool { + switch item { + case .feed: + return true + default: + return false + } + } + + func open() { + guard let indexPathForSelectedRow = tableView.indexPathForSelectedRow else { return } + guard let diffableDataSource = viewModel.diffableDataSource else { return } + guard let item = diffableDataSource.itemIdentifier(for: indexPathForSelectedRow) else { return } + + Task { @MainActor in + switch item { + case .feed(let record): + guard let feed = record.object(in: self.context.managedObjectContext) else { return } + guard let notification = feed.notification else { return } + + if let stauts = notification.status { + let threadViewModel = ThreadViewModel( + context: self.context, + optionalRoot: .root(context: .init(status: .init(objectID: stauts.objectID))) + ) + self.coordinator.present( + scene: .thread(viewModel: threadViewModel), + from: self, + transition: .show + ) + } else { + let profileViewModel = ProfileViewModel( + context: self.context, + optionalMastodonUser: notification.account + ) + self.coordinator.present( + scene: .profile(viewModel: profileViewModel), + from: self, + transition: .show + ) + } + default: + break + } + } // end Task + } + + func navigateKeyCommandHandlerRelay(_ sender: UIKeyCommand) { + navigateKeyCommandHandler(sender) + } + +} diff --git a/Mastodon/Scene/Notification/NotificationTimeline/NotificationTimelineViewModel+Diffable.swift b/Mastodon/Scene/Notification/NotificationTimeline/NotificationTimelineViewModel+Diffable.swift index 1476ef2e..b32eae76 100644 --- a/Mastodon/Scene/Notification/NotificationTimeline/NotificationTimelineViewModel+Diffable.swift +++ b/Mastodon/Scene/Notification/NotificationTimeline/NotificationTimelineViewModel+Diffable.swift @@ -20,7 +20,9 @@ extension NotificationTimelineViewModel { tableView: tableView, context: context, configuration: NotificationSection.Configuration( - notificationTableViewCellDelegate: notificationTableViewCellDelegate + notificationTableViewCellDelegate: notificationTableViewCellDelegate, + filterContext: .notifications, + activeFilters: context.statusFilterService.$activeFilters ) ) diff --git a/Mastodon/Scene/Notification/NotificationTimeline/NotificationTimelineViewModel.swift b/Mastodon/Scene/Notification/NotificationTimeline/NotificationTimelineViewModel.swift index eb24f3a3..ee2ac8a0 100644 --- a/Mastodon/Scene/Notification/NotificationTimeline/NotificationTimelineViewModel.swift +++ b/Mastodon/Scene/Notification/NotificationTimeline/NotificationTimelineViewModel.swift @@ -148,7 +148,7 @@ extension NotificationTimelineViewModel { guard let authenticationBox = context.authenticationService.activeMastodonAuthenticationBox.value else { return } isLoadingLatest = true - defer{ isLoadingLatest = false } + defer { isLoadingLatest = false } do { _ = try await context.apiService.notifications( diff --git a/Mastodon/Scene/Notification/NotificationViewController.swift b/Mastodon/Scene/Notification/NotificationViewController.swift index aa49680a..dd4d9704 100644 --- a/Mastodon/Scene/Notification/NotificationViewController.swift +++ b/Mastodon/Scene/Notification/NotificationViewController.swift @@ -93,96 +93,6 @@ extension NotificationViewController { } } .store(in: &disposeBag) - -// segmentControl.translatesAutoresizingMaskIntoConstraints = false -// navigationItem.titleView = segmentControl -// NSLayoutConstraint.activate([ -// segmentControl.widthAnchor.constraint(equalToConstant: 287) -// ]) -// segmentControl.addTarget(self, action: #selector(NotificationViewController.segmentedControlValueChanged(_:)), for: .valueChanged) -// -// tableView.translatesAutoresizingMaskIntoConstraints = false -// view.addSubview(tableView) -// NSLayoutConstraint.activate([ -// tableView.topAnchor.constraint(equalTo: view.topAnchor), -// tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor), -// tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor), -// tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), -// ]) -// -// tableView.refreshControl = refreshControl -// refreshControl.addTarget(self, action: #selector(NotificationViewController.refreshControlValueChanged(_:)), for: .valueChanged) -// -// tableView.delegate = self -// viewModel.tableView = tableView -// viewModel.contentOffsetAdjustableTimelineViewControllerDelegate = self -// viewModel.setupDiffableDataSource( -// for: tableView, -// dependency: self, -// delegate: self, -// statusTableViewCellDelegate: self -// ) -// viewModel.viewDidLoad.send() -// -// // bind refresh control -// viewModel.isFetchingLatestNotification -// .receive(on: DispatchQueue.main) -// .sink { [weak self] isFetching in -// guard let self = self else { return } -// if !isFetching { -// UIView.animate(withDuration: 0.5) { [weak self] in -// guard let self = self else { return } -// self.refreshControl.endRefreshing() -// } -// } -// } -// .store(in: &disposeBag) -// -// viewModel.dataSourceDidUpdated -// .receive(on: RunLoop.main) -// .sink { [weak self] in -// guard let self = self else { return } -// guard self.viewModel.needsScrollToTopAfterDataSourceUpdate else { return } -// self.viewModel.needsScrollToTopAfterDataSourceUpdate = false -// DispatchQueue.main.asyncAfter(deadline: .now() + 0.33) { -// self.scrollToTop(animated: true) -// } -// } -// .store(in: &disposeBag) -// -// viewModel.selectedIndex -// .removeDuplicates() -// .receive(on: DispatchQueue.main) -// .sink { [weak self] segment in -// guard let self = self else { return } -// self.segmentControl.selectedSegmentIndex = segment.rawValue -// -// // trigger scroll-to-top after data reload -// self.viewModel.needsScrollToTopAfterDataSourceUpdate = true -// -// guard let domain = self.viewModel.activeMastodonAuthenticationBox.value?.domain, let userID = self.viewModel.activeMastodonAuthenticationBox.value?.userID else { -// return -// } -// -// self.viewModel.needsScrollToTopAfterDataSourceUpdate = true -// -// switch segment { -// case .everyThing: -// self.viewModel.notificationPredicate.value = MastodonNotification.predicate(domain: domain, userID: userID) -// case .mentions: -// self.viewModel.notificationPredicate.value = MastodonNotification.predicate(domain: domain, userID: userID, typeRaw: Mastodon.Entity.Notification.NotificationType.mention.rawValue) -// } -// } -// .store(in: &disposeBag) -// -// segmentControl.observe(\.selectedSegmentIndex, options: [.new]) { [weak self] segmentControl, _ in -// guard let self = self else { return } -// // scroll to top when select same segment -// if segmentControl.selectedSegmentIndex == self.viewModel.selectedIndex.value.rawValue { -// self.scrollToTop(animated: true) -// } -// } -// .store(in: &observations) } override func viewWillAppear(_ animated: Bool) { @@ -197,19 +107,12 @@ extension NotificationViewController { // needs trigger manually after onboarding dismiss -// setNeedsStatusBarAppearanceUpdate() + setNeedsStatusBarAppearanceUpdate() } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) -// DispatchQueue.main.async { [weak self] in -// guard let self = self else { return } -// if (self.viewModel.fetchedResultsController.fetchedObjects ?? []).count == 0 { -//// self.viewModel.loadLatestStateMachine.enter(NotificationViewModel.LoadLatestState.Loading.self) -// } -// } -// // reset notification count context.notificationService.clearNotificationCountForActiveUser() } @@ -265,331 +168,82 @@ extension NotificationViewController { } } -// MARK: - UITableViewDelegate - -extension NotificationViewController: UITableViewDelegate { - -// func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { -// aspectTableView(tableView, estimatedHeightForRowAt: indexPath) -// } -// -// func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { -// guard let diffableDataSource = viewModel.diffableDataSource else { return } -// guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return } -// switch item { -// case .notificationStatus: -// aspectTableView(tableView, willDisplay: cell, forRowAt: indexPath) -// case .bottomLoader: -// if !tableView.isDragging, !tableView.isDecelerating { -// viewModel.loadOldestStateMachine.enter(NotificationViewModel.LoadOldestState.Loading.self) -// } -// default: -// break -// } -// } -// -// func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) { -// aspectTableView(tableView, didEndDisplaying: cell, forRowAt: indexPath) -// } -// -// func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { -// aspectTableView(tableView, didSelectRowAt: indexPath) -// } -// -// func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? { -// return aspectTableView(tableView, contextMenuConfigurationForRowAt: indexPath, point: point) -// } -// -// func tableView(_ tableView: UITableView, previewForHighlightingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? { -// return aspectTableView(tableView, previewForHighlightingContextMenuWithConfiguration: configuration) -// } -// -// func tableView(_ tableView: UITableView, previewForDismissingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? { -// return aspectTableView(tableView, previewForDismissingContextMenuWithConfiguration: configuration) -// } -// -// func tableView(_ tableView: UITableView, willPerformPreviewActionForMenuWith configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionCommitAnimating) { -// aspectTableView(tableView, willPerformPreviewActionForMenuWith: configuration, animator: animator) -// } - +// MARK: - ScrollViewContainer +extension NotificationViewController: ScrollViewContainer { + var scrollView: UIScrollView? { + guard let viewController = currentViewController as? NotificationTimelineViewController else { + return nil + } + return viewController.scrollView + } } -//extension NotificationViewController { -// private func open(item: NotificationItem) { -// switch item { -// case .notification(let objectID, _): -// let notification = context.managedObjectContext.object(with: objectID) as! MastodonNotification -// if let status = notification.status { -// let viewModel = ThreadViewModel( -// context: context, -// optionalRoot: .root(context: .init(status: status.asRecord)) -// ) -// coordinator.present(scene: .thread(viewModel: viewModel), from: self, transition: .show) -// } else { -// let viewModel = ProfileViewModel( -// context: context, -// optionalMastodonUser: notification.account -// ) -// coordinator.present(scene: .profile(viewModel: viewModel), from: self, transition: .show) -// } -// default: -// break -// } -// } -//} -// MARK: - NotificationTableViewCellDelegate -//extension NotificationViewController: NotificationTableViewCellDelegate { -// -// func notificationStatusTableViewCell(_ cell: NotificationStatusTableViewCell, avatarImageViewDidPressed imageView: UIImageView) { -// guard let diffableDataSource = viewModel.diffableDataSource else { return } -// guard let indexPath = tableView.indexPath(for: cell) else { return } -// guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return } -// switch item { -// case .notification(let objectID, _): -// guard let notification = try? viewModel.fetchedResultsController.managedObjectContext.existingObject(with: objectID) as? MastodonNotification else { return } -// let viewModel = ProfileViewModel(context: context, optionalMastodonUser: notification.account) -// coordinator.present(scene: .profile(viewModel: viewModel), from: self, transition: .show) -// default: -// break -// } -// } -// -// func notificationStatusTableViewCell(_ cell: NotificationStatusTableViewCell, authorNameLabelDidPressed label: MetaLabel) { -// guard let diffableDataSource = viewModel.diffableDataSource else { return } -// guard let indexPath = tableView.indexPath(for: cell) else { return } -// guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return } -// switch item { -// case .notification(let objectID, _): -// guard let notification = try? viewModel.fetchedResultsController.managedObjectContext.existingObject(with: objectID) as? MastodonNotification else { return } -// let viewModel = ProfileViewModel(context: context, optionalMastodonUser: notification.account) -// coordinator.present(scene: .profile(viewModel: viewModel), from: self, transition: .show) -// default: -// break -// } -// } -// -// func notificationTableViewCell(_ cell: NotificationStatusTableViewCell, notification: MastodonNotification, acceptButtonDidPressed button: UIButton) { -// viewModel.acceptFollowRequest(notification: notification) -// } -// -// func notificationTableViewCell(_ cell: NotificationStatusTableViewCell, notification: MastodonNotification, rejectButtonDidPressed button: UIButton) { -// viewModel.rejectFollowRequest(notification: notification) -// } -// -// func userNameLabelDidPressed(notification: MastodonNotification) { -// let viewModel = CachedProfileViewModel(context: context, mastodonUser: notification.account) -// DispatchQueue.main.async { -// self.coordinator.present(scene: .profile(viewModel: viewModel), from: self, transition: .show) -// } -// } -// -// func parent() -> UIViewController { -// self -// } -// -// func notificationStatusTableViewCell(_ cell: NotificationStatusTableViewCell, statusView: StatusView, revealContentWarningButtonDidPressed button: UIButton) { -// StatusProviderFacade.responseToStatusContentWarningRevealAction(provider: self, cell: cell) -// } -// -// func notificationStatusTableViewCell(_ cell: NotificationStatusTableViewCell, statusView: StatusView, contentWarningOverlayViewDidPressed contentWarningOverlayView: ContentWarningOverlayView) { -// StatusProviderFacade.responseToStatusContentWarningRevealAction(provider: self, cell: cell) -// } -// -// func notificationStatusTableViewCell(_ cell: NotificationStatusTableViewCell, statusView: StatusView, playerContainerView: PlayerContainerView, contentWarningOverlayViewDidPressed contentWarningOverlayView: ContentWarningOverlayView) { -// StatusProviderFacade.responseToStatusContentWarningRevealAction(provider: self, cell: cell) -// } -// -// func notificationStatusTableViewCell(_ cell: NotificationStatusTableViewCell, statusView: StatusView, metaText: MetaText, didSelectMeta meta: Meta) { -// StatusProviderFacade.responseToStatusMetaTextAction(provider: self, cell: cell, metaText: metaText, didSelectMeta: meta) -// } -//} +extension NotificationViewController { + + enum CategorySwitch: String, CaseIterable { + case everything + case mentions + + var title: String { + switch self { + case .everything: return L10n.Scene.Notification.Keyobard.showEverything + case .mentions: return L10n.Scene.Notification.Keyobard.showMentions + } + } + + // UIKeyCommand input + var input: String { + switch self { + case .everything: return "[" // + shift + command + case .mentions: return "]" // + shift + command + } + } + + var modifierFlags: UIKeyModifierFlags { + switch self { + case .everything: return [.shift, .command] + case .mentions: return [.shift, .command] + } + } + + var propertyList: Any { + return rawValue + } + } + + var categorySwitchKeyCommands: [UIKeyCommand] { + CategorySwitch.allCases.map { category in + UIKeyCommand( + title: category.title, + image: nil, + action: #selector(NotificationViewController.showCategory(_:)), + input: category.input, + modifierFlags: category.modifierFlags, + propertyList: category.propertyList, + alternates: [], + discoverabilityTitle: nil, + attributes: [], + state: .off + ) + } + } -// MARK: - UIScrollViewDelegate - -//extension NotificationViewController { -// func scrollViewDidScroll(_ scrollView: UIScrollView) { -// handleScrollViewDidScroll(scrollView) -// } -//} - -// MARK: - ScrollViewContainer -//extension NotificationViewController: ScrollViewContainer { -// -// var scrollView: UIScrollView { tableView } -// -// func scrollToTop(animated: Bool) { -// let indexPath = IndexPath(row: 0, section: 0) -// guard viewModel.diffableDataSource?.itemIdentifier(for: indexPath) != nil else { return } -// tableView.scrollToRow(at: indexPath, at: .top, animated: true) -// } -//} - -// MARK: - AVPlayerViewControllerDelegate -//extension NotificationViewController: AVPlayerViewControllerDelegate { -// func playerViewController(_ playerViewController: AVPlayerViewController, willBeginFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) { -// handlePlayerViewController(playerViewController, willBeginFullScreenPresentationWithAnimationCoordinator: coordinator) -// } -// -// func playerViewController(_ playerViewController: AVPlayerViewController, willEndFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) { -// handlePlayerViewController(playerViewController, willEndFullScreenPresentationWithAnimationCoordinator: coordinator) -// } -//} - -//// MARK: - statusTableViewCellDelegate -//extension NotificationViewController: StatusTableViewCellDelegate { -// var playerViewControllerDelegate: AVPlayerViewControllerDelegate? { -// return self -// } -//} - -//extension NotificationViewController { -// -// enum CategorySwitch: String, CaseIterable { -// case showEverything -// case showMentions -// -// var title: String { -// switch self { -// case .showEverything: return L10n.Scene.Notification.Keyobard.showEverything -// case .showMentions: return L10n.Scene.Notification.Keyobard.showMentions -// } -// } -// -// // UIKeyCommand input -// var input: String { -// switch self { -// case .showEverything: return "[" // + shift + command -// case .showMentions: return "]" // + shift + command -// } -// } -// -// var modifierFlags: UIKeyModifierFlags { -// switch self { -// case .showEverything: return [.shift, .command] -// case .showMentions: return [.shift, .command] -// } -// } -// -// var propertyList: Any { -// return rawValue -// } -// } -// -// var categorySwitchKeyCommands: [UIKeyCommand] { -// CategorySwitch.allCases.map { category in -// UIKeyCommand( -// title: category.title, -// image: nil, -// action: #selector(NotificationViewController.showCategory(_:)), -// input: category.input, -// modifierFlags: category.modifierFlags, -// propertyList: category.propertyList, -// alternates: [], -// discoverabilityTitle: nil, -// attributes: [], -// state: .off -// ) -// } -// } -// -// @objc private func showCategory(_ sender: UIKeyCommand) { -// os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) -// guard let rawValue = sender.propertyList as? String, -// let category = CategorySwitch(rawValue: rawValue) else { return } -// -// switch category { -// case .showEverything: -// viewModel.selectedIndex.value = .everyThing -// case .showMentions: -// viewModel.selectedIndex.value = .mentions -// } -// } -// -// override var keyCommands: [UIKeyCommand]? { -// return categorySwitchKeyCommands + navigationKeyCommands -// } -//} - -//extension NotificationViewController: TableViewControllerNavigateable { -// -// func navigate(direction: TableViewNavigationDirection) { -// if let indexPathForSelectedRow = tableView.indexPathForSelectedRow { -// // navigate up/down on the current selected item -// navigateToStatus(direction: direction, indexPath: indexPathForSelectedRow) -// } else { -// // set first visible item selected -// navigateToFirstVisibleStatus() -// } -// } -// -// private func navigateToStatus(direction: TableViewNavigationDirection, indexPath: IndexPath) { -// guard let diffableDataSource = viewModel.diffableDataSource else { return } -// let items = diffableDataSource.snapshot().itemIdentifiers -// guard let selectedItem = diffableDataSource.itemIdentifier(for: indexPath), -// let selectedItemIndex = items.firstIndex(of: selectedItem) else { -// return -// } -// -// let _navigateToItem: NotificationItem? = { -// var index = selectedItemIndex -// while 0..<items.count ~= index { -// index = { -// switch direction { -// case .up: return index - 1 -// case .down: return index + 1 -// } -// }() -// guard 0..<items.count ~= index else { return nil } -// let item = items[index] -// -// guard Self.validNavigateableItem(item) else { continue } -// return item -// } -// return nil -// }() -// -// guard let item = _navigateToItem, let indexPath = diffableDataSource.indexPath(for: item) else { return } -// let scrollPosition: UITableView.ScrollPosition = overrideNavigationScrollPosition ?? Self.navigateScrollPosition(tableView: tableView, indexPath: indexPath) -// tableView.selectRow(at: indexPath, animated: true, scrollPosition: scrollPosition) -// } -// -// private func navigateToFirstVisibleStatus() { -// guard let indexPathsForVisibleRows = tableView.indexPathsForVisibleRows else { return } -// guard let diffableDataSource = viewModel.diffableDataSource else { return } -// -// var visibleItems: [NotificationItem] = indexPathsForVisibleRows.sorted().compactMap { indexPath in -// guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return nil } -// guard Self.validNavigateableItem(item) else { return nil } -// return item -// } -// if indexPathsForVisibleRows.first?.row != 0, visibleItems.count > 1 { -// // drop first when visible not the first cell of table -// visibleItems.removeFirst() -// } -// guard let item = visibleItems.first, let indexPath = diffableDataSource.indexPath(for: item) else { return } -// let scrollPosition: UITableView.ScrollPosition = overrideNavigationScrollPosition ?? Self.navigateScrollPosition(tableView: tableView, indexPath: indexPath) -// tableView.selectRow(at: indexPath, animated: true, scrollPosition: scrollPosition) -// } -// -// static func validNavigateableItem(_ item: NotificationItem) -> Bool { -// switch item { -// case .notification: -// return true -// default: -// return false -// } -// } -// -// func open() { -// guard let indexPathForSelectedRow = tableView.indexPathForSelectedRow else { return } -// guard let diffableDataSource = viewModel.diffableDataSource else { return } -// guard let item = diffableDataSource.itemIdentifier(for: indexPathForSelectedRow) else { return } -// open(item: item) -// } -// -// func navigateKeyCommandHandlerRelay(_ sender: UIKeyCommand) { -// navigateKeyCommandHandler(sender) -// } -// -//} + @objc private func showCategory(_ sender: UIKeyCommand) { + os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) + guard let rawValue = sender.propertyList as? String, + let category = CategorySwitch(rawValue: rawValue) + else { return } + + switch category { + case .everything: + scrollToPage(.first, animated: true, completion: nil) + case .mentions: + scrollToPage(.last, animated: true, completion: nil) + } + } + + override var keyCommands: [UIKeyCommand]? { + return categorySwitchKeyCommands + } +} diff --git a/Mastodon/Scene/Onboarding/ConfirmEmail/MastodonConfirmEmailViewController.swift b/Mastodon/Scene/Onboarding/ConfirmEmail/MastodonConfirmEmailViewController.swift index 44a90fd9..b1b2280d 100644 --- a/Mastodon/Scene/Onboarding/ConfirmEmail/MastodonConfirmEmailViewController.swift +++ b/Mastodon/Scene/Onboarding/ConfirmEmail/MastodonConfirmEmailViewController.swift @@ -36,7 +36,7 @@ final class MastodonConfirmEmailViewController: UIViewController, NeedsDependenc let label = UILabel() label.font = UIFontMetrics(forTextStyle: .title1).scaledFont(for: UIFont.systemFont(ofSize: 20)) label.textColor = .secondaryLabel - label.text = L10n.Scene.ConfirmEmail.subtitle(viewModel.email) + label.text = L10n.Scene.ConfirmEmail.subtitle label.numberOfLines = 0 return label }() @@ -51,7 +51,7 @@ final class MastodonConfirmEmailViewController: UIViewController, NeedsDependenc let navigationActionView: NavigationActionView = { let navigationActionView = NavigationActionView() - navigationActionView.backgroundColor = Asset.Scene.Onboarding.onboardingBackground.color + navigationActionView.backgroundColor = Asset.Scene.Onboarding.background.color return navigationActionView }() @@ -135,7 +135,7 @@ extension MastodonConfirmEmailViewController { .store(in: &self.disposeBag) - navigationActionView.backButton.setTitle("Resend", for: .normal) // TODO: i18n + navigationActionView.backButton.setTitle(L10n.Scene.ConfirmEmail.Button.resend, for: .normal) navigationActionView.backButton.addTarget(self, action: #selector(MastodonConfirmEmailViewController.resendButtonPressed(_:)), for: .touchUpInside) navigationActionView.nextButton.setTitle(L10n.Scene.ConfirmEmail.Button.openEmailApp, for: .normal) diff --git a/Mastodon/Scene/Onboarding/ConfirmEmail/MastodonConfirmEmailViewModel.swift b/Mastodon/Scene/Onboarding/ConfirmEmail/MastodonConfirmEmailViewModel.swift index 7ddcefbb..35480ba9 100644 --- a/Mastodon/Scene/Onboarding/ConfirmEmail/MastodonConfirmEmailViewModel.swift +++ b/Mastodon/Scene/Onboarding/ConfirmEmail/MastodonConfirmEmailViewModel.swift @@ -38,7 +38,7 @@ final class MastodonConfirmEmailViewModel { self.updateCredentialQuery = updateCredentialQuery } - #if DEBUG + #if DEBUG || SNAPSHOT init() { self.context = AppContext.shared self.email = "example.com" diff --git a/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewController.swift b/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewController.swift index 78a43395..2d43faa5 100644 --- a/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewController.swift +++ b/Mastodon/Scene/Onboarding/PickServer/MastodonPickServerViewController.swift @@ -51,7 +51,7 @@ final class MastodonPickServerViewController: UIViewController, NeedsDependency let navigationActionView: NavigationActionView = { let navigationActionView = NavigationActionView() - navigationActionView.backgroundColor = Asset.Scene.Onboarding.onboardingBackground.color + navigationActionView.backgroundColor = Asset.Scene.Onboarding.background.color return navigationActionView }() diff --git a/Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerCell.swift b/Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerCell.swift index cf92778b..66906777 100644 --- a/Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerCell.swift +++ b/Mastodon/Scene/Onboarding/PickServer/TableViewCell/PickServerCell.swift @@ -114,7 +114,7 @@ class PickServerCell: UITableViewCell { extension PickServerCell { private func _init() { selectionStyle = .none - backgroundColor = Asset.Scene.Onboarding.onboardingBackground.color + backgroundColor = Asset.Scene.Onboarding.background.color checkbox.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(checkbox) diff --git a/Mastodon/Scene/Onboarding/PickServer/View/PickServerServerSectionTableHeaderView.swift b/Mastodon/Scene/Onboarding/PickServer/View/PickServerServerSectionTableHeaderView.swift index f26f79b0..b2269b9c 100644 --- a/Mastodon/Scene/Onboarding/PickServer/View/PickServerServerSectionTableHeaderView.swift +++ b/Mastodon/Scene/Onboarding/PickServer/View/PickServerServerSectionTableHeaderView.swift @@ -136,7 +136,7 @@ final class PickServerServerSectionTableHeaderView: UIView { extension PickServerServerSectionTableHeaderView { private func _init() { preservesSuperviewLayoutMargins = true - backgroundColor = Asset.Scene.Onboarding.onboardingBackground.color + backgroundColor = Asset.Scene.Onboarding.background.color collectionView.translatesAutoresizingMaskIntoConstraints = false collectionView.preservesSuperviewLayoutMargins = true diff --git a/Mastodon/Scene/Onboarding/Register/Cell/MastodonRegisterTextFieldTableViewCell.swift b/Mastodon/Scene/Onboarding/Register/Cell/MastodonRegisterTextFieldTableViewCell.swift index 8659e150..3daa2eb1 100644 --- a/Mastodon/Scene/Onboarding/Register/Cell/MastodonRegisterTextFieldTableViewCell.swift +++ b/Mastodon/Scene/Onboarding/Register/Cell/MastodonRegisterTextFieldTableViewCell.swift @@ -87,6 +87,8 @@ extension MastodonRegisterTextFieldTableViewCell { textField.autocapitalizationType = .none textField.attributedPlaceholder = nil textField.isSecureTextEntry = false + textField.textAlignment = .natural + textField.semanticContentAttribute = .unspecified let paddingRect = CGRect(x: 0, y: 0, width: 16, height: 10) textField.leftView = UIView(frame: paddingRect) diff --git a/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewController.swift b/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewController.swift index f4edf8e8..bd2db3d4 100644 --- a/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewController.swift +++ b/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewController.swift @@ -69,7 +69,7 @@ final class MastodonRegisterViewController: UIViewController, NeedsDependency, O let navigationActionView: NavigationActionView = { let navigationActionView = NavigationActionView() - navigationActionView.backgroundColor = Asset.Scene.Onboarding.onboardingBackground.color + navigationActionView.backgroundColor = Asset.Scene.Onboarding.background.color return navigationActionView }() diff --git a/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewModel+Diffable.swift b/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewModel+Diffable.swift index dbf7c5f1..beb16890 100644 --- a/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewModel+Diffable.swift +++ b/Mastodon/Scene/Onboarding/Register/MastodonRegisterViewModel+Diffable.swift @@ -21,9 +21,9 @@ extension MastodonRegisterViewModel { diffableDataSource = UITableViewDiffableDataSource(tableView: tableView) { tableView, indexPath, item in switch item { - case .header: + case .header(let domain): let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: OnboardingHeadlineTableViewCell.self), for: indexPath) as! OnboardingHeadlineTableViewCell - cell.titleLabel.text = L10n.Scene.Register.title + cell.titleLabel.text = L10n.Scene.Register.title(domain) cell.subTitleLabel.isHidden = true return cell case .avatar: @@ -55,6 +55,8 @@ extension MastodonRegisterViewModel { cell.textField.keyboardType = .alphabet cell.textField.autocorrectionType = .no cell.textField.text = self.username + cell.textField.textAlignment = .left + cell.textField.semanticContentAttribute = .forceLeftToRight NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: cell.textField) .receive(on: DispatchQueue.main) .compactMap { notification in @@ -94,6 +96,8 @@ extension MastodonRegisterViewModel { cell.textField.autocorrectionType = .no cell.textField.isSecureTextEntry = true cell.textField.text = self.password + cell.textField.textAlignment = .left + cell.textField.semanticContentAttribute = .forceLeftToRight NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: cell.textField) .receive(on: DispatchQueue.main) .compactMap { notification in @@ -136,7 +140,7 @@ extension MastodonRegisterViewModel { var snapshot = NSDiffableDataSourceSnapshot<RegisterSection, RegisterItem>() snapshot.appendSections([.main]) - snapshot.appendItems([.header], toSection: .main) + snapshot.appendItems([.header(domain: domain)], toSection: .main) snapshot.appendItems([.avatar, .name, .username, .email, .password, .hint], toSection: .main) if approvalRequired { snapshot.appendItems([.reason], toSection: .main) diff --git a/Mastodon/Scene/Onboarding/ServerRules/MastodonServerRulesViewController.swift b/Mastodon/Scene/Onboarding/ServerRules/MastodonServerRulesViewController.swift index 74649bc2..2f13ad19 100644 --- a/Mastodon/Scene/Onboarding/ServerRules/MastodonServerRulesViewController.swift +++ b/Mastodon/Scene/Onboarding/ServerRules/MastodonServerRulesViewController.swift @@ -46,7 +46,7 @@ final class MastodonServerRulesViewController: UIViewController, NeedsDependency let navigationActionView: NavigationActionView = { let navigationActionView = NavigationActionView() - navigationActionView.backgroundColor = Asset.Scene.Onboarding.onboardingBackground.color + navigationActionView.backgroundColor = Asset.Scene.Onboarding.background.color return navigationActionView }() diff --git a/Mastodon/Scene/Onboarding/Share/OnboardingHeadlineTableViewCell.swift b/Mastodon/Scene/Onboarding/Share/OnboardingHeadlineTableViewCell.swift index a6c603c2..01070fbe 100644 --- a/Mastodon/Scene/Onboarding/Share/OnboardingHeadlineTableViewCell.swift +++ b/Mastodon/Scene/Onboarding/Share/OnboardingHeadlineTableViewCell.swift @@ -25,7 +25,7 @@ final class OnboardingHeadlineTableViewCell: UITableViewCell { let label = UILabel() label.font = MastodonPickServerViewController.subTitleFont label.textColor = MastodonPickServerViewController.subTitleTextColor - label.text = "Pick a community based on your interests, region, or a general purpose one. Each community is operated by an entirely independent organization or individual." + label.text = L10n.Scene.ServerPicker.subtitle label.adjustsFontForContentSizeCategory = true label.numberOfLines = 0 return label @@ -46,7 +46,7 @@ extension OnboardingHeadlineTableViewCell { private func _init() { selectionStyle = .none - backgroundColor = Asset.Scene.Onboarding.onboardingBackground.color + backgroundColor = Asset.Scene.Onboarding.background.color let container = UIStackView() container.axis = .vertical diff --git a/Mastodon/Scene/Onboarding/Share/OnboardingViewControllerAppearance.swift b/Mastodon/Scene/Onboarding/Share/OnboardingViewControllerAppearance.swift index 5c51fb55..ba1eecfc 100644 --- a/Mastodon/Scene/Onboarding/Share/OnboardingViewControllerAppearance.swift +++ b/Mastodon/Scene/Onboarding/Share/OnboardingViewControllerAppearance.swift @@ -40,7 +40,7 @@ extension OnboardingViewControllerAppearance { } func setupOnboardingAppearance() { - view.backgroundColor = Asset.Scene.Onboarding.onboardingBackground.color + view.backgroundColor = Asset.Scene.Onboarding.background.color setupNavigationBarAppearance() @@ -72,7 +72,7 @@ extension OnboardingViewControllerAppearance { func setupNavigationBarBackgroundView() { let navigationBarBackgroundView: UIView = { let view = UIView() - view.backgroundColor = Asset.Scene.Onboarding.onboardingBackground.color + view.backgroundColor = Asset.Scene.Onboarding.background.color return view }() diff --git a/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift b/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift index f10bfc42..2389947a 100644 --- a/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift +++ b/Mastodon/Scene/Onboarding/Welcome/WelcomeViewController.swift @@ -50,7 +50,7 @@ final class WelcomeViewController: UIViewController, NeedsDependency { private(set) lazy var signUpButton: PrimaryActionButton = { let button = PrimaryActionButton() button.adjustsBackgroundImageWhenUserInterfaceStyleChanges = false - button.setTitle("Get Started", for: .normal) // TODO: i18n + button.setTitle(L10n.Scene.Welcome.getStarted, for: .normal) let backgroundImageColor: UIColor = .white let backgroundImageHighlightedColor: UIColor = UIColor(white: 0.8, alpha: 1.0) button.setBackgroundImage(.placeholder(color: backgroundImageColor), for: .normal) @@ -64,7 +64,7 @@ final class WelcomeViewController: UIViewController, NeedsDependency { let button = PrimaryActionButton() button.adjustsBackgroundImageWhenUserInterfaceStyleChanges = false button.titleLabel?.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 15, weight: .semibold)) - button.setTitle("Log In", for: .normal) + button.setTitle(L10n.Scene.Welcome.logIn, for: .normal) let backgroundImageColor = Asset.Scene.Welcome.signInButtonBackground.color let backgroundImageHighlightedColor = Asset.Scene.Welcome.signInButtonBackground.color.withAlphaComponent(0.8) button.setBackgroundImage(.placeholder(color: backgroundImageColor), for: .normal) diff --git a/Mastodon/Scene/Profile/About/ProfileAboutViewController.swift b/Mastodon/Scene/Profile/About/ProfileAboutViewController.swift index 9b386847..4879be74 100644 --- a/Mastodon/Scene/Profile/About/ProfileAboutViewController.swift +++ b/Mastodon/Scene/Profile/About/ProfileAboutViewController.swift @@ -162,7 +162,7 @@ extension ProfileAboutViewController: ProfileFieldEditCollectionViewCellDelegate // MARK: - ScrollViewContainer extension ProfileAboutViewController: ScrollViewContainer { - var scrollView: UIScrollView { + var scrollView: UIScrollView? { collectionView } } diff --git a/Mastodon/Scene/Profile/About/ProfileAboutViewModel+Diffable.swift b/Mastodon/Scene/Profile/About/ProfileAboutViewModel+Diffable.swift index 66b7d25c..259cad12 100644 --- a/Mastodon/Scene/Profile/About/ProfileAboutViewModel+Diffable.swift +++ b/Mastodon/Scene/Profile/About/ProfileAboutViewModel+Diffable.swift @@ -74,6 +74,10 @@ extension ProfileAboutViewModel { items.append(.addEntry) } + if !isEditing, items.isEmpty { + items.append(.noResult) + } + snapshot.appendItems(items, toSection: .main) diffableDataSource.apply(snapshot, animatingDifferences: false, completion: nil) diff --git a/Mastodon/Scene/Profile/CachedProfileViewModel.swift b/Mastodon/Scene/Profile/CachedProfileViewModel.swift index 083724be..c33a905a 100644 --- a/Mastodon/Scene/Profile/CachedProfileViewModel.swift +++ b/Mastodon/Scene/Profile/CachedProfileViewModel.swift @@ -12,6 +12,8 @@ final class CachedProfileViewModel: ProfileViewModel { init(context: AppContext, mastodonUser: MastodonUser) { super.init(context: context, optionalMastodonUser: mastodonUser) + + logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): [Profile] user[\(mastodonUser.id)] profile: \(mastodonUser.acctWithDomain)") } } diff --git a/Mastodon/Scene/Profile/Favorite/FavoriteViewController.swift b/Mastodon/Scene/Profile/Favorite/FavoriteViewController.swift index d061826c..2ac1e206 100644 --- a/Mastodon/Scene/Profile/Favorite/FavoriteViewController.swift +++ b/Mastodon/Scene/Profile/Favorite/FavoriteViewController.swift @@ -73,7 +73,6 @@ extension FavoriteViewController { ]) tableView.delegate = self -// tableView.prefetchDataSource = self viewModel.setupDiffableDataSource( tableView: tableView, statusTableViewCellDelegate: self @@ -104,20 +103,6 @@ extension FavoriteViewController { } -//// MARK: - TableViewCellHeightCacheableContainer -//extension FavoriteViewController: TableViewCellHeightCacheableContainer { -// var cellFrameCache: NSCache<NSNumber, NSValue> { -// return viewModel.cellFrameCache -// } -//} - -// MARK: - UIScrollViewDelegate -//extension FavoriteViewController { -// func scrollViewDidScroll(_ scrollView: UIScrollView) { -// aspectScrollViewDidScroll(scrollView) -// } -//} - // MARK: - UITableViewDelegate extension FavoriteViewController: UITableViewDelegate, AutoGenerateTableViewDelegate { // sourcery:inline:FavoriteViewController.AutoGenerateTableViewDelegate @@ -146,83 +131,24 @@ extension FavoriteViewController: UITableViewDelegate, AutoGenerateTableViewDele // sourcery:end - -// func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { -// aspectTableView(tableView, estimatedHeightForRowAt: indexPath) -// } -// -// func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { -// aspectTableView(tableView, willDisplay: cell, forRowAt: indexPath) -// } -// -// func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) { -// aspectTableView(tableView, didEndDisplaying: cell, forRowAt: indexPath) -// } -// -// func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { -// aspectTableView(tableView, didSelectRowAt: indexPath) -// } -// -// func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? { -// return aspectTableView(tableView, contextMenuConfigurationForRowAt: indexPath, point: point) -// } -// -// func tableView(_ tableView: UITableView, previewForHighlightingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? { -// return aspectTableView(tableView, previewForHighlightingContextMenuWithConfiguration: configuration) -// } -// -// func tableView(_ tableView: UITableView, previewForDismissingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? { -// return aspectTableView(tableView, previewForDismissingContextMenuWithConfiguration: configuration) -// } -// -// func tableView(_ tableView: UITableView, willPerformPreviewActionForMenuWith configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionCommitAnimating) { -// aspectTableView(tableView, willPerformPreviewActionForMenuWith: configuration, animator: animator) -// } -// } -// MARK: - UITableViewDataSourcePrefetching -//extension FavoriteViewController: UITableViewDataSourcePrefetching { -// func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) { -// aspectTableView(tableView, prefetchRowsAt: indexPaths) -// } -//} - -// MARK: - AVPlayerViewControllerDelegate -//extension FavoriteViewController: AVPlayerViewControllerDelegate { -// -// func playerViewController(_ playerViewController: AVPlayerViewController, willBeginFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) { -// aspectPlayerViewController(playerViewController, willBeginFullScreenPresentationWithAnimationCoordinator: coordinator) -// } -// -// func playerViewController(_ playerViewController: AVPlayerViewController, willEndFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) { -// aspectPlayerViewController(playerViewController, willEndFullScreenPresentationWithAnimationCoordinator: coordinator) -// } -// -//} - -// MARK: - TimelinePostTableViewCellDelegate -//extension FavoriteViewController: StatusTableViewCellDelegate { -// weak var playerViewControllerDelegate: AVPlayerViewControllerDelegate? { return self } -// func parent() -> UIViewController { return self } -//} - -//extension FavoriteViewController { -// override var keyCommands: [UIKeyCommand]? { -// return navigationKeyCommands + statusNavigationKeyCommands -// } -//} -// -//// MARK: - StatusTableViewControllerNavigateable -//extension FavoriteViewController: StatusTableViewControllerNavigateable { -// @objc func navigateKeyCommandHandlerRelay(_ sender: UIKeyCommand) { -// navigateKeyCommandHandler(sender) -// } -// -// @objc func statusKeyCommandHandlerRelay(_ sender: UIKeyCommand) { -// statusKeyCommandHandler(sender) -// } -//} - // MARK: - StatusTableViewCellDelegate extension FavoriteViewController: StatusTableViewCellDelegate { } + +extension FavoriteViewController { + override var keyCommands: [UIKeyCommand]? { + return navigationKeyCommands + statusNavigationKeyCommands + } +} + +// MARK: - StatusTableViewControllerNavigateable +extension FavoriteViewController: StatusTableViewControllerNavigateable { + @objc func navigateKeyCommandHandlerRelay(_ sender: UIKeyCommand) { + navigateKeyCommandHandler(sender) + } + + @objc func statusKeyCommandHandlerRelay(_ sender: UIKeyCommand) { + statusKeyCommandHandler(sender) + } +} diff --git a/Mastodon/Scene/Profile/Favorite/FavoriteViewModel+Diffable.swift b/Mastodon/Scene/Profile/Favorite/FavoriteViewModel+Diffable.swift index f74d3de7..58109247 100644 --- a/Mastodon/Scene/Profile/Favorite/FavoriteViewModel+Diffable.swift +++ b/Mastodon/Scene/Profile/Favorite/FavoriteViewModel+Diffable.swift @@ -18,7 +18,9 @@ extension FavoriteViewModel { context: context, configuration: StatusSection.Configuration( statusTableViewCellDelegate: statusTableViewCellDelegate, - timelineMiddleLoaderTableViewCellDelegate: nil + timelineMiddleLoaderTableViewCellDelegate: nil, + filterContext: .none, + activeFilters: nil ) ) // set empty section to make update animation top-to-bottom style diff --git a/Mastodon/Scene/Profile/Follower/FollowerListViewModel.swift b/Mastodon/Scene/Profile/Follower/FollowerListViewModel.swift index a212c95b..80f26e60 100644 --- a/Mastodon/Scene/Profile/Follower/FollowerListViewModel.swift +++ b/Mastodon/Scene/Profile/Follower/FollowerListViewModel.swift @@ -44,7 +44,7 @@ final class FollowerListViewModel { self.userFetchedResultsController = UserFetchedResultsController( managedObjectContext: context.managedObjectContext, domain: domain, - additionalTweetPredicate: nil + additionalPredicate: nil ) self.domain = CurrentValueSubject(domain) self.userID = CurrentValueSubject(userID) diff --git a/Mastodon/Scene/Profile/Following/FollowingListViewModel.swift b/Mastodon/Scene/Profile/Following/FollowingListViewModel.swift index 22658a0e..f1e07f9d 100644 --- a/Mastodon/Scene/Profile/Following/FollowingListViewModel.swift +++ b/Mastodon/Scene/Profile/Following/FollowingListViewModel.swift @@ -44,7 +44,7 @@ final class FollowingListViewModel { self.userFetchedResultsController = UserFetchedResultsController( managedObjectContext: context.managedObjectContext, domain: domain, - additionalTweetPredicate: nil + additionalPredicate: nil ) self.domain = CurrentValueSubject(domain) self.userID = CurrentValueSubject(userID) diff --git a/Mastodon/Scene/Profile/Header/ProfileHeaderViewController.swift b/Mastodon/Scene/Profile/Header/ProfileHeaderViewController.swift index 9c959722..de6ad541 100644 --- a/Mastodon/Scene/Profile/Header/ProfileHeaderViewController.swift +++ b/Mastodon/Scene/Profile/Header/ProfileHeaderViewController.swift @@ -61,12 +61,15 @@ final class ProfileHeaderViewController: UIViewController { case .dark: // Asset.Colors.Label.primary.color button.selectedTintColor = UIColor(red: 238.0/255.0, green: 238.0/255.0, blue: 238.0/255.0, alpha: 1.0) + // Asset.Colors.Label.secondary.color + button.tintColor = UIColor(red: 151.0/255.0, green: 157.0/255.0, blue: 173.0/255.0, alpha: 1.0) default: // Asset.Colors.Label.primary.color button.selectedTintColor = UIColor(red: 40.0/255.0, green: 44.0/255.0, blue: 55.0/255.0, alpha: 1.0) + // Asset.Colors.Label.secondary.color + button.tintColor = UIColor(red: 60.0/255.0, green: 60.0/255.0, blue: 67.0/255.0, alpha: 0.6) } - button.tintColor = .secondaryLabel // UIColor(red: 60.0/255.0, green: 60.0/255.0, blue: 67.0/255.0, alpha: 1.0) button.backgroundColor = .clear } } diff --git a/Mastodon/Scene/Profile/Header/View/ProfileHeaderView.swift b/Mastodon/Scene/Profile/Header/View/ProfileHeaderView.swift index 0c1b0423..78430cb3 100644 --- a/Mastodon/Scene/Profile/Header/View/ProfileHeaderView.swift +++ b/Mastodon/Scene/Profile/Header/View/ProfileHeaderView.swift @@ -75,6 +75,7 @@ final class ProfileHeaderView: UIView { let avatarButton: AvatarButton = { let button = AvatarButton() button.avatarImageView.configure(cornerConfiguration: .init(corner: .fixed(radius: 0))) + button.accessibilityLabel = "Avatar image" // FIXME: i18n return button }() @@ -153,6 +154,8 @@ final class ProfileHeaderView: UIView { }() let statusDashboardView = ProfileStatusDashboardView() + + let relationshipActionButtonShadowContainer = ShadowBackgroundContainer() let relationshipActionButton: ProfileRelationshipActionButton = { let button = ProfileRelationshipActionButton() button.titleLabel?.font = .systemFont(ofSize: 17, weight: .semibold) @@ -196,37 +199,6 @@ final class ProfileHeaderView: UIView { return metaText }() -// static func createFieldCollectionViewLayout() -> UICollectionViewLayout { -// let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(44)) -// let item = NSCollectionLayoutItem(layoutSize: itemSize) -// let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(44)) -// let group = NSCollectionLayoutGroup.vertical(layoutSize: groupSize, subitems: [item]) -// let section = NSCollectionLayoutSection(group: group) -// section.contentInsetsReference = .readableContent -// -// let headerFooterSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(1)) -// let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerFooterSize, elementKind: UICollectionView.elementKindSectionHeader, alignment: .top) -// let footer = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerFooterSize, elementKind: UICollectionView.elementKindSectionFooter, alignment: .bottom) -// section.boundarySupplementaryItems = [header, footer] -// // note: toggle this not take effect -// // section.supplementariesFollowContentInsets = false -// -// return UICollectionViewCompositionalLayout(section: section) -// } -// -// let fieldCollectionView: UICollectionView = { -// let collectionViewLayout = ProfileHeaderView.createFieldCollectionViewLayout() -// let collectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: 100, height: 100), collectionViewLayout: collectionViewLayout) -// collectionView.register(ProfileFieldCollectionViewCell.self, forCellWithReuseIdentifier: String(describing: ProfileFieldCollectionViewCell.self)) -// collectionView.register(ProfileFieldAddEntryCollectionViewCell.self, forCellWithReuseIdentifier: String(describing: ProfileFieldAddEntryCollectionViewCell.self)) -// collectionView.register(ProfileFieldCollectionViewHeaderFooterView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: ProfileFieldCollectionViewHeaderFooterView.headerReuseIdentifer) -// collectionView.register(ProfileFieldCollectionViewHeaderFooterView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: ProfileFieldCollectionViewHeaderFooterView.footerReuseIdentifer) -// collectionView.isScrollEnabled = false -// return collectionView -// }() -// var fieldCollectionViewHeightLayoutConstraint: NSLayoutConstraint! -// var fieldCollectionViewHeightObservation: NSKeyValueObservation? - override init(frame: CGRect) { super.init(frame: frame) _init() @@ -237,10 +209,6 @@ final class ProfileHeaderView: UIView { _init() } - deinit { -// fieldCollectionViewHeightObservation = nil - } - } extension ProfileHeaderView { @@ -282,7 +250,7 @@ extension ProfileHeaderView { avatarImageViewBackgroundView.translatesAutoresizingMaskIntoConstraints = false addSubview(avatarImageViewBackgroundView) NSLayoutConstraint.activate([ - avatarImageViewBackgroundView.leadingAnchor.constraint(equalToSystemSpacingAfter: bannerContainerView.leadingAnchor, multiplier: 2.0), + avatarImageViewBackgroundView.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor), // align to dashboardContainer bottom ]) @@ -338,8 +306,8 @@ extension ProfileHeaderView { addSubview(container) NSLayoutConstraint.activate([ container.topAnchor.constraint(equalTo: bannerContainerView.bottomAnchor), - container.leadingAnchor.constraint(equalToSystemSpacingAfter: leadingAnchor, multiplier: 2.0), - trailingAnchor.constraint(equalToSystemSpacingAfter: container.trailingAnchor, multiplier: 2.0), + container.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor), + layoutMarginsGuide.trailingAnchor.constraint(equalTo: container.trailingAnchor), container.bottomAnchor.constraint(equalTo: bottomAnchor), ]) @@ -356,7 +324,7 @@ extension ProfileHeaderView { avatarImageViewBackgroundView.bottomAnchor.constraint(equalTo: dashboardContainer.bottomAnchor), ]) - // authorContainer: H - [ nameContainer | relationshipActionButton ] + // authorContainer: H - [ nameContainer | padding | relationshipActionButtonShadowContainer ] let authorContainer = UIStackView() authorContainer.axis = .horizontal authorContainer.alignment = .top @@ -401,9 +369,16 @@ extension ProfileHeaderView { nameContainerStackView.addArrangedSubview(usernameLabel) authorContainer.addArrangedSubview(nameContainerStackView) + authorContainer.addArrangedSubview(UIView()) + authorContainer.addArrangedSubview(relationshipActionButtonShadowContainer) + relationshipActionButton.translatesAutoresizingMaskIntoConstraints = false - authorContainer.addArrangedSubview(relationshipActionButton) + relationshipActionButtonShadowContainer.addSubview(relationshipActionButton) NSLayoutConstraint.activate([ + relationshipActionButton.topAnchor.constraint(equalTo: relationshipActionButtonShadowContainer.topAnchor), + relationshipActionButton.leadingAnchor.constraint(equalTo: relationshipActionButtonShadowContainer.leadingAnchor), + relationshipActionButton.trailingAnchor.constraint(equalTo: relationshipActionButtonShadowContainer.trailingAnchor), + relationshipActionButton.bottomAnchor.constraint(equalTo: relationshipActionButtonShadowContainer.bottomAnchor), relationshipActionButton.widthAnchor.constraint(greaterThanOrEqualToConstant: ProfileHeaderView.friendshipActionButtonSize.width).priority(.required - 1), relationshipActionButton.heightAnchor.constraint(equalToConstant: ProfileHeaderView.friendshipActionButtonSize.height).priority(.defaultHigh), ]) @@ -426,10 +401,37 @@ extension ProfileHeaderView { relationshipActionButton.addTarget(self, action: #selector(ProfileHeaderView.relationshipActionButtonDidPressed(_:)), for: .touchUpInside) configure(state: .normal) + + updateLayoutMargins() + } + + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + + updateLayoutMargins() } } +extension ProfileHeaderView { + private func updateLayoutMargins() { + let margin: CGFloat = { + switch traitCollection.userInterfaceIdiom { + case .phone: + return ProfileViewController.containerViewMarginForCompactHorizontalSizeClass + default: + return traitCollection.horizontalSizeClass == .regular ? + ProfileViewController.containerViewMarginForRegularHorizontalSizeClass : + ProfileViewController.containerViewMarginForCompactHorizontalSizeClass + } + }() + + layoutMargins.left = margin + layoutMargins.right = margin + } + +} + extension ProfileHeaderView { enum State { case normal diff --git a/Mastodon/Scene/Profile/Header/View/ProfileRelationshipActionButton.swift b/Mastodon/Scene/Profile/Header/View/ProfileRelationshipActionButton.swift index fffb061b..87c189a4 100644 --- a/Mastodon/Scene/Profile/Header/View/ProfileRelationshipActionButton.swift +++ b/Mastodon/Scene/Profile/Header/View/ProfileRelationshipActionButton.swift @@ -7,12 +7,13 @@ import UIKit import MastodonUI +import MastodonAsset final class ProfileRelationshipActionButton: RoundedEdgesButton { let activityIndicatorView: UIActivityIndicatorView = { let activityIndicatorView = UIActivityIndicatorView(style: .medium) - activityIndicatorView.color = .white + activityIndicatorView.color = Asset.Colors.Label.primaryReverse.color return activityIndicatorView }() @@ -30,6 +31,7 @@ final class ProfileRelationshipActionButton: RoundedEdgesButton { extension ProfileRelationshipActionButton { private func _init() { + cornerRadius = 10 titleLabel?.font = .systemFont(ofSize: 17, weight: .semibold) activityIndicatorView.translatesAutoresizingMaskIntoConstraints = false @@ -41,17 +43,22 @@ extension ProfileRelationshipActionButton { activityIndicatorView.hidesWhenStopped = true activityIndicatorView.stopAnimating() + + configureAppearance() + } + + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + + configureAppearance() } } extension ProfileRelationshipActionButton { func configure(actionOptionSet: ProfileViewModel.RelationshipActionOptionSet) { setTitle(actionOptionSet.title, for: .normal) - setTitleColor(.white, for: .normal) - setTitleColor(UIColor.white.withAlphaComponent(0.5), for: .highlighted) - setBackgroundImage(.placeholder(color: actionOptionSet.backgroundColor), for: .normal) - setBackgroundImage(.placeholder(color: actionOptionSet.backgroundColor.withAlphaComponent(0.5)), for: .highlighted) - setBackgroundImage(.placeholder(color: actionOptionSet.backgroundColor.withAlphaComponent(0.5)), for: .disabled) + + configureAppearance() titleEdgeInsets = UIEdgeInsets(top: 0, left: 4, bottom: 0, right: 4) @@ -66,5 +73,23 @@ extension ProfileRelationshipActionButton { isEnabled = true } } + + private func configureAppearance() { + setTitleColor(Asset.Colors.Label.primaryReverse.color, for: .normal) + setTitleColor(Asset.Colors.Label.primaryReverse.color.withAlphaComponent(0.5), for: .highlighted) + switch traitCollection.userInterfaceStyle { + case .dark: + setBackgroundImage(.placeholder(color: Asset.Scene.Profile.RelationshipButton.backgroundDark.color), for: .normal) + setBackgroundImage(.placeholder(color: Asset.Scene.Profile.RelationshipButton.backgroundHighlightedDark.color), for: .highlighted) + setBackgroundImage(.placeholder(color: Asset.Scene.Profile.RelationshipButton.backgroundHighlightedDark.color), for: .disabled) + default: + setBackgroundImage(.placeholder(color: Asset.Scene.Profile.RelationshipButton.backgroundLight.color), for: .normal) + setBackgroundImage(.placeholder(color: Asset.Scene.Profile.RelationshipButton.backgroundHighlightedLight.color), for: .highlighted) + setBackgroundImage(.placeholder(color: Asset.Scene.Profile.RelationshipButton.backgroundHighlightedLight.color), for: .disabled) + } +// setBackgroundImage(.placeholder(color: actionOptionSet.backgroundColor), for: .normal) +// setBackgroundImage(.placeholder(color: actionOptionSet.backgroundColor.withAlphaComponent(0.5)), for: .highlighted) +// setBackgroundImage(.placeholder(color: actionOptionSet.backgroundColor.withAlphaComponent(0.5)), for: .disabled) + } } diff --git a/Mastodon/Scene/Profile/Header/View/ProfileStatusDashboardView.swift b/Mastodon/Scene/Profile/Header/View/ProfileStatusDashboardView.swift index 5bb23b0b..9448f196 100644 --- a/Mastodon/Scene/Profile/Header/View/ProfileStatusDashboardView.swift +++ b/Mastodon/Scene/Profile/Header/View/ProfileStatusDashboardView.swift @@ -75,6 +75,9 @@ extension ProfileStatusDashboardView { tapGestureRecognizer.addTarget(self, action: #selector(ProfileStatusDashboardView.tapGestureRecognizerHandler(_:))) meterView.addGestureRecognizer(tapGestureRecognizer) } + + followingDashboardMeterView.accessibilityHint = "Double tap to open the list" // TODO: i18n + followersDashboardMeterView.accessibilityHint = "Double tap to open the list" } } diff --git a/Mastodon/Scene/Profile/ProfileViewController.swift b/Mastodon/Scene/Profile/ProfileViewController.swift index 8fe8ad2b..a890505e 100644 --- a/Mastodon/Scene/Profile/ProfileViewController.swift +++ b/Mastodon/Scene/Profile/ProfileViewController.swift @@ -22,6 +22,9 @@ protocol ProfileViewModelEditable { final class ProfileViewController: UIViewController, NeedsDependency, MediaPreviewableViewController { + public static let containerViewMarginForRegularHorizontalSizeClass: CGFloat = 64 + public static let containerViewMarginForCompactHorizontalSizeClass: CGFloat = 16 + let logger = Logger(subsystem: "ProfileViewController", category: "ViewController") weak var context: AppContext! { willSet { precondition(!isViewLoaded) } } @@ -279,13 +282,14 @@ extension ProfileViewController { self.profileHeaderViewController.view.addSubview(buttonBar) NSLayoutConstraint.activate([ buttonBar.topAnchor.constraint(equalTo: self.profileHeaderViewController.profileHeaderView.bottomAnchor), - buttonBar.leadingAnchor.constraint(equalToSystemSpacingAfter: self.profileHeaderViewController.view.leadingAnchor, multiplier: 2.0), - buttonBar.trailingAnchor.constraint(equalTo: self.profileHeaderViewController.view.layoutMarginsGuide.trailingAnchor), + buttonBar.leadingAnchor.constraint(equalTo: self.profileHeaderViewController.view.leadingAnchor), + buttonBar.trailingAnchor.constraint(equalTo: self.profileHeaderViewController.view.trailingAnchor), buttonBar.bottomAnchor.constraint(equalTo: self.profileHeaderViewController.view.bottomAnchor), buttonBar.heightAnchor.constraint(equalToConstant: ProfileHeaderViewController.segmentedControlHeight).priority(.required - 1), ]) }) ) + updateBarButtonInsets() overlayScrollView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(overlayScrollView) @@ -375,9 +379,12 @@ extension ProfileViewController { viewModel.viewDidAppear.send() // set overlay scroll view initial content size - guard let currentViewController = profileSegmentedViewController.pagingViewController.currentViewController as? ScrollViewContainer else { return } - currentPostTimelineTableViewContentSizeObservation = observeTableViewContentSize(scrollView: currentViewController.scrollView) - currentViewController.scrollView.panGestureRecognizer.require(toFail: overlayScrollView.panGestureRecognizer) + guard let currentViewController = profileSegmentedViewController.pagingViewController.currentViewController as? ScrollViewContainer, + let scrollView = currentViewController.scrollView + else { return } + + currentPostTimelineTableViewContentSizeObservation = observeTableViewContentSize(scrollView: scrollView) + scrollView.panGestureRecognizer.require(toFail: overlayScrollView.panGestureRecognizer) } override func viewDidDisappear(_ animated: Bool) { @@ -386,6 +393,31 @@ extension ProfileViewController { currentPostTimelineTableViewContentSizeObservation = nil } + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + + updateBarButtonInsets() + } + +} + +extension ProfileViewController { + private func updateBarButtonInsets() { + let margin: CGFloat = { + switch traitCollection.userInterfaceIdiom { + case .phone: + return ProfileViewController.containerViewMarginForCompactHorizontalSizeClass + default: + return traitCollection.horizontalSizeClass == .regular ? + ProfileViewController.containerViewMarginForRegularHorizontalSizeClass : + ProfileViewController.containerViewMarginForCompactHorizontalSizeClass + } + }() + + profileHeaderViewController.buttonBar.layout.contentInset.left = margin + profileHeaderViewController.buttonBar.layout.contentInset.right = margin + } + } extension ProfileViewController { @@ -616,7 +648,7 @@ extension ProfileViewController { .receive(on: DispatchQueue.main) .sink { [weak self] isHidden in guard let self = self else { return } - self.profileHeaderViewController.profileHeaderView.relationshipActionButton.isHidden = isHidden + self.profileHeaderViewController.profileHeaderView.relationshipActionButtonShadowContainer.isHidden = isHidden } .store(in: &disposeBag) @@ -787,7 +819,7 @@ extension ProfileViewController: UIScrollViewDelegate { if scrollView.contentOffset.y < topMaxContentOffsetY { self.containerScrollView.contentOffset.y = scrollView.contentOffset.y for postTimelineView in profileSegmentedViewController.pagingViewController.viewModel.viewControllers { - postTimelineView.scrollView.contentOffset.y = 0 + postTimelineView.scrollView?.contentOffset.y = 0 } contentOffsets.removeAll() } else { @@ -797,7 +829,7 @@ extension ProfileViewController: UIScrollViewDelegate { } else { if let customScrollViewContainerController = profileSegmentedViewController.pagingViewController.currentViewController as? ScrollViewContainer { let contentOffsetY = scrollView.contentOffset.y - containerScrollView.contentOffset.y - customScrollViewContainerController.scrollView.contentOffset.y = contentOffsetY + customScrollViewContainerController.scrollView?.contentOffset.y = contentOffsetY } } @@ -840,8 +872,10 @@ extension ProfileViewController: ProfilePagingViewControllerDelegate { overlayScrollView.contentOffset.y = contentOffsets[index] ?? containerScrollView.contentOffset.y // setup observer and gesture fallback - currentPostTimelineTableViewContentSizeObservation = observeTableViewContentSize(scrollView: postTimelineViewController.scrollView) - postTimelineViewController.scrollView.panGestureRecognizer.require(toFail: overlayScrollView.panGestureRecognizer) + if let scrollView = postTimelineViewController.scrollView { + currentPostTimelineTableViewContentSizeObservation = observeTableViewContentSize(scrollView: scrollView) + scrollView.panGestureRecognizer.require(toFail: overlayScrollView.panGestureRecognizer) + } } } @@ -997,8 +1031,8 @@ extension ProfileViewController: ProfileHeaderViewDelegate { let name = user.displayNameWithFallback let alertController = UIAlertController( - title: L10n.Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.title, - message: L10n.Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.message(name), + title: L10n.Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.title, + message: L10n.Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.message(name), preferredStyle: .alert ) let record = ManagedObjectRecord<MastodonUser>(objectID: user.objectID) @@ -1098,20 +1132,22 @@ extension ProfileViewController: MastodonMenuDelegate { } // MARK: - ScrollViewContainer -//extension ProfileViewController: ScrollViewContainer { -// var scrollView: UIScrollView { return overlayScrollView } -//} -// +extension ProfileViewController: ScrollViewContainer { + var scrollView: UIScrollView? { + return overlayScrollView + } +} + //extension ProfileViewController { -// +// // override var keyCommands: [UIKeyCommand]? { // if !viewModel.isEditing.value { // return segmentedControlNavigateKeyCommands // } -// +// // return nil // } -// +// //} // MARK: - SegmentedControlNavigateable diff --git a/Mastodon/Scene/Profile/ProfileViewModel.swift b/Mastodon/Scene/Profile/ProfileViewModel.swift index 588651c8..403437da 100644 --- a/Mastodon/Scene/Profile/ProfileViewModel.swift +++ b/Mastodon/Scene/Profile/ProfileViewModel.swift @@ -442,6 +442,7 @@ extension ProfileViewModel { } } + @available(*, deprecated, message: "") var backgroundColor: UIColor { guard let highPriorityAction = self.highPriorityAction(except: []) else { assertionFailure() diff --git a/Mastodon/Scene/Profile/Segmented/Paging/ProfilePagingViewModel.swift b/Mastodon/Scene/Profile/Segmented/Paging/ProfilePagingViewModel.swift index 0df9688d..e5220ef7 100644 --- a/Mastodon/Scene/Profile/Segmented/Paging/ProfilePagingViewModel.swift +++ b/Mastodon/Scene/Profile/Segmented/Paging/ProfilePagingViewModel.swift @@ -44,9 +44,9 @@ final class ProfilePagingViewModel: NSObject { let barItems: [TMBarItemable] = { let items = [ TMBarItem(title: L10n.Scene.Profile.SegmentedControl.posts), - TMBarItem(title: "Posts and Replies"), // TODO: i18n + TMBarItem(title: L10n.Scene.Profile.SegmentedControl.postsAndReplies), // TODO: i18n TMBarItem(title: L10n.Scene.Profile.SegmentedControl.media), - TMBarItem(title: "About"), + TMBarItem(title: L10n.Scene.Profile.SegmentedControl.about), ] return items }() diff --git a/Mastodon/Scene/Profile/Timeline/UserTimelineViewController.swift b/Mastodon/Scene/Profile/Timeline/UserTimelineViewController.swift index 0b836da7..12925ca4 100644 --- a/Mastodon/Scene/Profile/Timeline/UserTimelineViewController.swift +++ b/Mastodon/Scene/Profile/Timeline/UserTimelineViewController.swift @@ -26,17 +26,14 @@ final class UserTimelineViewController: UIViewController, NeedsDependency, Media lazy var tableView: UITableView = { let tableView = UITableView() - tableView.register(StatusTableViewCell.self, forCellReuseIdentifier: String(describing: StatusTableViewCell.self)) - tableView.register(TimelineBottomLoaderTableViewCell.self, forCellReuseIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self)) - tableView.register(TimelineHeaderTableViewCell.self, forCellReuseIdentifier: String(describing: TimelineHeaderTableViewCell.self)) tableView.rowHeight = UITableView.automaticDimension tableView.estimatedRowHeight = 100 tableView.separatorStyle = .none tableView.backgroundColor = .clear return tableView }() - - var overrideNavigationScrollPosition: UITableView.ScrollPosition? = nil + + let cellFrameCache = NSCache<NSNumber, NSValue>() deinit { os_log("%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function) @@ -93,6 +90,16 @@ extension UserTimelineViewController { } +// MARK: - CellFrameCacheContainer +extension UserTimelineViewController: CellFrameCacheContainer { + func keyForCache(tableView: UITableView, indexPath: IndexPath) -> NSNumber? { + guard let diffableDataSource = viewModel.diffableDataSource else { return nil } + guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return nil } + let key = NSNumber(value: item.hashValue) + return key + } +} + // MARK: - UITableViewDelegate extension UserTimelineViewController: UITableViewDelegate, AutoGenerateTableViewDelegate { // sourcery:inline:UserTimelineViewController.AutoGenerateTableViewDelegate @@ -121,12 +128,40 @@ extension UserTimelineViewController: UITableViewDelegate, AutoGenerateTableView // sourcery:end + func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { + guard let frame = retrieveCellFrame(tableView: tableView, indexPath: indexPath) else { + return 200 + } + return ceil(frame.height) + } + + func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) { + cacheCellFrame(tableView: tableView, didEndDisplaying: cell, forRowAt: indexPath) + } + } // MARK: - CustomScrollViewContainerController extension UserTimelineViewController: ScrollViewContainer { - var scrollView: UIScrollView { return tableView } + var scrollView: UIScrollView? { return tableView } } // MARK: - StatusTableViewCellDelegate extension UserTimelineViewController: StatusTableViewCellDelegate { } + +extension UserTimelineViewController { + override var keyCommands: [UIKeyCommand]? { + return navigationKeyCommands + statusNavigationKeyCommands + } +} + +// MARK: - StatusTableViewControllerNavigateable +extension UserTimelineViewController: StatusTableViewControllerNavigateable { + @objc func navigateKeyCommandHandlerRelay(_ sender: UIKeyCommand) { + navigateKeyCommandHandler(sender) + } + + @objc func statusKeyCommandHandlerRelay(_ sender: UIKeyCommand) { + statusKeyCommandHandler(sender) + } +} diff --git a/Mastodon/Scene/Profile/Timeline/UserTimelineViewModel+Diffable.swift b/Mastodon/Scene/Profile/Timeline/UserTimelineViewModel+Diffable.swift index 56d0973e..a0a1f52c 100644 --- a/Mastodon/Scene/Profile/Timeline/UserTimelineViewModel+Diffable.swift +++ b/Mastodon/Scene/Profile/Timeline/UserTimelineViewModel+Diffable.swift @@ -19,7 +19,9 @@ extension UserTimelineViewModel { context: context, configuration: StatusSection.Configuration( statusTableViewCellDelegate: statusTableViewCellDelegate, - timelineMiddleLoaderTableViewCellDelegate: nil + timelineMiddleLoaderTableViewCellDelegate: nil, + filterContext: .none, + activeFilters: nil ) ) diff --git a/Mastodon/Scene/Report/ReportResult/ReportResultViewController.swift b/Mastodon/Scene/Report/ReportResult/ReportResultViewController.swift index 6970b856..26f56b98 100644 --- a/Mastodon/Scene/Report/ReportResult/ReportResultViewController.swift +++ b/Mastodon/Scene/Report/ReportResult/ReportResultViewController.swift @@ -39,7 +39,7 @@ final class ReportResultViewController: UIViewController, NeedsDependency, Repor let navigationActionView: NavigationActionView = { let navigationActionView = NavigationActionView() - navigationActionView.backgroundColor = Asset.Scene.Onboarding.onboardingBackground.color + navigationActionView.backgroundColor = Asset.Scene.Onboarding.background.color navigationActionView.hidesBackButton = true navigationActionView.nextButton.setTitle(L10n.Common.Controls.Actions.done, for: .normal) return navigationActionView diff --git a/Mastodon/Scene/Report/ReportStatus/ReportViewController.swift b/Mastodon/Scene/Report/ReportStatus/ReportViewController.swift index 4cb1f56f..12291a96 100644 --- a/Mastodon/Scene/Report/ReportStatus/ReportViewController.swift +++ b/Mastodon/Scene/Report/ReportStatus/ReportViewController.swift @@ -47,7 +47,7 @@ class ReportViewController: UIViewController, NeedsDependency, ReportViewControl let navigationActionView: NavigationActionView = { let navigationActionView = NavigationActionView() - navigationActionView.backgroundColor = Asset.Scene.Onboarding.onboardingBackground.color + navigationActionView.backgroundColor = Asset.Scene.Onboarding.background.color navigationActionView.backButton.setTitle(L10n.Common.Controls.Actions.skip, for: .normal) return navigationActionView }() diff --git a/Mastodon/Scene/Report/ReportSupplementary/ReportSupplementaryViewController.swift b/Mastodon/Scene/Report/ReportSupplementary/ReportSupplementaryViewController.swift index 44545dd2..4f6e102b 100644 --- a/Mastodon/Scene/Report/ReportSupplementary/ReportSupplementaryViewController.swift +++ b/Mastodon/Scene/Report/ReportSupplementary/ReportSupplementaryViewController.swift @@ -55,7 +55,7 @@ final class ReportSupplementaryViewController: UIViewController, NeedsDependency let navigationActionView: NavigationActionView = { let navigationActionView = NavigationActionView() - navigationActionView.backgroundColor = Asset.Scene.Onboarding.onboardingBackground.color + navigationActionView.backgroundColor = Asset.Scene.Onboarding.background.color navigationActionView.backButton.setTitle(L10n.Common.Controls.Actions.skip, for: .normal) return navigationActionView }() diff --git a/Mastodon/Scene/Report/Share/Cell/ReportResultActionTableViewCell.swift b/Mastodon/Scene/Report/Share/Cell/ReportResultActionTableViewCell.swift index 7c0d84f0..9b605a0c 100644 --- a/Mastodon/Scene/Report/Share/Cell/ReportResultActionTableViewCell.swift +++ b/Mastodon/Scene/Report/Share/Cell/ReportResultActionTableViewCell.swift @@ -31,7 +31,7 @@ final class ReportResultActionTableViewCell: UITableViewCell { let reportBannerLabel: UILabel = { let label = UILabel() let padding = Array(repeating: " ", count: 2).joined() - label.text = padding + "Reported" + padding // TODO: i18n + label.text = padding + L10n.Scene.Report.reported + padding label.textColor = Asset.Scene.Report.reportBanner.color label.font = FontFamily.Staatliches.regular.font(size: 49) label.backgroundColor = Asset.Scene.Report.background.color diff --git a/Mastodon/Scene/Report/Share/ReportViewControllerAppearance.swift b/Mastodon/Scene/Report/Share/ReportViewControllerAppearance.swift index 7bdaba64..6b35f3d8 100644 --- a/Mastodon/Scene/Report/Share/ReportViewControllerAppearance.swift +++ b/Mastodon/Scene/Report/Share/ReportViewControllerAppearance.swift @@ -19,7 +19,7 @@ extension ReportViewControllerAppearance { func setupAppearance() { - title = "Report" // TODO: i18n + title = L10n.Scene.Report.titleReport view.backgroundColor = Asset.Scene.Report.background.color setupNavigationBarAppearance() diff --git a/Mastodon/Scene/Root/RootSplitViewController.swift b/Mastodon/Scene/Root/RootSplitViewController.swift index e9d7549b..d9b18b0b 100644 --- a/Mastodon/Scene/Root/RootSplitViewController.swift +++ b/Mastodon/Scene/Root/RootSplitViewController.swift @@ -101,12 +101,7 @@ extension RootSplitViewController { override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) - coordinator.animate { [weak self] context in - guard let self = self else { return } - self.updateBehavior(size: size) - } completion: { context in - // do nothing - } + self.updateBehavior(size: size) } override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { diff --git a/Mastodon/Scene/Search/Search/Cell/TrendCollectionViewCell.swift b/Mastodon/Scene/Search/Search/Cell/TrendCollectionViewCell.swift index 48a7606b..a43d65df 100644 --- a/Mastodon/Scene/Search/Search/Cell/TrendCollectionViewCell.swift +++ b/Mastodon/Scene/Search/Search/Cell/TrendCollectionViewCell.swift @@ -132,3 +132,4 @@ extension TrendCollectionViewCell { } } + diff --git a/Mastodon/Scene/Search/Search/Cell/TrendSectionHeaderCollectionReusableView.swift b/Mastodon/Scene/Search/Search/Cell/TrendSectionHeaderCollectionReusableView.swift index 4632f384..9d21ee28 100644 --- a/Mastodon/Scene/Search/Search/Cell/TrendSectionHeaderCollectionReusableView.swift +++ b/Mastodon/Scene/Search/Search/Cell/TrendSectionHeaderCollectionReusableView.swift @@ -23,6 +23,7 @@ final class TrendSectionHeaderCollectionReusableView: UICollectionReusableView { label.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 22, weight: .bold)) label.textColor = Asset.Colors.Label.primary.color label.text = L10n.Scene.Search.Recommend.HashTag.title + label.numberOfLines = 0 return label }() diff --git a/Mastodon/Scene/Search/SearchDetail/SearchResult/SearchResultViewModel.swift b/Mastodon/Scene/Search/SearchDetail/SearchResult/SearchResultViewModel.swift index 7641bc0c..ad012518 100644 --- a/Mastodon/Scene/Search/SearchDetail/SearchResult/SearchResultViewModel.swift +++ b/Mastodon/Scene/Search/SearchDetail/SearchResult/SearchResultViewModel.swift @@ -53,7 +53,7 @@ final class SearchResultViewModel { self.userFetchedResultsController = UserFetchedResultsController( managedObjectContext: context.managedObjectContext, domain: nil, - additionalTweetPredicate: nil + additionalPredicate: nil ) self.statusFetchedResultsController = StatusFetchedResultsController( managedObjectContext: context.managedObjectContext, diff --git a/Mastodon/Scene/Settings/Cell/SettingsAppearanceTableViewCell+ViewModel.swift b/Mastodon/Scene/Settings/Cell/SettingsAppearanceTableViewCell+ViewModel.swift index f73be235..153ed890 100644 --- a/Mastodon/Scene/Settings/Cell/SettingsAppearanceTableViewCell+ViewModel.swift +++ b/Mastodon/Scene/Settings/Cell/SettingsAppearanceTableViewCell+ViewModel.swift @@ -51,11 +51,7 @@ extension SettingsAppearanceTableViewCell.ViewModel { case .unspecified: cell.systemAppearanceView.selected = true case .dark: - if preferredTrueBlackDarkMode { - cell.reallyDarkAppearanceView.selected = true - } else { - cell.sortaDarkAppearanceView.selected = true - } + cell.darkAppearanceView.selected = true case .light: cell.lightAppearanceView.selected = true @unknown default: diff --git a/Mastodon/Scene/Settings/Cell/SettingsAppearanceTableViewCell.swift b/Mastodon/Scene/Settings/Cell/SettingsAppearanceTableViewCell.swift index b808d1c4..3760fd8e 100644 --- a/Mastodon/Scene/Settings/Cell/SettingsAppearanceTableViewCell.swift +++ b/Mastodon/Scene/Settings/Cell/SettingsAppearanceTableViewCell.swift @@ -38,27 +38,22 @@ class SettingsAppearanceTableViewCell: UITableViewCell { }() let systemAppearanceView = AppearanceView( - image: Asset.Settings.darkAuto.image, - title: "Use System" // TODO: i18n + image: Asset.Settings.automatic.image, + title: L10n.Scene.Settings.Section.Appearance.automatic ) - let reallyDarkAppearanceView = AppearanceView( + let darkAppearanceView = AppearanceView( image: Asset.Settings.dark.image, - title: "Really Dark" - ) - let sortaDarkAppearanceView = AppearanceView( - image: Asset.Settings.dark.image, - title: "Sorta Dark" + title: L10n.Scene.Settings.Section.Appearance.dark ) let lightAppearanceView = AppearanceView( image: Asset.Settings.light.image, - title: "Light" + title: L10n.Scene.Settings.Section.Appearance.light ) var appearanceViews: [AppearanceView] { return [ systemAppearanceView, - reallyDarkAppearanceView, - sortaDarkAppearanceView, + darkAppearanceView, lightAppearanceView, ] } @@ -105,14 +100,13 @@ extension SettingsAppearanceTableViewCell { contentView.addSubview(stackView) NSLayoutConstraint.activate([ stackView.topAnchor.constraint(equalTo: contentView.topAnchor), - stackView.leadingAnchor.constraint(equalTo: contentView.readableContentGuide.leadingAnchor), + stackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), stackView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - stackView.trailingAnchor.constraint(equalTo: contentView.readableContentGuide.trailingAnchor), + stackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor), ]) stackView.addArrangedSubview(systemAppearanceView) - stackView.addArrangedSubview(reallyDarkAppearanceView) - stackView.addArrangedSubview(sortaDarkAppearanceView) + stackView.addArrangedSubview(darkAppearanceView) stackView.addArrangedSubview(lightAppearanceView) appearanceViews.forEach { view in @@ -132,10 +126,8 @@ extension SettingsAppearanceTableViewCell { switch sender.view { case systemAppearanceView: mode = .system - case reallyDarkAppearanceView: - mode = .reallyDark - case sortaDarkAppearanceView: - mode = .sortaDark + case darkAppearanceView: + mode = .dark case lightAppearanceView: mode = .light default: diff --git a/Mastodon/Scene/Settings/Cell/SettingsToggleTableViewCell.swift b/Mastodon/Scene/Settings/Cell/SettingsToggleTableViewCell.swift index 419f24d6..4926dbfc 100644 --- a/Mastodon/Scene/Settings/Cell/SettingsToggleTableViewCell.swift +++ b/Mastodon/Scene/Settings/Cell/SettingsToggleTableViewCell.swift @@ -20,7 +20,6 @@ class SettingsToggleTableViewCell: UITableViewCell { private(set) lazy var switchButton: UISwitch = { let view = UISwitch(frame:.zero) - view.onTintColor = contentView.window?.tintColor ?? .label return view }() @@ -49,8 +48,15 @@ class SettingsToggleTableViewCell: UITableViewCell { accessoryView = switchButton textLabel?.numberOfLines = 0 + updateAppearance() switchButton.addTarget(self, action: #selector(switchValueDidChange(sender:)), for: .valueChanged) } + + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + super.traitCollectionDidChange(previousTraitCollection) + + updateAppearance() + } } @@ -72,4 +78,16 @@ extension SettingsToggleTableViewCell { switchButton.isOn = enabled ?? false } + private func updateAppearance() { + switchButton.onTintColor = { + switch traitCollection.userInterfaceStyle { + case .dark: + // set default green for Dark Mode + return nil + default: + // set tint black for Light Mode + return self.contentView.window?.tintColor ?? nil + } + }() + } } diff --git a/Mastodon/Scene/Settings/SettingsViewController.swift b/Mastodon/Scene/Settings/SettingsViewController.swift index 172602c3..4cf20cd0 100644 --- a/Mastodon/Scene/Settings/SettingsViewController.swift +++ b/Mastodon/Scene/Settings/SettingsViewController.swift @@ -99,14 +99,8 @@ class SettingsViewController: UIViewController, NeedsDependency { }() private(set) lazy var tableView: UITableView = { - let style: UITableView.Style = { - switch UIDevice.current.userInterfaceIdiom { - case .phone: return .grouped - default: return .insetGrouped - } - }() // init with a frame to fix a conflict ('UIView-Encapsulated-Layout-Width' UIStackView:0x7f8c2b6c0590.width == 0) - let tableView = UITableView(frame: CGRect(x: 0, y: 0, width: 320, height: 320), style: style) + let tableView = UITableView(frame: CGRect(x: 0, y: 0, width: 320, height: 320), style: .insetGrouped) tableView.translatesAutoresizingMaskIntoConstraints = false tableView.delegate = self tableView.rowHeight = UITableView.automaticDimension @@ -212,8 +206,7 @@ extension SettingsViewController { } .store(in: &disposeBag) - - let footer = "Mastodon v\(UIApplication.appVersion()) (\(UIApplication.appBuild()))" + let footer = "Mastodon for iOS v\(UIApplication.appVersion()) (\(UIApplication.appBuild()))" let metaContent = PlaintextMetaContent(string: footer) tableFooterLabel.configure(content: metaContent) } @@ -328,6 +321,10 @@ extension SettingsViewController: UITableViewDelegate { let header: SettingsSectionHeader switch sectionIdentifier { + case .appearancePreference: + return UIView() + case .preference: + return UIView() case .notifications: header = SettingsSectionHeader( frame: CGRect(x: 0, y: 0, width: 375, height: 66), @@ -360,6 +357,9 @@ extension SettingsViewController: UITableViewDelegate { case .appearance: // do nothing break + case .appearancePreference: + // do nothing + break case .notification: // do nothing break @@ -450,28 +450,16 @@ extension SettingsViewController: SettingsAppearanceTableViewCellDelegate { let item = dataSource.itemIdentifier(for: indexPath) guard case let .appearance(record) = item else { return } - Task { @MainActor in - var preferredTrueBlackDarkMode = false - + Task { @MainActor in switch appearanceMode { case .system: UserDefaults.shared.customUserInterfaceStyle = .unspecified - case .reallyDark: - UserDefaults.shared.customUserInterfaceStyle = .dark - preferredTrueBlackDarkMode = true - case .sortaDark: + case .dark: UserDefaults.shared.customUserInterfaceStyle = .dark case .light: UserDefaults.shared.customUserInterfaceStyle = .light } - let managedObjectContext = context.managedObjectContext - try await managedObjectContext.performChanges { - guard let setting = record.object(in: managedObjectContext) else { return } - setting.update(preferredTrueBlackDarkMode: preferredTrueBlackDarkMode) - } - ThemeService.shared.set(themeName: preferredTrueBlackDarkMode ? .system : .mastodon) - let feedbackGenerator = UIImpactFeedbackGenerator(style: .light) feedbackGenerator.impactOccurred() } // end Task @@ -507,6 +495,18 @@ extension SettingsViewController: SettingsToggleCellDelegate { // do nothing } .store(in: &disposeBag) + case .appearancePreference(let record, let appearanceType): + switch appearanceType { + case .preferredTrueDarkMode: + Task { + let managedObjectContext = context.managedObjectContext + try await managedObjectContext.performChanges { + guard let setting = record.object(in: managedObjectContext) else { return } + setting.update(preferredTrueBlackDarkMode: isOn) + } + ThemeService.shared.set(themeName: isOn ? .system : .mastodon) + } // end Task + } case .preference(let record, let preferenceType): let managedObjectContext = context.backgroundManagedObjectContext managedObjectContext.performChanges { diff --git a/Mastodon/Scene/Settings/SettingsViewModel.swift b/Mastodon/Scene/Settings/SettingsViewModel.swift index 9f9640b7..1eb9a409 100644 --- a/Mastodon/Scene/Settings/SettingsViewModel.swift +++ b/Mastodon/Scene/Settings/SettingsViewModel.swift @@ -108,10 +108,16 @@ extension SettingsViewModel { var snapshot = NSDiffableDataSourceSnapshot<SettingsSection, SettingsItem>() // appearance - let appearanceItems = [SettingsItem.appearance(record: .init(objectID: setting.objectID))] + let appearanceItems = [ + SettingsItem.appearance(record: .init(objectID: setting.objectID)) + ] snapshot.appendSections([.appearance]) snapshot.appendItems(appearanceItems, toSection: .appearance) + // appearancePreference + snapshot.appendSections([.appearancePreference]) + snapshot.appendItems([SettingsItem.appearancePreference(record: .init(objectID: setting.objectID), appearanceType: .preferredTrueDarkMode)], toSection: .appearancePreference) + // preference snapshot.appendSections([.preference]) let preferenceItems: [SettingsItem] = SettingsItem.PreferenceType.allCases.map { preferenceType in diff --git a/Mastodon/Scene/Settings/View/AppearanceView.swift b/Mastodon/Scene/Settings/View/AppearanceView.swift index c29ae96e..cdc29100 100644 --- a/Mastodon/Scene/Settings/View/AppearanceView.swift +++ b/Mastodon/Scene/Settings/View/AppearanceView.swift @@ -8,14 +8,16 @@ import UIKit import MastodonAsset import MastodonLocalization +import MastodonUI class AppearanceView: UIView { + let imageViewShadowBackgroundContainer = ShadowBackgroundContainer() lazy var imageView: UIImageView = { let view = UIImageView() view.contentMode = .scaleAspectFill view.layer.masksToBounds = true - view.layer.cornerRadius = 8 + view.layer.cornerRadius = 4 view.layer.cornerCurve = .continuous // accessibility view.accessibilityIgnoresInvertColors = true @@ -29,6 +31,17 @@ class AppearanceView: UIView { label.textAlignment = .center return label }() + + lazy var checkmarkButton: UIButton = { + let button = UIButton() + button.isUserInteractionEnabled = false + button.setImage(UIImage(systemName: "circle"), for: .normal) + button.setImage(UIImage(systemName: "checkmark.circle.fill"), for: .selected) + button.imageView?.preferredSymbolConfiguration = UIImage.SymbolConfiguration(textStyle: .body) + button.imageView?.tintColor = Asset.Colors.Label.primary.color + button.imageView?.contentMode = .scaleAspectFill + return button + }() lazy var stackView: UIStackView = { let view = UIStackView() @@ -70,8 +83,19 @@ class AppearanceView: UIView { extension AppearanceView { private func setupUI() { - stackView.addArrangedSubview(imageView) + imageView.translatesAutoresizingMaskIntoConstraints = false + imageViewShadowBackgroundContainer.addSubview(imageView) + NSLayoutConstraint.activate([ + imageView.topAnchor.constraint(equalTo: imageViewShadowBackgroundContainer.topAnchor), + imageView.leadingAnchor.constraint(equalTo: imageViewShadowBackgroundContainer.leadingAnchor), + imageView.trailingAnchor.constraint(equalTo: imageViewShadowBackgroundContainer.trailingAnchor), + imageView.bottomAnchor.constraint(equalTo: imageViewShadowBackgroundContainer.bottomAnchor), + ]) + imageViewShadowBackgroundContainer.cornerRadius = 4 + + stackView.addArrangedSubview(imageViewShadowBackgroundContainer) stackView.addArrangedSubview(titleLabel) + stackView.addArrangedSubview(checkmarkButton) addSubview(stackView) translatesAutoresizingMaskIntoConstraints = false @@ -81,20 +105,18 @@ extension AppearanceView { stackView.leadingAnchor.constraint(equalTo: self.leadingAnchor), stackView.bottomAnchor.constraint(equalTo: self.bottomAnchor), stackView.trailingAnchor.constraint(equalTo: self.trailingAnchor), - imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor, multiplier: 120.0 / 90.0), + imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor, multiplier: 121.0 / 100.0), // height / width ]) } private func configureForSelection() { if selected { - imageView.layer.borderWidth = 3 - imageView.layer.borderColor = Asset.Colors.Label.primary.color.cgColor accessibilityTraits.insert(.selected) } else { - imageView.layer.borderWidth = 1 - imageView.layer.borderColor = Asset.Colors.Label.primaryReverse.color.cgColor accessibilityTraits.remove(.selected) } + + checkmarkButton.isSelected = selected } override func layoutSubviews() { diff --git a/Mastodon/Scene/Share/View/Content/NotificationView+Configuration.swift b/Mastodon/Scene/Share/View/Content/NotificationView+Configuration.swift index 705e90a7..052dc44c 100644 --- a/Mastodon/Scene/Share/View/Content/NotificationView+Configuration.swift +++ b/Mastodon/Scene/Share/View/Content/NotificationView+Configuration.swift @@ -118,37 +118,37 @@ extension NotificationView { switch type { case .follow: self.viewModel.notificationIndicatorText = createMetaContent( - text: L10n.Scene.Notification.userFollowedYou(""), + text: L10n.Scene.Notification.NotificationDescription.followedYou, emojis: emojis.asDictionary ) case .followRequest: self.viewModel.notificationIndicatorText = createMetaContent( - text: L10n.Scene.Notification.userRequestedToFollowYou(author.displayNameWithFallback), + text: L10n.Scene.Notification.NotificationDescription.requestToFollowYou, emojis: emojis.asDictionary ) case .mention: self.viewModel.notificationIndicatorText = createMetaContent( - text: L10n.Scene.Notification.userMentionedYou(""), + text: L10n.Scene.Notification.NotificationDescription.mentionedYou, emojis: emojis.asDictionary ) case .reblog: self.viewModel.notificationIndicatorText = createMetaContent( - text: L10n.Scene.Notification.userRebloggedYourPost(""), + text: L10n.Scene.Notification.NotificationDescription.rebloggedYourPost, emojis: emojis.asDictionary ) case .favourite: self.viewModel.notificationIndicatorText = createMetaContent( - text: L10n.Scene.Notification.userFavoritedYourPost(""), + text: L10n.Scene.Notification.NotificationDescription.favoritedYourPost, emojis: emojis.asDictionary ) case .poll: self.viewModel.notificationIndicatorText = createMetaContent( - text: L10n.Scene.Notification.userYourPollHasEnded(""), + text: L10n.Scene.Notification.NotificationDescription.pollHasEnded, emojis: emojis.asDictionary ) case .status: self.viewModel.notificationIndicatorText = createMetaContent( - text: L10n.Scene.Notification.userMentionedYou(""), + text: L10n.Scene.Notification.NotificationDescription.mentionedYou, emojis: emojis.asDictionary ) case ._other: diff --git a/Mastodon/Scene/Share/View/Content/PollOptionView+Configuration.swift b/Mastodon/Scene/Share/View/Content/PollOptionView+Configuration.swift index a4183a83..717c35f8 100644 --- a/Mastodon/Scene/Share/View/Content/PollOptionView+Configuration.swift +++ b/Mastodon/Scene/Share/View/Content/PollOptionView+Configuration.swift @@ -20,7 +20,7 @@ extension PollOptionView { .receive(on: DispatchQueue.main) .sink { [weak self] theme in guard let self = self else { return } - self.viewModel.roundedBackgroundViewColor = theme.secondarySystemBackgroundColor + self.viewModel.roundedBackgroundViewColor = theme.systemElevatedBackgroundColor } .store(in: &disposeBag) // metaContent diff --git a/Mastodon/Scene/Share/View/Content/StatusView+Configuration.swift b/Mastodon/Scene/Share/View/Content/StatusView+Configuration.swift index 85105c2c..1a90c69a 100644 --- a/Mastodon/Scene/Share/View/Content/StatusView+Configuration.swift +++ b/Mastodon/Scene/Share/View/Content/StatusView+Configuration.swift @@ -9,11 +9,16 @@ import UIKit import Combine import MastodonUI import CoreDataStack +import MastodonSDK import MastodonLocalization import MastodonMeta import Meta +import NaturalLanguage extension StatusView { + + static let statusFilterWorkingQueue = DispatchQueue(label: "StatusFilterWorkingQueue") + public func configure(feed: Feed) { switch feed.kind { case .home: @@ -48,7 +53,8 @@ extension StatusView { configureContent(status: status) configureMedia(status: status) configurePoll(status: status) - configureToolbar(status: status) + configureToolbar(status: status) + configureFilter(status: status) } } @@ -60,7 +66,7 @@ extension StatusView { status.author.publisher(for: \.emojis) ) .map { name, emojis -> StatusView.ViewModel.Header in - let text = L10n.Common.Controls.Status.userReblogged(name) + let text = L10n.Common.Controls.Status.userReblogged(status.author.displayNameWithFallback) let content = MastodonContent(content: text, emojis: emojis.asDictionary) do { let metaContent = try MastodonMetaContent.convert(document: content) @@ -245,6 +251,8 @@ extension StatusView { } else { viewModel.spoilerContent = nil } + // language + viewModel.language = (status.reblog ?? status).language // content do { let content = MastodonContent(content: status.content, emojis: status.emojis.asDictionary) @@ -395,5 +403,58 @@ extension StatusView { .assign(to: \.isFavorite, on: viewModel) .store(in: &disposeBag) } + + private func configureFilter(status: Status) { + let status = status.reblog ?? status + + let content = status.content.lowercased() + + Publishers.CombineLatest( + viewModel.$activeFilters, + viewModel.$filterContext + ) + .receive(on: StatusView.statusFilterWorkingQueue) + .map { filters, filterContext in + var wordFilters: [Mastodon.Entity.Filter] = [] + var nonWordFilters: [Mastodon.Entity.Filter] = [] + for filter in filters { + guard filter.context.contains(where: { $0 == filterContext }) else { continue } + if filter.wholeWord { + wordFilters.append(filter) + } else { + nonWordFilters.append(filter) + } + } + + var needsFilter = false + for filter in nonWordFilters { + guard content.contains(filter.phrase.lowercased()) else { continue } + needsFilter = true + break + } + + if needsFilter { + return true + } + + let tokenizer = NLTokenizer(unit: .word) + tokenizer.string = content + let phraseWords = wordFilters.map { $0.phrase.lowercased() } + tokenizer.enumerateTokens(in: content.startIndex..<content.endIndex) { range, _ in + let word = String(content[range]) + if phraseWords.contains(word) { + needsFilter = true + return false + } else { + return true + } + } + + return needsFilter + } + .receive(on: DispatchQueue.main) + .assign(to: \.isFiltered, on: viewModel) + .store(in: &disposeBag) + } } diff --git a/Mastodon/Scene/Share/View/TableviewCell/AdaptiveMarginStatusTableViewCell.swift b/Mastodon/Scene/Share/View/TableviewCell/AdaptiveMarginStatusTableViewCell.swift deleted file mode 100644 index 78363d09..00000000 --- a/Mastodon/Scene/Share/View/TableviewCell/AdaptiveMarginStatusTableViewCell.swift +++ /dev/null @@ -1,45 +0,0 @@ -// -// AdaptiveMarginStatusTableViewCell.swift -// Mastodon -// -// Created by MainasuK on 2022-2-10. -// - -import UIKit -import MastodonUI - -protocol AdaptiveContainerMarginTableViewCell: UITableViewCell { - associatedtype ContainerView: UIView - static var containerViewMarginForRegularHorizontalSizeClass: CGFloat { get } - var containerView: ContainerView { get } - var containerViewLeadingLayoutConstraint: NSLayoutConstraint! { get set } - var containerViewTrailingLayoutConstraint: NSLayoutConstraint! { get set } -} - -extension AdaptiveContainerMarginTableViewCell { - - static var containerViewMarginForRegularHorizontalSizeClass: CGFloat { 64 } - - func setupContainerViewMarginConstraints() { - containerViewLeadingLayoutConstraint = containerView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor) - containerViewTrailingLayoutConstraint = contentView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor) - } - - func updateContainerViewMarginConstraints() { - guard traitCollection.userInterfaceIdiom != .phone, - traitCollection.horizontalSizeClass == .regular - else { - containerViewLeadingLayoutConstraint.constant = 0 - containerViewTrailingLayoutConstraint.constant = 0 - return - } - - containerViewLeadingLayoutConstraint.constant = Self.containerViewMarginForRegularHorizontalSizeClass - containerViewTrailingLayoutConstraint.constant = Self.containerViewMarginForRegularHorizontalSizeClass - } - - var containerViewHorizontalMargin: CGFloat { - containerViewLeadingLayoutConstraint.constant + containerViewTrailingLayoutConstraint.constant - } - -} diff --git a/Mastodon/Scene/Share/View/TableviewCell/StatusTableViewCell.swift b/Mastodon/Scene/Share/View/TableviewCell/StatusTableViewCell.swift index 3ec9aa90..a1033f05 100644 --- a/Mastodon/Scene/Share/View/TableviewCell/StatusTableViewCell.swift +++ b/Mastodon/Scene/Share/View/TableviewCell/StatusTableViewCell.swift @@ -28,20 +28,6 @@ final class StatusTableViewCell: UITableViewCell { var containerViewLeadingLayoutConstraint: NSLayoutConstraint! var containerViewTrailingLayoutConstraint: NSLayoutConstraint! -// var isFiltered: Bool = false { -// didSet { -// configure(isFiltered: isFiltered) -// } -// } -// -// let filteredLabel: UILabel = { -// let label = UILabel() -// label.textColor = Asset.Colors.Label.secondary.color -// label.text = L10n.Common.Controls.Timeline.filtered -// label.font = .preferredFont(forTextStyle: .body) -// return label -// }() -// override func prepareForReuse() { super.prepareForReuse() @@ -71,7 +57,6 @@ extension StatusTableViewCell { statusView.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(statusView) setupContainerViewMarginConstraints() - updateContainerViewMarginConstraints() NSLayoutConstraint.activate([ statusView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 16), containerViewLeadingLayoutConstraint, @@ -79,6 +64,7 @@ extension StatusTableViewCell { statusView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), ]) statusView.setup(style: .inline) + updateContainerViewMarginConstraints() separatorLine.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(separatorLine) diff --git a/Mastodon/Scene/Share/View/TableviewCell/StatusThreadRootTableViewCell.swift b/Mastodon/Scene/Share/View/TableviewCell/StatusThreadRootTableViewCell.swift index e16e4f28..e27cc2dd 100644 --- a/Mastodon/Scene/Share/View/TableviewCell/StatusThreadRootTableViewCell.swift +++ b/Mastodon/Scene/Share/View/TableviewCell/StatusThreadRootTableViewCell.swift @@ -58,7 +58,6 @@ extension StatusThreadRootTableViewCell { statusView.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(statusView) setupContainerViewMarginConstraints() - updateContainerViewMarginConstraints() NSLayoutConstraint.activate([ statusView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 16), containerViewLeadingLayoutConstraint, @@ -66,6 +65,7 @@ extension StatusThreadRootTableViewCell { statusView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), ]) statusView.setup(style: .plain) + updateContainerViewMarginConstraints() separatorLine.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(separatorLine) @@ -79,8 +79,8 @@ extension StatusThreadRootTableViewCell { statusView.delegate = self // a11y - statusView.contentMetaText.textView.isSelectable = true statusView.contentMetaText.textView.isAccessibilityElement = false + statusView.contentMetaText.textView.isSelectable = true } override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { @@ -91,6 +91,49 @@ extension StatusThreadRootTableViewCell { } +extension StatusThreadRootTableViewCell { + + override var accessibilityElements: [Any]? { + get { + var elements = [ + statusView.headerContainerView, + statusView.avatarButton, + statusView.authorNameLabel, + statusView.menuButton, + statusView.authorUsernameLabel, + statusView.dateLabel, + statusView.contentSensitiveeToggleButton, + statusView.spoilerOverlayView, + statusView.contentMetaText.textView, + statusView.mediaGridContainerView, + statusView.pollTableView, + statusView.pollStatusStackView, + statusView.actionToolbarContainer, + statusView.statusMetricView + ] + + if !statusView.viewModel.isSensitive { + elements.removeAll(where: { $0 === statusView.contentSensitiveeToggleButton }) + } + + if statusView.viewModel.isContentReveal { + elements.removeAll(where: { $0 === statusView.spoilerOverlayView }) + } else { + elements.removeAll(where: { $0 === statusView.contentMetaText.textView }) + } + + if statusView.viewModel.pollItems.isEmpty { + elements.removeAll(where: { $0 === statusView.pollTableView }) + elements.removeAll(where: { $0 === statusView.pollStatusStackView }) + } + + return elements + } + set { } + } + +} + extension StatusThreadRootTableViewCell: AdaptiveContainerMarginTableViewCell { var containerView: StatusView { statusView diff --git a/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewController.swift b/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewController.swift index 20449fdf..07c27a72 100644 --- a/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewController.swift +++ b/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewController.swift @@ -74,7 +74,7 @@ extension SuggestionAccountViewController { setupBackgroundColor(theme: ThemeService.shared.currentTheme.value) ThemeService.shared.currentTheme - .receive(on: RunLoop.main) + .receive(on: DispatchQueue.main) .sink { [weak self] theme in guard let self = self else { return } self.setupBackgroundColor(theme: theme) @@ -169,29 +169,31 @@ extension SuggestionAccountViewController: UITableViewDelegate { } extension SuggestionAccountViewController: SuggestionAccountTableViewCellDelegate { - func accountButtonPressed(objectID: NSManagedObjectID, cell: SuggestionAccountTableViewCell) { -// let selected = !viewModel.selectedAccounts.value.contains(objectID) -// cell.startAnimating() -// viewModel.followAction(objectID: objectID)? -// .sink(receiveCompletion: { [weak self] completion in -// guard let self = self else { return } -// cell.stopAnimating() -// switch completion { -// case .failure(let error): -// os_log("%{public}s[%{public}ld], %{public}s: follow failed. %s", (#file as NSString).lastPathComponent, #line, #function, error.localizedDescription) -// case .finished: -// var selectedAccounts = self.viewModel.selectedAccounts.value -// if selected { -// selectedAccounts.append(objectID) -// } else { -// selectedAccounts.removeAll { $0 == objectID } -// } -// cell.button.isSelected = selected -// self.viewModel.selectedAccounts.value = selectedAccounts -// } -// }, receiveValue: { _ in -// }) -// .store(in: &disposeBag) + func suggestionAccountTableViewCell( + _ cell: SuggestionAccountTableViewCell, + friendshipDidPressed button: UIButton + ) { + guard let tableViewDiffableDataSource = viewModel.tableViewDiffableDataSource else { return } + guard let indexPath = tableView.indexPath(for: cell) else { return } + guard let item = tableViewDiffableDataSource.itemIdentifier(for: indexPath) else { return } + guard let authenticationBox = context.authenticationService.activeMastodonAuthenticationBox.value else { return } + + switch item { + case .account(let user): + Task { @MainActor in + cell.startAnimating() + do { + try await DataSourceFacade.responseToUserFollowAction( + dependency: self, + user: user, + authenticationBox: authenticationBox + ) + } catch { + // do noting + } + cell.stopAnimating() + } // end Task + } } } diff --git a/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewModel+Diffable.swift b/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewModel+Diffable.swift index 49f38c88..4496b9f0 100644 --- a/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewModel+Diffable.swift +++ b/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewModel+Diffable.swift @@ -22,6 +22,7 @@ extension SuggestionAccountViewModel { ) userFetchedResultsController.$records + .removeDuplicates() .receive(on: DispatchQueue.main) .sink { [weak self] records in guard let self = self else { return } @@ -50,7 +51,7 @@ extension SuggestionAccountViewModel { context: context ) - userFetchedResultsController.$records + selectedUserFetchedResultsController.$records .receive(on: DispatchQueue.main) .sink { [weak self] records in guard let self = self else { return } @@ -58,7 +59,16 @@ extension SuggestionAccountViewModel { var snapshot = NSDiffableDataSourceSnapshot<SelectedAccountSection, SelectedAccountItem>() snapshot.appendSections([.main]) - let items: [SelectedAccountItem] = records.map { SelectedAccountItem.account($0) } + var items: [SelectedAccountItem] = records.map { SelectedAccountItem.account($0) } + + if items.count < 10 { + let count = 10 - items.count + let placeholderItems: [SelectedAccountItem] = (0..<count).map { _ in + SelectedAccountItem.placeHolder(uuid: UUID()) + } + items.append(contentsOf: placeholderItems) + } + snapshot.appendItems(items, toSection: .main) if #available(iOS 15.0, *) { diff --git a/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewModel.swift b/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewModel.swift index 5a79f14d..0263b61e 100644 --- a/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewModel.swift +++ b/Mastodon/Scene/SuggestionAccount/SuggestionAccountViewModel.swift @@ -25,6 +25,7 @@ final class SuggestionAccountViewModel: NSObject { // input let context: AppContext let userFetchedResultsController: UserFetchedResultsController + let selectedUserFetchedResultsController: UserFetchedResultsController var viewWillAppear = PassthroughSubject<Void, Never>() @@ -32,11 +33,6 @@ final class SuggestionAccountViewModel: NSObject { var collectionViewDiffableDataSource: UICollectionViewDiffableDataSource<SelectedAccountSection, SelectedAccountItem>? var tableViewDiffableDataSource: UITableViewDiffableDataSource<RecommendAccountSection, RecommendAccountItem>? - @Published var selectedAccounts: [ManagedObjectRecord<MastodonUser>] = [] - var headerPlaceholderCount = CurrentValueSubject<Int?, Never>(nil) - var suggestionAccountsFallback = PassthroughSubject<Void, Never>() - - init( context: AppContext ) { @@ -44,53 +40,26 @@ final class SuggestionAccountViewModel: NSObject { self.userFetchedResultsController = UserFetchedResultsController( managedObjectContext: context.managedObjectContext, domain: nil, - additionalTweetPredicate: nil + additionalPredicate: nil + ) + self.selectedUserFetchedResultsController = UserFetchedResultsController( + managedObjectContext: context.managedObjectContext, + domain: nil, + additionalPredicate: nil ) super.init() - -// Publishers.CombineLatest( -// $accounts, -// $selectedAccounts -// ) -// .receive(on: RunLoop.main) -// .sink { [weak self] accounts,selectedAccounts in -// self?.applyTableViewDataSource(accounts: accounts) -// self?.applySelectedCollectionViewDataSource(accounts: selectedAccounts) -// } -// .store(in: &disposeBag) - -// Publishers.CombineLatest( -// self.selectedAccounts, -// self.headerPlaceholderCount -// ) -// .receive(on: RunLoop.main) -// .sink { [weak self] selectedAccount,count in -// self?.applySelectedCollectionViewDataSource(accounts: selectedAccount) -// } -// .store(in: &disposeBag) -// -// viewWillAppear -// .sink { [weak self] _ in -// self?.checkAccountsFollowState() -// } -// .store(in: &disposeBag) -// -// context.authenticationService.activeMastodonAuthentication -// .sink { [weak self] activeMastodonAuthentication in -// guard let self = self else { return } -// guard let activeMastodonAuthentication = activeMastodonAuthentication else { -// self.currentMastodonUser.value = nil -// return -// } -// self.currentMastodonUser.value = activeMastodonAuthentication.user -// } -// .store(in: &disposeBag) - + guard let authenticationBox = context.authenticationService.activeMastodonAuthenticationBox.value else { return } userFetchedResultsController.domain = authenticationBox.domain + selectedUserFetchedResultsController.domain = authenticationBox.domain + selectedUserFetchedResultsController.additionalPredicate = NSCompoundPredicate(orPredicateWithSubpredicates: [ + MastodonUser.predicate(followingBy: authenticationBox.userID), + MastodonUser.predicate(followRequestedBy: authenticationBox.userID) + ]) + // fetch recomment users Task { var userIDs: [MastodonUser.ID] = [] do { @@ -111,121 +80,25 @@ final class SuggestionAccountViewModel: NSObject { guard !userIDs.isEmpty else { return } userFetchedResultsController.userIDs = userIDs + selectedUserFetchedResultsController.userIDs = userIDs } -// .sink { [weak self] completion in -// switch completion { -// case .failure(let error): -// if let apiError = error as? Mastodon.API.Error { -// if apiError.httpResponseStatus == .notFound { -// self?.suggestionAccountsFallback.send() -// } -// } -// case .finished: -// // handle isFetchingLatestTimeline in fetch controller delegate -// break -// } -// } receiveValue: { [weak self] response in -// let ids = response.value.map(\.account.id) -// self?.receiveAccounts(ids: ids) -// } -// .store(in: &disposeBag) -// -// suggestionAccountsFallback -// .sink(receiveValue: { [weak self] _ in -// self?.requestSuggestionAccount() -// }) -// .store(in: &disposeBag) + // fetch relationship + userFetchedResultsController.$records + .removeDuplicates() + .sink { [weak self] records in + guard let _ = self else { return } + Task { + guard let authenticationBox = context.authenticationService.activeMastodonAuthenticationBox.value else { + return + } + _ = try await context.apiService.relationship( + records: records, + authenticationBox: authenticationBox + ) + } + } + .store(in: &disposeBag) } - -// func applyTableViewDataSource(accounts: [NSManagedObjectID]) { -// assert(Thread.isMainThread) -// guard let dataSource = diffableDataSource else { return } -// var snapshot = NSDiffableDataSourceSnapshot<RecommendAccountSection, NSManagedObjectID>() -// snapshot.appendSections([.main]) -// snapshot.appendItems(accounts, toSection: .main) -// dataSource.apply(snapshot, animatingDifferences: false, completion: nil) -// } -// -// func applySelectedCollectionViewDataSource(accounts: [NSManagedObjectID]) { -// assert(Thread.isMainThread) -// guard let count = headerPlaceholderCount.value else { return } -// guard let dataSource = collectionDiffableDataSource else { return } -// var snapshot = NSDiffableDataSourceSnapshot<SelectedAccountSection, SelectedAccountItem>() -// snapshot.appendSections([.main]) -// let placeholderCount = count - accounts.count -// let accountItems = accounts.map { SelectedAccountItem.accountObjectID(accountObjectID: $0) } -// snapshot.appendItems(accountItems, toSection: .main) -// -// if placeholderCount > 0 { -// for _ in 0 ..< placeholderCount { -// snapshot.appendItems([SelectedAccountItem.placeHolder(uuid: UUID())], toSection: .main) -// } -// } -// dataSource.apply(snapshot, animatingDifferences: false, completion: nil) -// } -// func receiveAccounts(userIDs: [MastodonUser.ID]) { -// guard let activeMastodonAuthenticationBox = context.authenticationService.activeMastodonAuthenticationBox.value else { -// return -// } -// let request = MastodonUser.sortedFetchRequest -// request.predicate = MastodonUser.predicate(domain: activeMastodonAuthenticationBox.domain, ids: userIDs) -// let mastodonUsers: [MastodonUser]? = { -// let userFetchRequest = MastodonUser.sortedFetchRequest -// userFetchRequest.predicate = MastodonUser.predicate(domain: activeMastodonAuthenticationBox.domain, ids: ids) -// userFetchRequest.returnsObjectsAsFaults = false -// do { -// return try self.context.managedObjectContext.fetch(userFetchRequest) -// } catch { -// assertionFailure(error.localizedDescription) -// return nil -// } -// }() -// if let users = mastodonUsers { -// let sortedUsers = users.sorted { (user1, user2) -> Bool in -// (ids.firstIndex(of: user1.id) ?? 0) < (ids.firstIndex(of: user2.id) ?? 0) -// } -// accounts.value = sortedUsers.map(\.objectID) -// } -// } - - func followAction(objectID: NSManagedObjectID) -> AnyPublisher<Mastodon.Response.Content<Mastodon.Entity.Relationship>, Error>? { - fatalError() -// guard let activeMastodonAuthenticationBox = context.authenticationService.activeMastodonAuthenticationBox.value else { return nil } -// -// let mastodonUser = context.managedObjectContext.object(with: objectID) as! MastodonUser -// return context.apiService.toggleFollow( -// for: mastodonUser, -// activeMastodonAuthenticationBox: activeMastodonAuthenticationBox -// ) - } - -// func checkAccountsFollowState() { -// fatalError() -// guard let currentMastodonUser = currentMastodonUser.value else { -// return -// } -// let users: [MastodonUser] = accounts.value.compactMap { -// guard let user = context.managedObjectContext.object(with: $0) as? MastodonUser else { -// return nil -// } -// let isBlock = user.blockingBy.flatMap { $0.contains(currentMastodonUser) } ?? false -// let isDomainBlock = user.domainBlockingBy.flatMap { $0.contains(currentMastodonUser) } ?? false -// if isBlock || isDomainBlock { -// return nil -// } else { -// return user -// } -// } -// accounts.value = users.map(\.objectID) -// -// let followingUsers = users.filter { user -> Bool in -// let isFollowing = user.followingBy.flatMap { $0.contains(currentMastodonUser) } ?? false -// let isPending = user.followRequestedBy.flatMap { $0.contains(currentMastodonUser) } ?? false -// return isFollowing || isPending -// }.map(\.objectID) -// -// selectedAccounts.value = followingUsers -// } } diff --git a/Mastodon/Scene/SuggestionAccount/TableViewCell/SuggestionAccountTableViewCell+ViewModel.swift b/Mastodon/Scene/SuggestionAccount/TableViewCell/SuggestionAccountTableViewCell+ViewModel.swift new file mode 100644 index 00000000..722f7618 --- /dev/null +++ b/Mastodon/Scene/SuggestionAccount/TableViewCell/SuggestionAccountTableViewCell+ViewModel.swift @@ -0,0 +1,139 @@ +// +// SuggestionAccountTableViewCell+ViewModel.swift +// Mastodon +// +// Created by MainasuK on 2022-2-16. +// + +import UIKit +import Combine +import CoreDataStack +import MastodonAsset +import MastodonMeta +import Meta + +extension SuggestionAccountTableViewCell { + + class ViewModel { + var disposeBag = Set<AnyCancellable>() + + @Published public var userIdentifier: UserIdentifier? // me + + @Published var avatarImageURL: URL? + @Published public var authorName: MetaContent? + @Published public var authorUsername: String? + + @Published var isFollowing = false + @Published var isPending = false + + func prepareForReuse() { + isFollowing = false + isPending = false + } + } + +} + +extension SuggestionAccountTableViewCell.ViewModel { + func bind(cell: SuggestionAccountTableViewCell) { + // avatar + $avatarImageURL.removeDuplicates() + .sink { url in + let configuration = AvatarImageView.Configuration(url: url) + cell.avatarButton.avatarImageView.configure(configuration: configuration) + cell.avatarButton.avatarImageView.configure(cornerConfiguration: .init(corner: .fixed(radius: 12))) + } + .store(in: &disposeBag) + // name + $authorName + .sink { metaContent in + let metaContent = metaContent ?? PlaintextMetaContent(string: " ") + cell.titleLabel.configure(content: metaContent) + } + .store(in: &disposeBag) + // username + $authorUsername + .map { text -> String in + guard let text = text else { return "" } + return "@\(text)" + } + .sink { username in + cell.subTitleLabel.text = username + } + .store(in: &disposeBag) + // button + Publishers.CombineLatest( + $isFollowing, + $isPending + ) + .sink { isFollowing, isPending in + let isFollowState = isFollowing || isPending + let imageName = isFollowState ? "minus.circle.fill" : "plus.circle" + let image = UIImage(systemName: imageName, withConfiguration: UIImage.SymbolConfiguration(pointSize: 22, weight: .regular)) + cell.button.setImage(image, for: .normal) + cell.button.tintColor = isFollowState ? Asset.Colors.danger.color : Asset.Colors.Label.secondary.color + } + .store(in: &disposeBag) + } +} + +extension SuggestionAccountTableViewCell { + func configure(user: MastodonUser) { + // author avatar + Publishers.CombineLatest( + user.publisher(for: \.avatar), + UserDefaults.shared.publisher(for: \.preferredStaticAvatar) + ) + .map { _ in user.avatarImageURL() } + .assign(to: \.avatarImageURL, on: viewModel) + .store(in: &disposeBag) + // author name + Publishers.CombineLatest( + user.publisher(for: \.displayName), + user.publisher(for: \.emojis) + ) + .map { _, emojis in + do { + let content = MastodonContent(content: user.displayNameWithFallback, emojis: emojis.asDictionary) + let metaContent = try MastodonMetaContent.convert(document: content) + return metaContent + } catch { + assertionFailure(error.localizedDescription) + return PlaintextMetaContent(string: user.displayNameWithFallback) + } + } + .assign(to: \.authorName, on: viewModel) + .store(in: &disposeBag) + // author username + user.publisher(for: \.acct) + .map { $0 as String? } + .assign(to: \.authorUsername, on: viewModel) + .store(in: &disposeBag) + // isFollowing + Publishers.CombineLatest( + viewModel.$userIdentifier, + user.publisher(for: \.followingBy) + ) + .map { userIdentifier, followingBy in + guard let userIdentifier = userIdentifier else { return false } + return followingBy.contains(where: { + $0.id == userIdentifier.userID && $0.domain == userIdentifier.domain + }) + } + .assign(to: \.isFollowing, on: viewModel) + .store(in: &disposeBag) + // isPending + Publishers.CombineLatest( + viewModel.$userIdentifier, + user.publisher(for: \.followRequestedBy) + ) + .map { userIdentifier, followRequestedBy in + guard let userIdentifier = userIdentifier else { return false } + return followRequestedBy.contains(where: { + $0.id == userIdentifier.userID && $0.domain == userIdentifier.domain + }) + } + .assign(to: \.isPending, on: viewModel) + .store(in: &disposeBag) + } +} diff --git a/Mastodon/Scene/SuggestionAccount/TableViewCell/SuggestionAccountTableViewCell.swift b/Mastodon/Scene/SuggestionAccount/TableViewCell/SuggestionAccountTableViewCell.swift index 5e3a2e1f..47bd9d6b 100644 --- a/Mastodon/Scene/SuggestionAccount/TableViewCell/SuggestionAccountTableViewCell.swift +++ b/Mastodon/Scene/SuggestionAccount/TableViewCell/SuggestionAccountTableViewCell.swift @@ -5,6 +5,7 @@ // Created by sxiaojian on 2021/4/21. // +import os.log import Combine import CoreData import CoreDataStack @@ -15,23 +16,28 @@ import MetaTextKit import MastodonMeta import MastodonAsset import MastodonLocalization +import MastodonUI protocol SuggestionAccountTableViewCellDelegate: AnyObject { - func accountButtonPressed(objectID: NSManagedObjectID, cell: SuggestionAccountTableViewCell) + func suggestionAccountTableViewCell(_ cell: SuggestionAccountTableViewCell, friendshipDidPressed button: UIButton) } final class SuggestionAccountTableViewCell: UITableViewCell { + + let logger = Logger(subsystem: "SuggestionAccountTableViewCell", category: "View") + var disposeBag = Set<AnyCancellable>() + weak var delegate: SuggestionAccountTableViewCellDelegate? - let _imageView: UIImageView = { - let imageView = UIImageView() - imageView.tintColor = Asset.Colors.Label.primary.color - imageView.layer.cornerRadius = 4 - imageView.clipsToBounds = true - return imageView + public private(set) lazy var viewModel: ViewModel = { + let viewModel = ViewModel() + viewModel.bind(cell: self) + return viewModel }() + let avatarButton = AvatarButton() + let titleLabel = MetaLabel(style: .statusName) let subTitleLabel: UILabel = { @@ -49,12 +55,8 @@ final class SuggestionAccountTableViewCell: UITableViewCell { let button: HighlightDimmableButton = { let button = HighlightDimmableButton(type: .custom) - if let plusImage = UIImage(systemName: "plus.circle", withConfiguration: UIImage.SymbolConfiguration(pointSize: 22, weight: .regular))?.withRenderingMode(.alwaysTemplate) { - button.setImage(plusImage, for: .normal) - } - if let minusImage = UIImage(systemName: "minus.circle.fill", withConfiguration: UIImage.SymbolConfiguration(pointSize: 22, weight: .regular))?.withRenderingMode(.alwaysTemplate) { - button.setImage(minusImage, for: .selected) - } + let image = UIImage(systemName: "plus.circle", withConfiguration: UIImage.SymbolConfiguration(pointSize: 22, weight: .regular)) + button.setImage(image, for: .normal) return button }() @@ -66,9 +68,10 @@ final class SuggestionAccountTableViewCell: UITableViewCell { override func prepareForReuse() { super.prepareForReuse() - _imageView.af.cancelImageRequest() - _imageView.image = nil + disposeBag.removeAll() + avatarButton.avatarImageView.prepareForReuse() + viewModel.prepareForReuse() } override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { @@ -80,9 +83,11 @@ final class SuggestionAccountTableViewCell: UITableViewCell { super.init(coder: coder) configure() } + } extension SuggestionAccountTableViewCell { + private func configure() { let containerStackView = UIStackView() containerStackView.axis = .horizontal @@ -99,11 +104,11 @@ extension SuggestionAccountTableViewCell { containerStackView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), ]) - _imageView.translatesAutoresizingMaskIntoConstraints = false - containerStackView.addArrangedSubview(_imageView) + avatarButton.translatesAutoresizingMaskIntoConstraints = false + containerStackView.addArrangedSubview(avatarButton) NSLayoutConstraint.activate([ - _imageView.widthAnchor.constraint(equalToConstant: 42).priority(.required - 1), - _imageView.heightAnchor.constraint(equalToConstant: 42).priority(.required - 1), + avatarButton.widthAnchor.constraint(equalToConstant: 42).priority(.required - 1), + avatarButton.heightAnchor.constraint(equalToConstant: 42).priority(.required - 1), ]) let textStackView = UIStackView() @@ -139,56 +144,31 @@ extension SuggestionAccountTableViewCell { buttonContainer.centerXAnchor.constraint(equalTo: button.centerXAnchor), buttonContainer.centerYAnchor.constraint(equalTo: button.centerYAnchor), ]) + + button.addTarget(self, action: #selector(SuggestionAccountTableViewCell.buttonDidPressed(_:)), for: .touchUpInside) } - func config(with account: MastodonUser) { - if let url = account.avatarImageURL() { - _imageView.af.setImage( - withURL: url, - placeholderImage: UIImage.placeholder(color: .systemFill), - imageTransition: .crossDissolve(0.2) - ) - } - let mastodonContent = MastodonContent(content: account.displayNameWithFallback, emojis: account.emojis.asDictionary) - do { - let metaContent = try MastodonMetaContent.convert(document: mastodonContent) - titleLabel.configure(content: metaContent) - } catch { - let metaContent = PlaintextMetaContent(string: account.displayNameWithFallback) - titleLabel.configure(content: metaContent) - } - subTitleLabel.text = "@" + account.acct - button.isSelected = isSelected - button.publisher(for: .touchUpInside) - .sink { [weak self] _ in - guard let self = self else { return } - self.delegate?.accountButtonPressed(objectID: account.objectID, cell: self) - } - .store(in: &disposeBag) - button.publisher(for: \.isSelected) - .sink { [weak self] isSelected in - if isSelected { - self?.button.tintColor = Asset.Colors.danger.color - } else { - self?.button.tintColor = Asset.Colors.Label.secondary.color - } - } - .store(in: &disposeBag) - activityIndicatorView.publisher(for: \.isHidden) - .receive(on: DispatchQueue.main) - .sink { [weak self] isHidden in - self?.button.isHidden = !isHidden - } - .store(in: &disposeBag) +} + +extension SuggestionAccountTableViewCell { + @objc private func buttonDidPressed(_ sender: UIButton) { + logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)") + delegate?.suggestionAccountTableViewCell(self, friendshipDidPressed: sender) } +} + +extension SuggestionAccountTableViewCell { func startAnimating() { activityIndicatorView.isHidden = false activityIndicatorView.startAnimating() + button.isHidden = true } func stopAnimating() { activityIndicatorView.stopAnimating() activityIndicatorView.isHidden = true + button.isHidden = false } + } diff --git a/Mastodon/Scene/Thread/ThreadViewController.swift b/Mastodon/Scene/Thread/ThreadViewController.swift index cfc28447..bd90fb37 100644 --- a/Mastodon/Scene/Thread/ThreadViewController.swift +++ b/Mastodon/Scene/Thread/ThreadViewController.swift @@ -92,10 +92,7 @@ extension ThreadViewController { tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor), ]) -// viewModel.tableView = tableView -// viewModel.contentOffsetAdjustableTimelineViewControllerDelegate = self tableView.delegate = self -// tableView.prefetchDataSource = self viewModel.setupDiffableDataSource( tableView: tableView, statusTableViewCellDelegate: self @@ -174,123 +171,26 @@ extension ThreadViewController: UITableViewDelegate, AutoGenerateTableViewDelega return indexPath } } - - -// func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { -// aspectTableView(tableView, estimatedHeightForRowAt: indexPath) -// } -// -// func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { -// aspectTableView(tableView, willDisplay: cell, forRowAt: indexPath) -// } -// -// func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) { -// aspectTableView(tableView, didEndDisplaying: cell, forRowAt: indexPath) -// } -// -// func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { -// aspectTableView(tableView, didSelectRowAt: indexPath) -// } -// -// func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? { -// guard let diffableDataSource = viewModel.diffableDataSource else { return nil } -// guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return nil } -// -// // disable root selection -// switch item { -// case .root: -// return nil -// default: -// return indexPath -// } -// } -// -// func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? { -// return aspectTableView(tableView, contextMenuConfigurationForRowAt: indexPath, point: point) -// } -// -// func tableView(_ tableView: UITableView, previewForHighlightingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? { -// return aspectTableView(tableView, previewForHighlightingContextMenuWithConfiguration: configuration) -// } -// -// func tableView(_ tableView: UITableView, previewForDismissingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? { -// return aspectTableView(tableView, previewForDismissingContextMenuWithConfiguration: configuration) -// } -// -// func tableView(_ tableView: UITableView, willPerformPreviewActionForMenuWith configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionCommitAnimating) { -// aspectTableView(tableView, willPerformPreviewActionForMenuWith: configuration, animator: animator) -// } - } -// MARK: - UITableViewDataSourcePrefetching -//extension ThreadViewController: UITableViewDataSourcePrefetching { -// func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) { -// aspectTableView(tableView, prefetchRowsAt: indexPaths) -// } -//} - -// MARK: - AVPlayerViewControllerDelegate -//extension ThreadViewController: AVPlayerViewControllerDelegate { -// -// func playerViewController(_ playerViewController: AVPlayerViewController, willBeginFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) { -// aspectPlayerViewController(playerViewController, willBeginFullScreenPresentationWithAnimationCoordinator: coordinator) -// } -// -// func playerViewController(_ playerViewController: AVPlayerViewController, willEndFullScreenPresentationWithAnimationCoordinator coordinator: UIViewControllerTransitionCoordinator) { -// aspectPlayerViewController(playerViewController, willEndFullScreenPresentationWithAnimationCoordinator: coordinator) -// } -// -//} - -// MARK: - statusTableViewCellDelegate -//extension ThreadViewController: StatusTableViewCellDelegate { -// weak var playerViewControllerDelegate: AVPlayerViewControllerDelegate? { return self } -// func parent() -> UIViewController { return self } -//} - -// MARK: - ThreadReplyLoaderTableViewCellDelegate -//extension ThreadViewController: ThreadReplyLoaderTableViewCellDelegate { -// func threadReplyLoaderTableViewCell(_ cell: ThreadReplyLoaderTableViewCell, loadMoreButtonDidPressed button: UIButton) { -// guard let diffableDataSource = viewModel.diffableDataSource else { return } -// guard let indexPath = tableView.indexPath(for: cell) else { return } -// guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return } -// guard case let .leafBottomLoader(statusObjectID) = item else { return } -// -// let nodes = viewModel.descendantNodes.value -// nodes.forEach { node in -// expandReply(node: node, statusObjectID: statusObjectID) -// } -// viewModel.descendantNodes.value = nodes -// } -// -// private func expandReply(node: ThreadViewModel.LeafNode, statusObjectID: NSManagedObjectID) { -// if node.objectID == statusObjectID { -// node.isChildrenExpanded = true -// } else { -// for child in node.children { -// expandReply(node: child, statusObjectID: statusObjectID) -// } -// } -// } -//} - -//extension ThreadViewController { -// override var keyCommands: [UIKeyCommand]? { -// return navigationKeyCommands + statusNavigationKeyCommands -// } -//} -// -//// MARK: - StatusTableViewControllerNavigateable -//extension ThreadViewController: StatusTableViewControllerNavigateable { -// @objc func navigateKeyCommandHandlerRelay(_ sender: UIKeyCommand) { -// navigateKeyCommandHandler(sender) -// } -// -// @objc func statusKeyCommandHandlerRelay(_ sender: UIKeyCommand) { -// statusKeyCommandHandler(sender) -// } -//} // MARK: - StatusTableViewCellDelegate extension ThreadViewController: StatusTableViewCellDelegate { } + + +extension ThreadViewController { + override var keyCommands: [UIKeyCommand]? { + return navigationKeyCommands + statusNavigationKeyCommands + } +} + +// MARK: - StatusTableViewControllerNavigateable +extension ThreadViewController: StatusTableViewControllerNavigateable { + @objc func navigateKeyCommandHandlerRelay(_ sender: UIKeyCommand) { + navigateKeyCommandHandler(sender) + } + + @objc func statusKeyCommandHandlerRelay(_ sender: UIKeyCommand) { + statusKeyCommandHandler(sender) + } +} diff --git a/Mastodon/Scene/Thread/ThreadViewModel+Diffable.swift b/Mastodon/Scene/Thread/ThreadViewModel+Diffable.swift index 07966713..a6b4848c 100644 --- a/Mastodon/Scene/Thread/ThreadViewModel+Diffable.swift +++ b/Mastodon/Scene/Thread/ThreadViewModel+Diffable.swift @@ -23,7 +23,9 @@ extension ThreadViewModel { context: context, configuration: StatusSection.Configuration( statusTableViewCellDelegate: statusTableViewCellDelegate, - timelineMiddleLoaderTableViewCellDelegate: nil + timelineMiddleLoaderTableViewCellDelegate: nil, + filterContext: .thread, + activeFilters: context.statusFilterService.$activeFilters ) ) diff --git a/Mastodon/Service/APIService/APIService+WebFinger.swift b/Mastodon/Service/APIService/APIService+WebFinger.swift index 7cc0425d..b49ad9e3 100644 --- a/Mastodon/Service/APIService/APIService+WebFinger.swift +++ b/Mastodon/Service/APIService/APIService+WebFinger.swift @@ -16,7 +16,8 @@ import MastodonSDK extension APIService { private static func webFingerEndpointURL(domain: String) -> URL { - return URL(string: "https://\(domain)/")! + + return URL(string: "\(URL.httpScheme(domain: domain))://\(domain)/")! .appendingPathComponent(".well-known") .appendingPathComponent("webfinger") } diff --git a/Mastodon/Service/StatusFilterService.swift b/Mastodon/Service/StatusFilterService.swift index 38a1a17c..b5afd08a 100644 --- a/Mastodon/Service/StatusFilterService.swift +++ b/Mastodon/Service/StatusFilterService.swift @@ -23,7 +23,7 @@ final class StatusFilterService { let filterUpdatePublisher = PassthroughSubject<Void, Never>() // output - let activeFilters = CurrentValueSubject<[Mastodon.Entity.Filter], Never>([]) + @Published var activeFilters: [Mastodon.Entity.Filter] = [] init( apiService: APIService, @@ -57,7 +57,14 @@ final class StatusFilterService { .map { response in let now = Date() let newResponse = response.map { filters in - return filters.filter { $0.expiresAt > now } // filter out expired rules + return filters.filter { filter in + if let expiresAt = filter.expiresAt { + // filter out expired rules + return expiresAt > now + } else { + return true + } + } } return Result<Mastodon.Response.Content<[Mastodon.Entity.Filter]>, Error>.success(newResponse) } @@ -70,7 +77,7 @@ final class StatusFilterService { switch result { case .success(let response): os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: fetch account filters success. %ld items", ((#file as NSString).lastPathComponent), #line, #function, response.value.count) - self.activeFilters.value = response.value + self.activeFilters = response.value case .failure(let error): os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: fetch account filters fail: %s", ((#file as NSString).lastPathComponent), #line, #function, error.localizedDescription) diff --git a/Mastodon/Supporting Files/SceneDelegate.swift b/Mastodon/Supporting Files/SceneDelegate.swift index 79ce1543..d178cd0d 100644 --- a/Mastodon/Supporting Files/SceneDelegate.swift +++ b/Mastodon/Supporting Files/SceneDelegate.swift @@ -59,6 +59,14 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { sceneCoordinator.setup() sceneCoordinator.setupOnboardingIfNeeds(animated: false) window.makeKeyAndVisible() + + #if SNAPSHOT + // speedup animation + // window.layer.speed = 999 + + // disable animation + UIView.setAnimationsEnabled(false) + #endif if let shortcutItem = connectionOptions.shortcutItem { // Save it off for later when we become active. @@ -67,7 +75,15 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { UserDefaults.shared.observe(\.customUserInterfaceStyle, options: [.initial, .new]) { [weak self] defaults, _ in guard let self = self else { return } + #if SNAPSHOT + // toggle Dark Mode + // https://stackoverflow.com/questions/32988241/how-to-access-launchenvironment-and-launcharguments-set-in-xcuiapplication-runn + if ProcessInfo.processInfo.arguments.contains("UIUserInterfaceStyleForceDark") { + self.window?.overrideUserInterfaceStyle = .dark + } + #else self.window?.overrideUserInterfaceStyle = defaults.customUserInterfaceStyle + #endif } .store(in: &observations) diff --git a/MastodonIntent/Info.plist b/MastodonIntent/Info.plist index 5dbe6951..02385f4e 100644 --- a/MastodonIntent/Info.plist +++ b/MastodonIntent/Info.plist @@ -19,7 +19,7 @@ <key>CFBundleShortVersionString</key> <string>1.3.0</string> <key>CFBundleVersion</key> - <string>96</string> + <string>109</string> <key>NSExtension</key> <dict> <key>NSExtensionAttributes</key> diff --git a/MastodonIntent/eu-ES.lproj/Intents.strings b/MastodonIntent/eu-ES.lproj/Intents.strings index b85bec4c..dbc27c1c 100644 --- a/MastodonIntent/eu-ES.lproj/Intents.strings +++ b/MastodonIntent/eu-ES.lproj/Intents.strings @@ -1,52 +1,51 @@ -"16wxgf" = "Post on Mastodon"; +"16wxgf" = "Argitaratu Mastodonen"; -"751xkl" = "Text Content"; +"751xkl" = "Testu-edukia"; -"CsR7G2" = "Post on Mastodon"; +"CsR7G2" = "Argitaratu Mastodonen"; -"HZSGTr" = "What content to post?"; +"HZSGTr" = "Ze eduki argitaratu?"; -"HdGikU" = "Posting failed"; +"HdGikU" = "Argitaratzeak huts egin du"; -"KDNTJ4" = "Failure Reason"; +"KDNTJ4" = "Hutsegitearen arrazoia"; -"RHxKOw" = "Send Post with text content"; +"RHxKOw" = "Argitaratu bidalketa testu-edukiarekin"; -"RxSqsb" = "Post"; +"RxSqsb" = "Bidali"; -"WCIR3D" = "Post ${content} on Mastodon"; +"WCIR3D" = "Argitaratu ${content} Mastodonen"; -"ZKJSNu" = "Post"; +"ZKJSNu" = "Bidali"; "ZS1XaK" = "${content}"; -"ZbSjzC" = "Visibility"; +"ZbSjzC" = "Ikusgaitasuna"; -"Zo4jgJ" = "Post Visibility"; +"Zo4jgJ" = "Bidalketaren ikusgaitasuna"; -"apSxMG-dYQ5NN" = "There are ${count} options matching ‘Public’."; +"apSxMG-dYQ5NN" = "'Publikoa'-rekin bat datozen ${count} aukera daude."; -"apSxMG-ehFLjY" = "There are ${count} options matching ‘Followers Only’."; +"apSxMG-ehFLjY" = "'Jarraitzaileak soilik'-ekin bat datozen ${count} aukera daude."; -"ayoYEb-dYQ5NN" = "${content}, Public"; +"ayoYEb-dYQ5NN" = "${content}, publikoa"; -"ayoYEb-ehFLjY" = "${content}, Followers Only"; +"ayoYEb-ehFLjY" = "${content}, jarraitzaileak besterik ez"; -"dUyuGg" = "Post on Mastodon"; +"dUyuGg" = "Argitaratu Mastodonen"; -"dYQ5NN" = "Public"; +"dYQ5NN" = "Publikoa"; -"ehFLjY" = "Followers Only"; +"ehFLjY" = "Jarraitzaileak soilik"; -"gfePDu" = "Posting failed. ${failureReason}"; +"gfePDu" = "Argitaratzeak huts egin du. ${failureReason}"; -"k7dbKQ" = "Post was sent successfully."; +"k7dbKQ" = "Bidalketa behar bezala bidali da."; -"oGiqmY-dYQ5NN" = "Just to confirm, you wanted ‘Public’?"; +"oGiqmY-dYQ5NN" = "Berresteagatik, 'Publikoa' izatea nahi duzu?"; -"oGiqmY-ehFLjY" = "Just to confirm, you wanted ‘Followers Only’?"; +"oGiqmY-ehFLjY" = "Berresteagatik, 'Jarraitzaileak soilik' izatea nahi duzu?"; -"rM6dvp" = "URL"; - -"ryJLwG" = "Post was sent successfully."; +"rM6dvp" = "URLa"; +"ryJLwG" = "Bidalketa behar bezala bidali da. "; diff --git a/MastodonIntent/fr.lproj/Intents.strings b/MastodonIntent/fr.lproj/Intents.strings index f4fec300..2703edd4 100644 --- a/MastodonIntent/fr.lproj/Intents.strings +++ b/MastodonIntent/fr.lproj/Intents.strings @@ -12,7 +12,7 @@ "RHxKOw" = "Envoyer une publication avec du contenu texte"; -"RxSqsb" = "Post"; +"RxSqsb" = "Publication"; "WCIR3D" = "Publier du ${content} sur Mastodon"; @@ -24,9 +24,9 @@ "Zo4jgJ" = "Visibilité de la publication"; -"apSxMG-dYQ5NN" = "There are ${count} options matching ‘Public’."; +"apSxMG-dYQ5NN" = "Il y a ${count} options correspondant à « Public »."; -"apSxMG-ehFLjY" = "There are ${count} options matching ‘Followers Only’."; +"apSxMG-ehFLjY" = "Il y a ${count} options correspondant à « Abonnés uniquement »."; "ayoYEb-dYQ5NN" = "${content}, Public"; diff --git a/MastodonIntent/ja.lproj/Intents.strings b/MastodonIntent/ja.lproj/Intents.strings index 6877490b..411b35c2 100644 --- a/MastodonIntent/ja.lproj/Intents.strings +++ b/MastodonIntent/ja.lproj/Intents.strings @@ -1,51 +1,51 @@ -"16wxgf" = "Post on Mastodon"; +"16wxgf" = "Mastodonに投稿"; -"751xkl" = "Text Content"; +"751xkl" = "テキストコンテンツ"; -"CsR7G2" = "Post on Mastodon"; +"CsR7G2" = "Mastodonに投稿"; "HZSGTr" = "What content to post?"; -"HdGikU" = "Posting failed"; +"HdGikU" = "投稿に失敗しました"; -"KDNTJ4" = "Failure Reason"; +"KDNTJ4" = "失敗の理由"; "RHxKOw" = "Send Post with text content"; -"RxSqsb" = "Post"; +"RxSqsb" = "投稿"; -"WCIR3D" = "Post ${content} on Mastodon"; +"WCIR3D" = "Mastodonに ${content} を投稿"; -"ZKJSNu" = "Post"; +"ZKJSNu" = "投稿"; "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" = "Mastodonに投稿"; -"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"; -"ryJLwG" = "Post was sent successfully. "; +"ryJLwG" = "投稿に成功しました。 "; diff --git a/MastodonIntent/ku-TR.lproj/Intents.strings b/MastodonIntent/ku.lproj/Intents.strings similarity index 100% rename from MastodonIntent/ku-TR.lproj/Intents.strings rename to MastodonIntent/ku.lproj/Intents.strings diff --git a/MastodonIntent/ku-TR.lproj/Intents.stringsdict b/MastodonIntent/ku.lproj/Intents.stringsdict similarity index 100% rename from MastodonIntent/ku-TR.lproj/Intents.stringsdict rename to MastodonIntent/ku.lproj/Intents.stringsdict diff --git a/MastodonIntent/sv_FI.lproj/Intents.strings b/MastodonIntent/sv_FI.lproj/Intents.strings index d4531ed6..1be213d4 100644 --- a/MastodonIntent/sv_FI.lproj/Intents.strings +++ b/MastodonIntent/sv_FI.lproj/Intents.strings @@ -1,51 +1,51 @@ -"16wxgf" = "Post on Mastodon"; +"16wxgf" = "Julkaise Mastodonissa"; -"751xkl" = "Text Content"; +"751xkl" = "Tekstisisältö"; -"CsR7G2" = "Post on Mastodon"; +"CsR7G2" = "Julkaise Mastodonissa"; -"HZSGTr" = "What content to post?"; +"HZSGTr" = "Mitä sisältöä julkaista?"; -"HdGikU" = "Posting failed"; +"HdGikU" = "Julkaiseminen epäonnistui"; -"KDNTJ4" = "Failure Reason"; +"KDNTJ4" = "Epäonnistumisen syy"; -"RHxKOw" = "Send Post with text content"; +"RHxKOw" = "Lähetä julkaisu teksisisällöllä"; -"RxSqsb" = "Post"; +"RxSqsb" = "Julkaisu"; -"WCIR3D" = "Posta ${content} på Mastodon"; +"WCIR3D" = "Julkaise ${content} Mastodonissa"; -"ZKJSNu" = "Post"; +"ZKJSNu" = "Julkaisu"; "ZS1XaK" = "${content}"; -"ZbSjzC" = "Visibility"; +"ZbSjzC" = "Näkyvyys"; -"Zo4jgJ" = "Post Visibility"; +"Zo4jgJ" = "Julkaisun näkyvyys"; -"apSxMG-dYQ5NN" = "There are ${count} options matching ‘Public’."; +"apSxMG-dYQ5NN" = "On ${count} vaihtoehtoa, jotka vastaavat ‘Julkinen’."; -"apSxMG-ehFLjY" = "There are ${count} options matching ‘Followers Only’."; +"apSxMG-ehFLjY" = "On ${count} vaihtoehtoa, jotka vastaavat ‘Vain seuraajat’."; -"ayoYEb-dYQ5NN" = "${content}, Public"; +"ayoYEb-dYQ5NN" = "${content}, julkinen"; -"ayoYEb-ehFLjY" = "${content}, Followers Only"; +"ayoYEb-ehFLjY" = "${content}, vain seuraajat"; -"dUyuGg" = "Post on Mastodon"; +"dUyuGg" = "Julkaise Mastodonissa"; -"dYQ5NN" = "Public"; +"dYQ5NN" = "Julkinen"; -"ehFLjY" = "Followers Only"; +"ehFLjY" = "Vain seuraajat"; -"gfePDu" = "Posting failed. ${failureReason}"; +"gfePDu" = "Julkaiseminen epäonnistui. ${failureReason}"; -"k7dbKQ" = "Post was sent successfully."; +"k7dbKQ" = "Julkaisu lähetettiin onnistuneesti."; -"oGiqmY-dYQ5NN" = "Just to confirm, you wanted ‘Public’?"; +"oGiqmY-dYQ5NN" = "Vahvitukseksi, halusit ‘Julkinen’?"; -"oGiqmY-ehFLjY" = "Just to confirm, you wanted ‘Followers Only’?"; +"oGiqmY-ehFLjY" = "Vahvitstukseksi, halusit ‘Vain seuraajat’?"; "rM6dvp" = "URL"; -"ryJLwG" = "Post was sent successfully. "; +"ryJLwG" = "Julkaisu lähetettiin onnistuneesti. "; diff --git a/MastodonSDK/Sources/CoreDataStack/CoreData.xcdatamodeld/CoreData 3.xcdatamodel/contents b/MastodonSDK/Sources/CoreDataStack/CoreData.xcdatamodeld/CoreData 3.xcdatamodel/contents index 3e2fcc13..a6f0ee0c 100644 --- a/MastodonSDK/Sources/CoreDataStack/CoreData.xcdatamodeld/CoreData 3.xcdatamodel/contents +++ b/MastodonSDK/Sources/CoreDataStack/CoreData.xcdatamodeld/CoreData 3.xcdatamodel/contents @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="19574" systemVersion="21D49" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier=""> +<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="19574" systemVersion="21D62" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier=""> <entity name="Application" representedClassName="CoreDataStack.Application" syncable="YES"> <attribute name="identifier" optional="YES" attributeType="UUID" usesScalarValueType="NO"/> <attribute name="name" attributeType="String"/> diff --git a/MastodonSDK/Sources/CoreDataStack/Entity/Mastodon/MastodonUser.swift b/MastodonSDK/Sources/CoreDataStack/Entity/Mastodon/MastodonUser.swift index 3def7efd..4b16b7c7 100644 --- a/MastodonSDK/Sources/CoreDataStack/Entity/Mastodon/MastodonUser.swift +++ b/MastodonSDK/Sources/CoreDataStack/Entity/Mastodon/MastodonUser.swift @@ -203,6 +203,14 @@ extension MastodonUser { ]) } + public static func predicate(followingBy userID: MastodonUser.ID) -> NSPredicate { + NSPredicate(format: "ANY %K.%K == %@", #keyPath(MastodonUser.followingBy), #keyPath(MastodonUser.id), userID) + } + + public static func predicate(followRequestedBy userID: MastodonUser.ID) -> NSPredicate { + NSPredicate(format: "ANY %K.%K == %@", #keyPath(MastodonUser.followRequestedBy), #keyPath(MastodonUser.id), userID) + } + } diff --git a/MastodonSDK/Sources/CoreDataStack/Entity/Mastodon/Status.swift b/MastodonSDK/Sources/CoreDataStack/Entity/Mastodon/Status.swift index c9946b3f..d17d1c61 100644 --- a/MastodonSDK/Sources/CoreDataStack/Entity/Mastodon/Status.swift +++ b/MastodonSDK/Sources/CoreDataStack/Entity/Mastodon/Status.swift @@ -197,166 +197,6 @@ extension Status { return object } - -// @discardableResult -// public static func insert( -// into context: NSManagedObjectContext, -// property: Property, -// author: MastodonUser, -// reblog: Status?, -// application: Application?, -// replyTo: Status?, -// poll: Poll?, -// mentions: [Mention]?, -// mediaAttachments: [Attachment]?, -// favouritedBy: MastodonUser?, -// rebloggedBy: MastodonUser?, -// mutedBy: MastodonUser?, -// bookmarkedBy: MastodonUser?, -// pinnedBy: MastodonUser? -// ) -> Status { -// let status: Status = context.insertObject() -// -// status.identifier = property.identifier -// status.domain = property.domain -// -// status.id = property.id -// status.uri = property.uri -// status.createdAt = property.createdAt -// status.content = property.content -// -// status.visibility = property.visibility -// status.sensitive = property.sensitive -// status.spoilerText = property.spoilerText -// status.application = application -// -// status.emojisData = property.emojisData -// -// status.reblogsCount = property.reblogsCount -// status.favouritesCount = property.favouritesCount -// status.repliesCount = property.repliesCount -// -// status.url = property.url -// status.inReplyToID = property.inReplyToID -// status.inReplyToAccountID = property.inReplyToAccountID -// -// status.language = property.language -// status.text = property.text -// -// status.author = author -// status.reblog = reblog -// -// status.pinnedBy = pinnedBy -// status.poll = poll -// -// if let mentions = mentions { -// status.mutableSetValue(forKey: #keyPath(Status.mentions)).addObjects(from: mentions) -// } -// if let mediaAttachments = mediaAttachments { -// status.mutableSetValue(forKey: #keyPath(Status.mediaAttachments)).addObjects(from: mediaAttachments) -// } -// if let favouritedBy = favouritedBy { -// status.mutableSetValue(forKey: #keyPath(Status.favouritedBy)).add(favouritedBy) -// } -// if let rebloggedBy = rebloggedBy { -// status.mutableSetValue(forKey: #keyPath(Status.rebloggedBy)).add(rebloggedBy) -// } -// if let mutedBy = mutedBy { -// status.mutableSetValue(forKey: #keyPath(Status.mutedBy)).add(mutedBy) -// } -// if let bookmarkedBy = bookmarkedBy { -// status.mutableSetValue(forKey: #keyPath(Status.bookmarkedBy)).add(bookmarkedBy) -// } -// -// status.updatedAt = property.networkDate -// -// return status -// } -// -// public func update(emojisData: Data?) { -// if self.emojisData != emojisData { -// self.emojisData = emojisData -// } -// } -// -// public func update(reblogsCount: NSNumber) { -// if self.reblogsCount.intValue != reblogsCount.intValue { -// self.reblogsCount = reblogsCount -// } -// } -// -// public func update(favouritesCount: NSNumber) { -// if self.favouritesCount.intValue != favouritesCount.intValue { -// self.favouritesCount = favouritesCount -// } -// } -// -// public func update(repliesCount: NSNumber?) { -// guard let count = repliesCount else { -// return -// } -// if self.repliesCount?.intValue != count.intValue { -// self.repliesCount = repliesCount -// } -// } -// -// public func update(replyTo: Status?) { -// if self.replyTo != replyTo { -// self.replyTo = replyTo -// } -// } -// -// public func update(liked: Bool, by mastodonUser: MastodonUser) { -// if liked { -// if !(self.favouritedBy ?? Set()).contains(mastodonUser) { -// self.mutableSetValue(forKey: #keyPath(Status.favouritedBy)).add(mastodonUser) -// } -// } else { -// if (self.favouritedBy ?? Set()).contains(mastodonUser) { -// self.mutableSetValue(forKey: #keyPath(Status.favouritedBy)).remove(mastodonUser) -// } -// } -// } -// -// public func update(reblogged: Bool, by mastodonUser: MastodonUser) { -// if reblogged { -// if !(self.rebloggedBy ?? Set()).contains(mastodonUser) { -// self.mutableSetValue(forKey: #keyPath(Status.rebloggedBy)).add(mastodonUser) -// } -// } else { -// if (self.rebloggedBy ?? Set()).contains(mastodonUser) { -// self.mutableSetValue(forKey: #keyPath(Status.rebloggedBy)).remove(mastodonUser) -// } -// } -// } -// -// public func update(muted: Bool, by mastodonUser: MastodonUser) { -// if muted { -// if !(self.mutedBy ?? Set()).contains(mastodonUser) { -// self.mutableSetValue(forKey: #keyPath(Status.mutedBy)).add(mastodonUser) -// } -// } else { -// if (self.mutedBy ?? Set()).contains(mastodonUser) { -// self.mutableSetValue(forKey: #keyPath(Status.mutedBy)).remove(mastodonUser) -// } -// } -// } -// -// public func update(bookmarked: Bool, by mastodonUser: MastodonUser) { -// if bookmarked { -// if !(self.bookmarkedBy ?? Set()).contains(mastodonUser) { -// self.mutableSetValue(forKey: #keyPath(Status.bookmarkedBy)).add(mastodonUser) -// } -// } else { -// if (self.bookmarkedBy ?? Set()).contains(mastodonUser) { -// self.mutableSetValue(forKey: #keyPath(Status.bookmarkedBy)).remove(mastodonUser) -// } -// } -// } -// -// public func didUpdate(at networkDate: Date) { -// self.updatedAt = networkDate -// } } @@ -737,78 +577,3 @@ extension Status { mutableSetValue(forKey: #keyPath(Status.feeds)).add(feed) } } - - -//extension Status { -// public struct Property { -// -// public let identifier: ID -// public let domain: String -// -// public let id: String -// public let uri: String -// public let createdAt: Date -// public let content: String -// -// public let visibility: String? -// public let sensitive: Bool -// public let spoilerText: String? -// -// public let emojisData: Data? -// -// public let reblogsCount: NSNumber -// public let favouritesCount: NSNumber -// public let repliesCount: NSNumber? -// -// public let url: String? -// public let inReplyToID: Status.ID? -// public let inReplyToAccountID: MastodonUser.ID? -// public let language: String? // (ISO 639 Part @1 two-letter language code) -// public let text: String? -// -// public let networkDate: Date -// -// public init( -// domain: String, -// id: String, -// uri: String, -// createdAt: Date, -// content: String, -// visibility: String?, -// sensitive: Bool, -// spoilerText: String?, -// emojisData: Data?, -// reblogsCount: NSNumber, -// favouritesCount: NSNumber, -// repliesCount: NSNumber?, -// url: String?, -// inReplyToID: Status.ID?, -// inReplyToAccountID: MastodonUser.ID?, -// language: String?, -// text: String?, -// networkDate: Date -// ) { -// self.identifier = id + "@" + domain -// self.domain = domain -// self.id = id -// self.uri = uri -// self.createdAt = createdAt -// self.content = content -// self.visibility = visibility -// self.sensitive = sensitive -// self.spoilerText = spoilerText -// self.emojisData = emojisData -// self.reblogsCount = reblogsCount -// self.favouritesCount = favouritesCount -// self.repliesCount = repliesCount -// self.url = url -// self.inReplyToID = inReplyToID -// self.inReplyToAccountID = inReplyToAccountID -// self.language = language -// self.text = text -// self.networkDate = networkDate -// } -// -// } -//} -// diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/Label/secondary.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/Label/secondary.colorset/Contents.json index 9d73ead0..cd123376 100644 --- a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/Label/secondary.colorset/Contents.json +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Colors/Label/secondary.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "0.600", - "blue" : "0.263", - "green" : "0.235", - "red" : "0.235" + "blue" : "67", + "green" : "60", + "red" : "60" } }, "idiom" : "universal" @@ -23,9 +23,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0.678", - "green" : "0.616", - "red" : "0.592" + "blue" : "173", + "green" : "157", + "red" : "151" } }, "idiom" : "universal" diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Onboarding/onboarding.background.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Onboarding/background.colorset/Contents.json similarity index 100% rename from MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Onboarding/onboarding.background.colorset/Contents.json rename to MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Onboarding/background.colorset/Contents.json diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Onboarding/navigation.next.button.background.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Onboarding/navigation.next.button.background.colorset/Contents.json index a36ab82c..0c0c8af0 100644 --- a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Onboarding/navigation.next.button.background.colorset/Contents.json +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Onboarding/navigation.next.button.background.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0.216", - "green" : "0.173", - "red" : "0.157" + "blue" : "55", + "green" : "44", + "red" : "40" } }, "idiom" : "universal" diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Profile/RelationshipButton/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Profile/RelationshipButton/Contents.json new file mode 100644 index 00000000..6e965652 --- /dev/null +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Profile/RelationshipButton/Contents.json @@ -0,0 +1,9 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "provides-namespace" : true + } +} diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Profile/RelationshipButton/background.dark.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Profile/RelationshipButton/background.dark.colorset/Contents.json new file mode 100644 index 00000000..63600675 --- /dev/null +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Profile/RelationshipButton/background.dark.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.933", + "green" : "0.933", + "red" : "0.933" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Profile/RelationshipButton/background.highlighted.dark.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Profile/RelationshipButton/background.highlighted.dark.colorset/Contents.json new file mode 100644 index 00000000..4e900a60 --- /dev/null +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Profile/RelationshipButton/background.highlighted.dark.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.729", + "green" : "0.729", + "red" : "0.729" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Profile/RelationshipButton/background.highlighted.light.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Profile/RelationshipButton/background.highlighted.light.colorset/Contents.json new file mode 100644 index 00000000..6ba0d80b --- /dev/null +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Profile/RelationshipButton/background.highlighted.light.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.106", + "green" : "0.082", + "red" : "0.075" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Profile/RelationshipButton/background.light.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Profile/RelationshipButton/background.light.colorset/Contents.json new file mode 100644 index 00000000..70d85d5d --- /dev/null +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Profile/RelationshipButton/background.light.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.216", + "green" : "0.173", + "red" : "0.157" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Setting/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Setting/Contents.json new file mode 100644 index 00000000..6e965652 --- /dev/null +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Setting/Contents.json @@ -0,0 +1,9 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "provides-namespace" : true + } +} diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Setting/background.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Setting/background.colorset/Contents.json new file mode 100644 index 00000000..4d55227b --- /dev/null +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Scene/Setting/background.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.969", + "green" : "0.949", + "red" : "0.949" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0.129", + "green" : "0.106", + "red" : "0.098" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/automatic.imageset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/automatic.imageset/Contents.json new file mode 100644 index 00000000..634b1b24 --- /dev/null +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/automatic.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "automatic.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "automatic@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "automatic@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/automatic.imageset/automatic.png b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/automatic.imageset/automatic.png new file mode 100644 index 00000000..8a499702 Binary files /dev/null and b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/automatic.imageset/automatic.png differ diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/automatic.imageset/automatic@2x.png b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/automatic.imageset/automatic@2x.png new file mode 100644 index 00000000..353f123a Binary files /dev/null and b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/automatic.imageset/automatic@2x.png differ diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/automatic.imageset/automatic@3x.png b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/automatic.imageset/automatic@3x.png new file mode 100644 index 00000000..6a865417 Binary files /dev/null and b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/automatic.imageset/automatic@3x.png differ diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/black.auto.imageset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/black.auto.imageset/Contents.json deleted file mode 100644 index 909d1ad2..00000000 --- a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/black.auto.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images" : [ - { - "filename" : "Mixed_Black_Light.png", - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/black.auto.imageset/Mixed_Black_Light.png b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/black.auto.imageset/Mixed_Black_Light.png deleted file mode 100644 index d27078d5..00000000 Binary files a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/black.auto.imageset/Mixed_Black_Light.png and /dev/null differ diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/black.imageset/Home Black.png b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/black.imageset/Home Black.png deleted file mode 100644 index b7348ae9..00000000 Binary files a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/black.imageset/Home Black.png and /dev/null differ diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/dark.auto.imageset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/dark.auto.imageset/Contents.json deleted file mode 100644 index 3b7f153c..00000000 --- a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/dark.auto.imageset/Contents.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "images" : [ - { - "filename" : "Mixed_Dark_Light.png", - "idiom" : "universal" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/dark.auto.imageset/Mixed_Dark_Light.png b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/dark.auto.imageset/Mixed_Dark_Light.png deleted file mode 100644 index 45067591..00000000 Binary files a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/dark.auto.imageset/Mixed_Dark_Light.png and /dev/null differ diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/dark.imageset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/dark.imageset/Contents.json index 01bdd059..45265b0c 100644 --- a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/dark.imageset/Contents.json +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/dark.imageset/Contents.json @@ -1,8 +1,19 @@ { "images" : [ { - "filename" : "Home Dark.png", - "idiom" : "universal" + "filename" : "dark.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "dark@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "dark@3x.png", + "idiom" : "universal", + "scale" : "3x" } ], "info" : { diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/dark.imageset/Home Dark.png b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/dark.imageset/Home Dark.png deleted file mode 100644 index 46926d86..00000000 Binary files a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/dark.imageset/Home Dark.png and /dev/null differ diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/dark.imageset/dark.png b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/dark.imageset/dark.png new file mode 100644 index 00000000..5bfe79ab Binary files /dev/null and b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/dark.imageset/dark.png differ diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/dark.imageset/dark@2x.png b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/dark.imageset/dark@2x.png new file mode 100644 index 00000000..4bbee362 Binary files /dev/null and b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/dark.imageset/dark@2x.png differ diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/dark.imageset/dark@3x.png b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/dark.imageset/dark@3x.png new file mode 100644 index 00000000..4ea316fb Binary files /dev/null and b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/dark.imageset/dark@3x.png differ diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/light.imageset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/light.imageset/Contents.json index beb5cfcf..c89e6245 100644 --- a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/light.imageset/Contents.json +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/light.imageset/Contents.json @@ -1,8 +1,19 @@ { "images" : [ { - "filename" : "Home Light.png", - "idiom" : "universal" + "filename" : "light.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "light@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "light@3x.png", + "idiom" : "universal", + "scale" : "3x" } ], "info" : { diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/light.imageset/Home Light.png b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/light.imageset/Home Light.png deleted file mode 100644 index cafff0bb..00000000 Binary files a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/light.imageset/Home Light.png and /dev/null differ diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/light.imageset/light.png b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/light.imageset/light.png new file mode 100644 index 00000000..23efb384 Binary files /dev/null and b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/light.imageset/light.png differ diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/light.imageset/light@2x.png b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/light.imageset/light@2x.png new file mode 100644 index 00000000..6bff099c Binary files /dev/null and b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/light.imageset/light@2x.png differ diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/light.imageset/light@3x.png b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/light.imageset/light@3x.png new file mode 100644 index 00000000..94c68eb5 Binary files /dev/null and b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Settings/light.imageset/light@3x.png differ diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/Mastodon/Background/secondary.system.background.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/Mastodon/Background/secondary.system.background.colorset/Contents.json index c915c891..14b5119b 100644 --- a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/Mastodon/Background/secondary.system.background.colorset/Contents.json +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/Mastodon/Background/secondary.system.background.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0.910", - "green" : "0.882", - "red" : "0.851" + "blue" : "0xF7", + "green" : "0xF2", + "red" : "0xF2" } }, "idiom" : "universal" diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/Mastodon/Background/sidebar.background.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/Mastodon/Background/sidebar.background.colorset/Contents.json index e30d6cab..bc3fb38b 100644 --- a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/Mastodon/Background/sidebar.background.colorset/Contents.json +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/Mastodon/Background/sidebar.background.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0.945", - "green" : "0.945", - "red" : "0.945" + "blue" : "0xF7", + "green" : "0xF2", + "red" : "0xF2" } }, "idiom" : "universal" diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/Mastodon/Background/system.elevated.background.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/Mastodon/Background/system.elevated.background.colorset/Contents.json index 33b71ef9..d47dc714 100644 --- a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/Mastodon/Background/system.elevated.background.colorset/Contents.json +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/Mastodon/Background/system.elevated.background.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "1.000", - "green" : "1.000", - "red" : "1.000" + "blue" : "0xF2", + "green" : "0xED", + "red" : "0xE9" } }, "idiom" : "universal" diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/Mastodon/Background/system.grouped.background.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/Mastodon/Background/system.grouped.background.colorset/Contents.json index c915c891..14b5119b 100644 --- a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/Mastodon/Background/system.grouped.background.colorset/Contents.json +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/Mastodon/Background/system.grouped.background.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0.910", - "green" : "0.882", - "red" : "0.851" + "blue" : "0xF7", + "green" : "0xF2", + "red" : "0xF2" } }, "idiom" : "universal" diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/Mastodon/Background/tertiary.system.grouped.background.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/Mastodon/Background/tertiary.system.grouped.background.colorset/Contents.json index 98dd7bbd..bc3fb38b 100644 --- a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/Mastodon/Background/tertiary.system.grouped.background.colorset/Contents.json +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/Mastodon/Background/tertiary.system.grouped.background.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0.910", - "green" : "0.882", - "red" : "0.851" + "blue" : "0xF7", + "green" : "0xF2", + "red" : "0xF2" } }, "idiom" : "universal" diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/secondary.grouped.system.background.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/secondary.grouped.system.background.colorset/Contents.json index b054549a..b0a1b74f 100644 --- a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/secondary.grouped.system.background.colorset/Contents.json +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/secondary.grouped.system.background.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0.996", - "green" : "1.000", - "red" : "0.996" + "blue" : "254", + "green" : "255", + "red" : "254" } }, "idiom" : "universal" @@ -23,9 +23,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0.180", - "green" : "0.173", - "red" : "0.173" + "blue" : "0x2D", + "green" : "0x2C", + "red" : "0x2C" } }, "idiom" : "universal" diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/secondary.system.background.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/secondary.system.background.colorset/Contents.json index facc139f..8fd668a5 100644 --- a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/secondary.system.background.colorset/Contents.json +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/secondary.system.background.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0.910", - "green" : "0.878", - "red" : "0.851" + "blue" : "0xF7", + "green" : "0xF2", + "red" : "0xF2" } }, "idiom" : "universal" @@ -23,9 +23,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0.180", - "green" : "0.173", - "red" : "0.173" + "blue" : "0x2D", + "green" : "0x2C", + "red" : "0x2C" } }, "idiom" : "universal" diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/sidebar.background.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/sidebar.background.colorset/Contents.json index 03bc91c3..f30d4222 100644 --- a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/sidebar.background.colorset/Contents.json +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/sidebar.background.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0.945", - "green" : "0.945", - "red" : "0.945" + "blue" : "0xF7", + "green" : "0xF2", + "red" : "0xF2" } }, "idiom" : "universal" diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/system.background.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/system.background.colorset/Contents.json index 2b3ad55e..ab7d9539 100644 --- a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/system.background.colorset/Contents.json +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/system.background.colorset/Contents.json @@ -23,9 +23,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0.000", - "green" : "0.000", - "red" : "0.000" + "blue" : "0x00", + "green" : "0x00", + "red" : "0x00" } }, "idiom" : "universal" diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/system.elevated.background.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/system.elevated.background.colorset/Contents.json index ca11ee75..25365248 100644 --- a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/system.elevated.background.colorset/Contents.json +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/system.elevated.background.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "1.000", - "green" : "1.000", - "red" : "1.000" + "blue" : "0xF2", + "green" : "0xED", + "red" : "0xE9" } }, "idiom" : "universal" @@ -23,9 +23,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0.118", - "green" : "0.110", - "red" : "0.110" + "blue" : "30", + "green" : "28", + "red" : "28" } }, "idiom" : "universal" diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/system.grouped.background.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/system.grouped.background.colorset/Contents.json index bcd0e01f..05051dc5 100644 --- a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/system.grouped.background.colorset/Contents.json +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/system.grouped.background.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0.910", - "green" : "0.878", - "red" : "0.851" + "blue" : "0xF7", + "green" : "0xF2", + "red" : "0xF2" } }, "idiom" : "universal" diff --git a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/tertiary.system.grouped.background.colorset/Contents.json b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/tertiary.system.grouped.background.colorset/Contents.json index 6b9fb70a..30aadfbc 100644 --- a/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/tertiary.system.grouped.background.colorset/Contents.json +++ b/MastodonSDK/Sources/MastodonAsset/Assets.xcassets/Theme/system/Background/tertiary.system.grouped.background.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "0.910", - "green" : "0.882", - "red" : "0.851" + "blue" : "0xF7", + "green" : "0xF2", + "red" : "0xF2" } }, "idiom" : "universal" diff --git a/MastodonSDK/Sources/MastodonAsset/Generated/Assets.swift b/MastodonSDK/Sources/MastodonAsset/Generated/Assets.swift index 23aa940d..26e54900 100644 --- a/MastodonSDK/Sources/MastodonAsset/Generated/Assets.swift +++ b/MastodonSDK/Sources/MastodonAsset/Generated/Assets.swift @@ -105,11 +105,11 @@ public enum Asset { public enum Scene { public enum Onboarding { public static let avatarPlaceholder = ImageAsset(name: "Scene/Onboarding/avatar.placeholder") + public static let background = ColorAsset(name: "Scene/Onboarding/background") public static let navigationBackButtonBackground = ColorAsset(name: "Scene/Onboarding/navigation.back.button.background") public static let navigationBackButtonBackgroundHighlighted = ColorAsset(name: "Scene/Onboarding/navigation.back.button.background.highlighted") public static let navigationNextButtonBackground = ColorAsset(name: "Scene/Onboarding/navigation.next.button.background") public static let navigationNextButtonBackgroundHighlighted = ColorAsset(name: "Scene/Onboarding/navigation.next.button.background.highlighted") - public static let onboardingBackground = ColorAsset(name: "Scene/Onboarding/onboarding.background") public static let searchBarBackground = ColorAsset(name: "Scene/Onboarding/search.bar.background") public static let textFieldBackground = ColorAsset(name: "Scene/Onboarding/textField.background") } @@ -119,11 +119,20 @@ public enum Asset { public static let nameEditBackgroundGray = ColorAsset(name: "Scene/Profile/Banner/name.edit.background.gray") public static let usernameGray = ColorAsset(name: "Scene/Profile/Banner/username.gray") } + public enum RelationshipButton { + public static let backgroundDark = ColorAsset(name: "Scene/Profile/RelationshipButton/background.dark") + public static let backgroundHighlightedDark = ColorAsset(name: "Scene/Profile/RelationshipButton/background.highlighted.dark") + public static let backgroundHighlightedLight = ColorAsset(name: "Scene/Profile/RelationshipButton/background.highlighted.light") + public static let backgroundLight = ColorAsset(name: "Scene/Profile/RelationshipButton/background.light") + } } public enum Report { public static let background = ColorAsset(name: "Scene/Report/background") public static let reportBanner = ColorAsset(name: "Scene/Report/report.banner") } + public enum Setting { + public static let background = ColorAsset(name: "Scene/Setting/background") + } public enum Sidebar { public static let logo = ImageAsset(name: "Scene/Sidebar/logo") } @@ -146,9 +155,7 @@ public enum Asset { } } public enum Settings { - public static let blackAuto = ImageAsset(name: "Settings/black.auto") - public static let black = ImageAsset(name: "Settings/black") - public static let darkAuto = ImageAsset(name: "Settings/dark.auto") + public static let automatic = ImageAsset(name: "Settings/automatic") public static let dark = ImageAsset(name: "Settings/dark") public static let light = ImageAsset(name: "Settings/light") } diff --git a/MastodonSDK/Sources/MastodonLocalization/Generated/Strings.swift b/MastodonSDK/Sources/MastodonLocalization/Generated/Strings.swift index 805a7e52..69e15f2d 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Generated/Strings.swift +++ b/MastodonSDK/Sources/MastodonLocalization/Generated/Strings.swift @@ -36,9 +36,9 @@ public enum L10n { public static let pleaseTryAgainLater = L10n.tr("Localizable", "Common.Alerts.Common.PleaseTryAgainLater") } public enum DeletePost { - /// Delete - public static let delete = L10n.tr("Localizable", "Common.Alerts.DeletePost.Delete") /// Are you sure you want to delete this post? + public static let message = L10n.tr("Localizable", "Common.Alerts.DeletePost.Message") + /// Delete Post public static let title = L10n.tr("Localizable", "Common.Alerts.DeletePost.Title") } public enum DiscardPostContent { @@ -132,6 +132,8 @@ public enum L10n { public static let ok = L10n.tr("Localizable", "Common.Controls.Actions.Ok") /// Open public static let `open` = L10n.tr("Localizable", "Common.Controls.Actions.Open") + /// Open in Browser + public static let openInBrowser = L10n.tr("Localizable", "Common.Controls.Actions.OpenInBrowser") /// Open in Safari public static let openInSafari = L10n.tr("Localizable", "Common.Controls.Actions.OpenInSafari") /// Preview @@ -283,6 +285,8 @@ public enum L10n { public enum Actions { /// Favorite public static let favorite = L10n.tr("Localizable", "Common.Controls.Status.Actions.Favorite") + /// Hide + public static let hide = L10n.tr("Localizable", "Common.Controls.Status.Actions.Hide") /// Menu public static let menu = L10n.tr("Localizable", "Common.Controls.Status.Actions.Menu") /// Reblog @@ -314,6 +318,16 @@ public enum L10n { /// URL public static let url = L10n.tr("Localizable", "Common.Controls.Status.Tag.Url") } + public enum Visibility { + /// Only mentioned user can see this post. + public static let direct = L10n.tr("Localizable", "Common.Controls.Status.Visibility.Direct") + /// Only their followers can see this post. + public static let `private` = L10n.tr("Localizable", "Common.Controls.Status.Visibility.Private") + /// Only my followers can see this post. + public static let privateFromMe = L10n.tr("Localizable", "Common.Controls.Status.Visibility.PrivateFromMe") + /// Everyone can see this post but not display in the public timeline. + public static let unlisted = L10n.tr("Localizable", "Common.Controls.Status.Visibility.Unlisted") + } } public enum Tabs { /// Home @@ -490,17 +504,15 @@ public enum L10n { } } public enum ConfirmEmail { - /// We just sent an email to %@,\ntap the link to confirm your account. - public static func subtitle(_ p1: Any) -> String { - return L10n.tr("Localizable", "Scene.ConfirmEmail.Subtitle", String(describing: p1)) - } + /// Tap the link we emailed to you to verify your account. + public static let subtitle = L10n.tr("Localizable", "Scene.ConfirmEmail.Subtitle") /// One last thing. public static let title = L10n.tr("Localizable", "Scene.ConfirmEmail.Title") public enum Button { - /// I never got an email - public static let dontReceiveEmail = L10n.tr("Localizable", "Scene.ConfirmEmail.Button.DontReceiveEmail") /// Open Email App public static let openEmailApp = L10n.tr("Localizable", "Scene.ConfirmEmail.Button.OpenEmailApp") + /// Resend + public static let resend = L10n.tr("Localizable", "Scene.ConfirmEmail.Button.Resend") } public enum DontReceiveEmail { /// Check if your email address is correct as well as your junk folder if you haven’t. @@ -548,36 +560,26 @@ public enum L10n { } } public enum Notification { - /// %@ favorited your post - public static func userFavoritedYourPost(_ p1: Any) -> String { - return L10n.tr("Localizable", "Scene.Notification.UserFavorited Your Post", String(describing: p1)) - } - /// %@ followed you - public static func userFollowedYou(_ p1: Any) -> String { - return L10n.tr("Localizable", "Scene.Notification.UserFollowedYou", String(describing: p1)) - } - /// %@ mentioned you - public static func userMentionedYou(_ p1: Any) -> String { - return L10n.tr("Localizable", "Scene.Notification.UserMentionedYou", String(describing: p1)) - } - /// %@ reblogged your post - public static func userRebloggedYourPost(_ p1: Any) -> String { - return L10n.tr("Localizable", "Scene.Notification.UserRebloggedYourPost", String(describing: p1)) - } - /// %@ requested to follow you - public static func userRequestedToFollowYou(_ p1: Any) -> String { - return L10n.tr("Localizable", "Scene.Notification.UserRequestedToFollowYou", String(describing: p1)) - } - /// %@ Your poll has ended - public static func userYourPollHasEnded(_ p1: Any) -> String { - return L10n.tr("Localizable", "Scene.Notification.UserYourPollHasEnded", String(describing: p1)) - } public enum Keyobard { /// Show Everything public static let showEverything = L10n.tr("Localizable", "Scene.Notification.Keyobard.ShowEverything") /// Show Mentions public static let showMentions = L10n.tr("Localizable", "Scene.Notification.Keyobard.ShowMentions") } + public enum NotificationDescription { + /// favorited your post + public static let favoritedYourPost = L10n.tr("Localizable", "Scene.Notification.NotificationDescription.FavoritedYourPost") + /// followed you + public static let followedYou = L10n.tr("Localizable", "Scene.Notification.NotificationDescription.FollowedYou") + /// mentioned you + public static let mentionedYou = L10n.tr("Localizable", "Scene.Notification.NotificationDescription.MentionedYou") + /// poll has ended + public static let pollHasEnded = L10n.tr("Localizable", "Scene.Notification.NotificationDescription.PollHasEnded") + /// reblogged your post + public static let rebloggedYourPost = L10n.tr("Localizable", "Scene.Notification.NotificationDescription.RebloggedYourPost") + /// request to follow you + public static let requestToFollowYou = L10n.tr("Localizable", "Scene.Notification.NotificationDescription.RequestToFollowYou") + } public enum Title { /// Everything public static let everything = L10n.tr("Localizable", "Scene.Notification.Title.Everything") @@ -615,13 +617,29 @@ public enum L10n { } } public enum RelationshipActionAlert { - public enum ConfirmUnblockUsre { + public enum ConfirmBlockUser { + /// Confirm to block %@ + public static func message(_ p1: Any) -> String { + return L10n.tr("Localizable", "Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Message", String(describing: p1)) + } + /// Block Account + public static let title = L10n.tr("Localizable", "Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title") + } + public enum ConfirmMuteUser { + /// Confirm to mute %@ + public static func message(_ p1: Any) -> String { + return L10n.tr("Localizable", "Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Message", String(describing: p1)) + } + /// Mute Account + public static let title = L10n.tr("Localizable", "Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Title") + } + public enum ConfirmUnblockUser { /// Confirm to unblock %@ public static func message(_ p1: Any) -> String { - return L10n.tr("Localizable", "Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Message", String(describing: p1)) + return L10n.tr("Localizable", "Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Message", String(describing: p1)) } /// Unblock Account - public static let title = L10n.tr("Localizable", "Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Title") + public static let title = L10n.tr("Localizable", "Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Title") } public enum ConfirmUnmuteUser { /// Confirm to unmute %@ @@ -633,17 +651,23 @@ public enum L10n { } } public enum SegmentedControl { + /// About + public static let about = L10n.tr("Localizable", "Scene.Profile.SegmentedControl.About") /// Media public static let media = L10n.tr("Localizable", "Scene.Profile.SegmentedControl.Media") /// Posts public static let posts = L10n.tr("Localizable", "Scene.Profile.SegmentedControl.Posts") + /// Posts and Replies + public static let postsAndReplies = L10n.tr("Localizable", "Scene.Profile.SegmentedControl.PostsAndReplies") /// Replies public static let replies = L10n.tr("Localizable", "Scene.Profile.SegmentedControl.Replies") } } public enum Register { - /// Tell us about you. - public static let title = L10n.tr("Localizable", "Scene.Register.Title") + /// Let’s get you set up on %@ + public static func title(_ p1: Any) -> String { + return L10n.tr("Localizable", "Scene.Register.Title", String(describing: p1)) + } public enum Error { public enum Item { /// Agreement @@ -730,10 +754,20 @@ public enum L10n { public static let registrationUserInviteRequest = L10n.tr("Localizable", "Scene.Register.Input.Invite.RegistrationUserInviteRequest") } public enum Password { + /// 8 characters + public static let characterLimit = L10n.tr("Localizable", "Scene.Register.Input.Password.CharacterLimit") /// Your password needs at least eight characters public static let hint = L10n.tr("Localizable", "Scene.Register.Input.Password.Hint") /// password public static let placeholder = L10n.tr("Localizable", "Scene.Register.Input.Password.Placeholder") + /// Your password needs at least: + public static let require = L10n.tr("Localizable", "Scene.Register.Input.Password.Require") + public enum Accessibility { + /// checked + public static let checked = L10n.tr("Localizable", "Scene.Register.Input.Password.Accessibility.Checked") + /// unchecked + public static let unchecked = L10n.tr("Localizable", "Scene.Register.Input.Password.Accessibility.Unchecked") + } } public enum Username { /// This username is taken. @@ -748,6 +782,10 @@ public enum L10n { public static let content1 = L10n.tr("Localizable", "Scene.Report.Content1") /// Is there anything the moderators should know about this report? public static let content2 = L10n.tr("Localizable", "Scene.Report.Content2") + /// REPORTED + public static let reported = L10n.tr("Localizable", "Scene.Report.Reported") + /// Thanks for reporting, we’ll look into this. + public static let reportSentTitle = L10n.tr("Localizable", "Scene.Report.ReportSentTitle") /// Send Report public static let send = L10n.tr("Localizable", "Scene.Report.Send") /// Send without comment @@ -762,6 +800,8 @@ public enum L10n { public static func title(_ p1: Any) -> String { return L10n.tr("Localizable", "Scene.Report.Title", String(describing: p1)) } + /// Report + public static let titleReport = L10n.tr("Localizable", "Scene.Report.TitleReport") } public enum Search { /// Search @@ -816,7 +856,11 @@ public enum L10n { } } public enum ServerPicker { - /// Pick a server,\nany server. + /// Pick a community based on your interests, region, or a general purpose one. + public static let subtitle = L10n.tr("Localizable", "Scene.ServerPicker.Subtitle") + /// Pick a community based on your interests, region, or a general purpose one. Each community is operated by an entirely independent organization or individual. + public static let subtitleExtend = L10n.tr("Localizable", "Scene.ServerPicker.SubtitleExtend") + /// Mastodon is made of users in different communities. public static let title = L10n.tr("Localizable", "Scene.ServerPicker.Title") public enum Button { /// See Less @@ -863,7 +907,7 @@ public enum L10n { public static let noResults = L10n.tr("Localizable", "Scene.ServerPicker.EmptyState.NoResults") } public enum Input { - /// Find a server or join your own... + /// Search communities public static let placeholder = L10n.tr("Localizable", "Scene.ServerPicker.Input.Placeholder") } public enum Label { @@ -882,7 +926,7 @@ public enum L10n { public static func prompt(_ p1: Any) -> String { return L10n.tr("Localizable", "Scene.ServerRules.Prompt", String(describing: p1)) } - /// These rules are set by the admins of %@. + /// These are set and enforced by the %@ moderators. public static func subtitle(_ p1: Any) -> String { return L10n.tr("Localizable", "Scene.ServerRules.Subtitle", String(describing: p1)) } @@ -929,6 +973,18 @@ public enum L10n { /// The Boring Zone public static let title = L10n.tr("Localizable", "Scene.Settings.Section.BoringZone.Title") } + public enum LookAndFeel { + /// Light + public static let light = L10n.tr("Localizable", "Scene.Settings.Section.LookAndFeel.Light") + /// Really Dark + public static let reallyDark = L10n.tr("Localizable", "Scene.Settings.Section.LookAndFeel.ReallyDark") + /// Sorta Dark + public static let sortaDark = L10n.tr("Localizable", "Scene.Settings.Section.LookAndFeel.SortaDark") + /// Look and Feel + public static let title = L10n.tr("Localizable", "Scene.Settings.Section.LookAndFeel.Title") + /// Use System + public static let useSystem = L10n.tr("Localizable", "Scene.Settings.Section.LookAndFeel.UseSystem") + } public enum Notifications { /// Reblogs my post public static let boosts = L10n.tr("Localizable", "Scene.Settings.Section.Notifications.Boosts") @@ -990,6 +1046,10 @@ public enum L10n { } } public enum Welcome { + /// Get Started + public static let getStarted = L10n.tr("Localizable", "Scene.Welcome.GetStarted") + /// Log In + public static let logIn = L10n.tr("Localizable", "Scene.Welcome.LogIn") /// Social networking\nback in your hands. public static let slogan = L10n.tr("Localizable", "Scene.Welcome.Slogan") } diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/ar.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/ar.lproj/Localizable.strings index b878e034..668c7788 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/ar.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/ar.lproj/Localizable.strings @@ -1,15 +1,15 @@ -"Common.Alerts.BlockDomain.BlockEntireDomain" = "حظر النِطاق"; -"Common.Alerts.BlockDomain.Title" = "هل أنتَ مُتأكِّدٌ حقًا مِن رغبتك في حظر %@ بالكامل؟ في معظم الحالات، يكون مِنَ الكافي والمُفَضَّل استهداف عدد محدود للحظر أو الكتم. لن ترى محتوى من هذا النطاق وسوف يتم إزالة جميع متابعيك المتواجدين فيه."; -"Common.Alerts.CleanCache.Message" = "تمَّ مَحو ذاكرة التخزين المؤقت %@ بنجاح."; +"Common.Alerts.BlockDomain.BlockEntireDomain" = "حظر النِّطاق"; +"Common.Alerts.BlockDomain.Title" = "هل أنتَ مُتأكِّدٌ حقًا مِن رغبتك في حظر %@ بالكامل؟ في معظم الحالات، يكون مِنَ الكافي والمُفَضَّل استهداف عدد محدود للحظر أو الكتم. لن ترى محتوى من هذا النطاق وسوف يُزال جميع متابعيك المتواجدين فيه."; +"Common.Alerts.CleanCache.Message" = "تمَّ مَحو %@ مِن ذاكرة التخزين المؤقت بنجاح."; "Common.Alerts.CleanCache.Title" = "مَحو ذاكرة التخزين المؤقت"; -"Common.Alerts.Common.PleaseTryAgain" = "يُرجى المحاولة مرة أُخرى."; -"Common.Alerts.Common.PleaseTryAgainLater" = "يُرجى المحاولة مرة أُخرى لاحقاً."; -"Common.Alerts.DeletePost.Delete" = "احذف"; +"Common.Alerts.Common.PleaseTryAgain" = "يُرجى المُحاولة مرة أُخرى."; +"Common.Alerts.Common.PleaseTryAgainLater" = "يُرجى المُحاولة مرة أُخرى لاحقًا."; +"Common.Alerts.DeletePost.Message" = "هَل أنتَ مُتأكِدٌ مِن رَغبتِكَ فِي حَذفِ هَذَا المَنشُور؟"; "Common.Alerts.DeletePost.Title" = "هل أنت متأكد من رغبتك في حذف هذا المنشور؟"; "Common.Alerts.DiscardPostContent.Message" = "أكِّد للتخلص مِن مُحتوى مَنشور مؤلَّف."; "Common.Alerts.DiscardPostContent.Title" = "التخلص من المسودة"; -"Common.Alerts.EditProfileFailure.Message" = "لا يمكن تعديل الملف الشخصي. يُرجى المحاولة مرة أُخرى."; -"Common.Alerts.EditProfileFailure.Title" = "خطأ في تَحرير الملف الشخصي"; +"Common.Alerts.EditProfileFailure.Message" = "يتعذَّر تعديل الملف التعريفي. يُرجى المُحاولة مرة أُخرى."; +"Common.Alerts.EditProfileFailure.Title" = "خطأ في تَحرير الملف التعريفي"; "Common.Alerts.PublishPostFailure.AttachmentsMessage.MoreThanOneVideo" = "لا يُمكِنُ إرفاق أكثر مِن مَقطع مرئي واحِد."; "Common.Alerts.PublishPostFailure.AttachmentsMessage.VideoAttachWithPhoto" = "لا يُمكن إرفاق مقطع مرئي إلى مَنشور يحتوي بالفعل على صُوَر."; "Common.Alerts.PublishPostFailure.Message" = "فَشَلَ نَشر المَنشور. @@ -19,7 +19,7 @@ "Common.Alerts.SavePhotoFailure.Title" = "إخفاق في حفظ الصورة"; "Common.Alerts.ServerError.Title" = "خطأ في الخادم"; "Common.Alerts.SignOut.Confirm" = "تسجيل الخروج"; -"Common.Alerts.SignOut.Message" = "هل أنت متأكد من رغبتك في تسجيل الخروج؟"; +"Common.Alerts.SignOut.Message" = "هل أنت متأكد من رغبتك في تسجيل الخُروج؟"; "Common.Alerts.SignOut.Title" = "تسجيل الخروج"; "Common.Alerts.SignUpFailure.Title" = "إخفاق في التسجيل"; "Common.Alerts.VoteFailure.PollEnded" = "انتهى استطلاع الرأي"; @@ -32,21 +32,22 @@ "Common.Controls.Actions.Confirm" = "تأكيد"; "Common.Controls.Actions.Continue" = "واصل"; "Common.Controls.Actions.CopyPhoto" = "نسخ الصورة"; -"Common.Controls.Actions.Delete" = "احذف"; -"Common.Controls.Actions.Discard" = "تجاهل"; +"Common.Controls.Actions.Delete" = "حذف"; +"Common.Controls.Actions.Discard" = "تجاهُل"; "Common.Controls.Actions.Done" = "تمّ"; "Common.Controls.Actions.Edit" = "تحرير"; -"Common.Controls.Actions.FindPeople" = "ابحث عن أشخاص لمتابعتهم"; -"Common.Controls.Actions.ManuallySearch" = "البحث يدوياً بدلاً من ذلك"; +"Common.Controls.Actions.FindPeople" = "ابحث عن أشخاص لِمُتابعتهم"; +"Common.Controls.Actions.ManuallySearch" = "البحث يدويًا بدلًا من ذلك"; "Common.Controls.Actions.Next" = "التالي"; "Common.Controls.Actions.Ok" = "حسنًا"; -"Common.Controls.Actions.Open" = "افتح"; -"Common.Controls.Actions.OpenInSafari" = "الفتح في Safari"; +"Common.Controls.Actions.Open" = "فتح"; +"Common.Controls.Actions.OpenInBrowser" = "الفَتحُ في المُتَصَفِّح"; +"Common.Controls.Actions.OpenInSafari" = "الفَتحُ في Safari"; "Common.Controls.Actions.Preview" = "مُعاينة"; "Common.Controls.Actions.Previous" = "السابق"; -"Common.Controls.Actions.Remove" = "احذف"; -"Common.Controls.Actions.Reply" = "الرَد"; -"Common.Controls.Actions.ReportUser" = "ابلغ عن %@"; +"Common.Controls.Actions.Remove" = "حذف"; +"Common.Controls.Actions.Reply" = "الرَّد"; +"Common.Controls.Actions.ReportUser" = "الإبلاغ عن %@"; "Common.Controls.Actions.Save" = "حفظ"; "Common.Controls.Actions.SavePhoto" = "حفظ الصورة"; "Common.Controls.Actions.SeeMore" = "عرض المزيد"; @@ -59,290 +60,318 @@ "Common.Controls.Actions.Skip" = "تخطي"; "Common.Controls.Actions.TakePhoto" = "التقاط صورة"; "Common.Controls.Actions.TryAgain" = "المُحاولة مرة أُخرى"; -"Common.Controls.Actions.UnblockDomain" = "إلغاء حظر %@"; +"Common.Controls.Actions.UnblockDomain" = "رفع الحظر عن %@"; "Common.Controls.Friendship.Block" = "حظر"; "Common.Controls.Friendship.BlockDomain" = "حظر %@"; "Common.Controls.Friendship.BlockUser" = "حظر %@"; "Common.Controls.Friendship.Blocked" = "محظور"; "Common.Controls.Friendship.EditInfo" = "تعديل المعلومات"; -"Common.Controls.Friendship.Follow" = "اتبع"; +"Common.Controls.Friendship.Follow" = "مُتابَعَة"; "Common.Controls.Friendship.Following" = "مُتابَع"; -"Common.Controls.Friendship.Mute" = "أكتم"; -"Common.Controls.Friendship.MuteUser" = "أكتم %@"; +"Common.Controls.Friendship.Mute" = "كَتم"; +"Common.Controls.Friendship.MuteUser" = "كَتم %@"; "Common.Controls.Friendship.Muted" = "مكتوم"; "Common.Controls.Friendship.Pending" = "قيد المُراجعة"; "Common.Controls.Friendship.Request" = "إرسال طَلَب"; -"Common.Controls.Friendship.Unblock" = "إلغاء الحَظر"; -"Common.Controls.Friendship.UnblockUser" = "إلغاء حظر %@"; -"Common.Controls.Friendship.Unmute" = "إلغاء الكتم"; -"Common.Controls.Friendship.UnmuteUser" = "إلغاء كتم %@"; +"Common.Controls.Friendship.Unblock" = "رفع الحَظر"; +"Common.Controls.Friendship.UnblockUser" = "رفع الحَظر عن %@"; +"Common.Controls.Friendship.Unmute" = "رفع الكتم"; +"Common.Controls.Friendship.UnmuteUser" = "رفع الكتم عن %@"; "Common.Controls.Keyboard.Common.ComposeNewPost" = "تأليف منشور جديد"; -"Common.Controls.Keyboard.Common.OpenSettings" = "أفتح الإعدادات"; -"Common.Controls.Keyboard.Common.ShowFavorites" = "إظهار المفضلة"; +"Common.Controls.Keyboard.Common.OpenSettings" = "فَتحُ الإعدادات"; +"Common.Controls.Keyboard.Common.ShowFavorites" = "إظهار المُفضَّلة"; "Common.Controls.Keyboard.Common.SwitchToTab" = "التبديل إلى %@"; "Common.Controls.Keyboard.SegmentedControl.NextSection" = "القسم التالي"; "Common.Controls.Keyboard.SegmentedControl.PreviousSection" = "القسم السابق"; "Common.Controls.Keyboard.Timeline.NextStatus" = "المنشور التالي"; -"Common.Controls.Keyboard.Timeline.OpenAuthorProfile" = "افتح الملف التعريفي للمؤلف"; -"Common.Controls.Keyboard.Timeline.OpenRebloggerProfile" = "افتح الملف التعريفي لمشارِك المنشور"; -"Common.Controls.Keyboard.Timeline.OpenStatus" = "افتح المنشور"; +"Common.Controls.Keyboard.Timeline.OpenAuthorProfile" = "فتح الملف التعريفي للمؤلف"; +"Common.Controls.Keyboard.Timeline.OpenRebloggerProfile" = "فتح الملف التعريفي لمُعيد تدوين المنشور"; +"Common.Controls.Keyboard.Timeline.OpenStatus" = "فتح المنشور"; "Common.Controls.Keyboard.Timeline.PreviewImage" = "معاينة الصورة"; "Common.Controls.Keyboard.Timeline.PreviousStatus" = "المنشور السابق"; -"Common.Controls.Keyboard.Timeline.ReplyStatus" = "رد على المنشور"; +"Common.Controls.Keyboard.Timeline.ReplyStatus" = "الرَّد على مَنشور"; "Common.Controls.Keyboard.Timeline.ToggleContentWarning" = "تبديل تحذير المُحتَوى"; "Common.Controls.Keyboard.Timeline.ToggleFavorite" = "تبديل المفضلة لِمنشور"; -"Common.Controls.Keyboard.Timeline.ToggleReblog" = "تبديل إعادة تدوين منشور"; -"Common.Controls.Status.Actions.Favorite" = "إضافة إلى المفضلة"; +"Common.Controls.Keyboard.Timeline.ToggleReblog" = "تبديل إعادة تدوين مَنشور"; +"Common.Controls.Status.Actions.Favorite" = "التفضيل"; +"Common.Controls.Status.Actions.Hide" = "إخفاء"; "Common.Controls.Status.Actions.Menu" = "القائمة"; "Common.Controls.Status.Actions.Reblog" = "إعادة النشر"; -"Common.Controls.Status.Actions.Reply" = "رد"; -"Common.Controls.Status.Actions.Unfavorite" = "إزالة من المفضلة"; -"Common.Controls.Status.Actions.Unreblog" = "تراجع عن إعادة النشر"; -"Common.Controls.Status.ContentWarning" = "تحذير عن المحتوى"; -"Common.Controls.Status.MediaContentWarning" = "انقر على أي مكان للكشف"; +"Common.Controls.Status.Actions.Reply" = "الرَّد"; +"Common.Controls.Status.Actions.Unfavorite" = "إزالة التفضيل"; +"Common.Controls.Status.Actions.Unreblog" = "التراجُع عن إعادة النشر"; +"Common.Controls.Status.ContentWarning" = "تحذير المُحتوى"; +"Common.Controls.Status.MediaContentWarning" = "انقر للكشف"; "Common.Controls.Status.Poll.Closed" = "انتهى"; "Common.Controls.Status.Poll.Vote" = "صَوِّت"; -"Common.Controls.Status.ShowPost" = "اظهر المنشور"; -"Common.Controls.Status.ShowUserProfile" = "اظهر الملف التعريفي للمستخدم"; -"Common.Controls.Status.Tag.Email" = "البريد الإلكتروني"; -"Common.Controls.Status.Tag.Emoji" = "إيموجي"; -"Common.Controls.Status.Tag.Hashtag" = "الوسم"; -"Common.Controls.Status.Tag.Link" = "الرابط"; -"Common.Controls.Status.Tag.Mention" = "أشر إلى"; +"Common.Controls.Status.ShowPost" = "إظهار منشور"; +"Common.Controls.Status.ShowUserProfile" = "إظهار الملف التعريفي للمُستخدِم"; +"Common.Controls.Status.Tag.Email" = "بريد إلكتروني"; +"Common.Controls.Status.Tag.Emoji" = "رمز تعبيري"; +"Common.Controls.Status.Tag.Hashtag" = "وسم"; +"Common.Controls.Status.Tag.Link" = "رابط"; +"Common.Controls.Status.Tag.Mention" = "إشارة"; "Common.Controls.Status.Tag.Url" = "عنوان URL"; "Common.Controls.Status.UserReblogged" = "أعادَ %@ تدوينها"; -"Common.Controls.Status.UserRepliedTo" = "رد على %@"; -"Common.Controls.Tabs.Home" = "الخيط الرئيسي"; +"Common.Controls.Status.UserRepliedTo" = "رَدًا على %@"; +"Common.Controls.Status.Visibility.Direct" = "المُستخدمِونَ المُشارِ إليهم فَقَطْ مَن يُمكِنُهُم رُؤيَةُ هَذَا المَنشُور."; +"Common.Controls.Status.Visibility.Private" = "فَقَطْ مُتابِعينَهُم مَن يُمكِنُهُم رُؤيَةُ هَذَا المَنشُور."; +"Common.Controls.Status.Visibility.PrivateFromMe" = "فَقَطْ مُتابِعيني أنَا مَن يُمكِنُهُم رُؤيَةُ هَذَا المَنشُور."; +"Common.Controls.Status.Visibility.Unlisted" = "يُمكِنُ لِلجَميعِ رُؤيَةُ هَذَا المَنشورِ وَلكِنَّهُ لَا يُعرَضُ فِي الخَطِّ الزَمنيّ العام."; +"Common.Controls.Tabs.Home" = "الرَّئِيسَة"; "Common.Controls.Tabs.Notification" = "الإشعارات"; "Common.Controls.Tabs.Profile" = "الملف التعريفي"; -"Common.Controls.Tabs.Search" = "بحث"; +"Common.Controls.Tabs.Search" = "البَحث"; "Common.Controls.Timeline.Filtered" = "مُصفَّى"; -"Common.Controls.Timeline.Header.BlockedWarning" = "لا يُمكِنُكَ عَرض الملف الشخصي لهذا المُستخدِم -حتَّى يَرفَعَ الحَظر عَنك."; -"Common.Controls.Timeline.Header.BlockingWarning" = "لا يُمكنك الاطلاع على الملف الشخصي لهذا المُستخدِم +"Common.Controls.Timeline.Header.BlockedWarning" = "لا يُمكِنُكَ عَرض الملف التَعريفي لهذا المُستخدِم +حتَّى يَرفَعَ الحَظرَ عَنك."; +"Common.Controls.Timeline.Header.BlockingWarning" = "لا يُمكِنُكَ الاِطلاع على الملف التَعريفي لهذا المُستخدِم حتَّى تَرفعَ الحَظر عنه. -ملفًّكَ الشخصي يَظهَرُ بِمثل هذِهِ الحالة بالنسبةِ لَهُ أيضًا."; -"Common.Controls.Timeline.Header.NoStatusFound" = "لا توجد هناك منشورات"; +ملفُّكَ التَعريفي يَظهَرُ بِمثل هذِهِ الحالة بالنسبةِ لَهُ أيضًا."; +"Common.Controls.Timeline.Header.NoStatusFound" = "لَم يُعْثَر على مَنشورات"; "Common.Controls.Timeline.Header.SuspendedWarning" = "تمَّ إيقاف هذا المُستخدِم."; -"Common.Controls.Timeline.Header.UserBlockedWarning" = "لا يُمكِنُكَ عَرض ملف %@ الشخصي +"Common.Controls.Timeline.Header.UserBlockedWarning" = "لا يُمكِنُكَ عَرض ملف %@ التَعريفي حتَّى يَرفَعَ الحَظر عَنك."; -"Common.Controls.Timeline.Header.UserBlockingWarning" = "لا يُمكنك الاطلاع على ملف %@ الشخصي +"Common.Controls.Timeline.Header.UserBlockingWarning" = "لا يُمكنك الاطلاع على ملف %@ التَعريفي حتَّى تَرفعَ الحَظر عنه. -ملفًّكَ الشخصي يَظهَرُ بِمثل هذِهِ الحالة بالنسبةِ لَهُ أيضًا."; -"Common.Controls.Timeline.Header.UserSuspendedWarning" = "لقد أوقِفَ حِساب %@."; -"Common.Controls.Timeline.Loader.LoadMissingPosts" = "تحميل المنشورات المَفقودة"; -"Common.Controls.Timeline.Loader.LoadingMissingPosts" = "تحميل المزيد من المنشورات..."; -"Common.Controls.Timeline.Loader.ShowMoreReplies" = "إظهار المزيد من الردود"; -"Common.Controls.Timeline.Timestamp.Now" = "الأن"; -"Scene.AccountList.AddAccount" = "إضافة حساب"; -"Scene.AccountList.DismissAccountSwitcher" = "تجاهُل مبدِّل الحساب"; -"Scene.AccountList.TabBarHint" = "المِلف المُحدَّد حاليًا: %@. انقر نقرًا مزدوجًا ثم اضغط مع الاستمرار لإظهار مُبدِّل الحِساب"; +ملفُّكَ التَعريفي يَظهَرُ بِمثل هذِهِ الحالة بالنسبةِ لَهُ أيضًا."; +"Common.Controls.Timeline.Header.UserSuspendedWarning" = "لقد أُوقِفَ حِساب %@."; +"Common.Controls.Timeline.Loader.LoadMissingPosts" = "تحميل المَنشورات المَفقودَة"; +"Common.Controls.Timeline.Loader.LoadingMissingPosts" = "يَجري تحميل المَنشورات المَفقودَة..."; +"Common.Controls.Timeline.Loader.ShowMoreReplies" = "إظهار مَزيد مِنَ الرُّدود"; +"Common.Controls.Timeline.Timestamp.Now" = "الآن"; +"Scene.AccountList.AddAccount" = "إضافَةُ حِساب"; +"Scene.AccountList.DismissAccountSwitcher" = "تجاهُل مبدِّل الحِساب"; +"Scene.AccountList.TabBarHint" = "المِلف المُحدَّد حاليًا: %@. انقر نقرًا مزدوجًا مع الاستمرار لإظهار مُبدِّل الحِساب"; "Scene.Compose.Accessibility.AppendAttachment" = "إضافة مُرفَق"; "Scene.Compose.Accessibility.AppendPoll" = "اضافة استطلاع رأي"; -"Scene.Compose.Accessibility.CustomEmojiPicker" = "منتقي مخصص للإيموجي"; -"Scene.Compose.Accessibility.DisableContentWarning" = "تعطيل تحذير الحتوى"; -"Scene.Compose.Accessibility.EnableContentWarning" = "تنشيط تحذير المحتوى"; +"Scene.Compose.Accessibility.CustomEmojiPicker" = "منتقي الرموز التعبيرية المُخصَّص"; +"Scene.Compose.Accessibility.DisableContentWarning" = "تعطيل تحذير المُحتَوى"; +"Scene.Compose.Accessibility.EnableContentWarning" = "تفعيل تحذير المُحتَوى"; "Scene.Compose.Accessibility.PostVisibilityMenu" = "قائمة ظهور المنشور"; "Scene.Compose.Accessibility.RemovePoll" = "إزالة الاستطلاع"; -"Scene.Compose.Attachment.AttachmentBroken" = "هذا ال%@ مُعطَّل ويتعذَّر رفعه إلى ماستودون."; -"Scene.Compose.Attachment.DescriptionPhoto" = "صِف الصورة للمكفوفين..."; -"Scene.Compose.Attachment.DescriptionVideo" = "صِف المقطع المرئي للمكفوفين..."; +"Scene.Compose.Attachment.AttachmentBroken" = "هذا ال%@ مُعطَّل +ويتعذَّرُ رفعُه إلى ماستودون."; +"Scene.Compose.Attachment.DescriptionPhoto" = "صِف الصورة للمَكفوفين..."; +"Scene.Compose.Attachment.DescriptionVideo" = "صِف المقطع المرئي للمَكفوفين..."; "Scene.Compose.Attachment.Photo" = "صورة"; -"Scene.Compose.Attachment.Video" = "فيديو"; -"Scene.Compose.AutoComplete.SpaceToAdd" = "انقر مساحة لإضافتِها"; -"Scene.Compose.ComposeAction" = "انشر"; +"Scene.Compose.Attachment.Video" = "مقطع مرئي"; +"Scene.Compose.AutoComplete.SpaceToAdd" = "انقر على مساحة لإضافتِها"; +"Scene.Compose.ComposeAction" = "نَشر"; "Scene.Compose.ContentInputPlaceholder" = "أخبِرنا بِما يَجُولُ فِي ذِهنَك"; "Scene.Compose.ContentWarning.Placeholder" = "اكتب تَحذيرًا دَقيقًا هُنا..."; "Scene.Compose.Keyboard.AppendAttachmentEntry" = "إضافة مُرفَق - %@"; "Scene.Compose.Keyboard.DiscardPost" = "تجاهُل المنشور"; "Scene.Compose.Keyboard.PublishPost" = "نَشر المَنشُور"; "Scene.Compose.Keyboard.SelectVisibilityEntry" = "اختر مدى الظهور - %@"; -"Scene.Compose.Keyboard.ToggleContentWarning" = "تبديل تحذير المُحتوى"; +"Scene.Compose.Keyboard.ToggleContentWarning" = "تبديل تحذير المُحتَوى"; "Scene.Compose.Keyboard.TogglePoll" = "تبديل الاستطلاع"; "Scene.Compose.MediaSelection.Browse" = "تصفح"; -"Scene.Compose.MediaSelection.Camera" = "التقط صورة"; +"Scene.Compose.MediaSelection.Camera" = "إلتقاط صورة"; "Scene.Compose.MediaSelection.PhotoLibrary" = "مكتبة الصور"; -"Scene.Compose.Poll.DurationTime" = "المدة: %@"; -"Scene.Compose.Poll.OneDay" = "يوم واحد"; -"Scene.Compose.Poll.OneHour" = "ساعة واحدة"; +"Scene.Compose.Poll.DurationTime" = "المُدَّة: %@"; +"Scene.Compose.Poll.OneDay" = "يومٌ واحِد"; +"Scene.Compose.Poll.OneHour" = "ساعةٌ واحدة"; "Scene.Compose.Poll.OptionNumber" = "الخيار %ld"; -"Scene.Compose.Poll.SevenDays" = "7 أيام"; -"Scene.Compose.Poll.SixHours" = "6 ساعات"; -"Scene.Compose.Poll.ThirtyMinutes" = "30 دقيقة"; -"Scene.Compose.Poll.ThreeDays" = "3 أيام"; -"Scene.Compose.ReplyingToUser" = "رد على %@"; +"Scene.Compose.Poll.SevenDays" = "سبعةُ أيام"; +"Scene.Compose.Poll.SixHours" = "سِتُّ ساعات"; +"Scene.Compose.Poll.ThirtyMinutes" = "ثلاثون دقيقة"; +"Scene.Compose.Poll.ThreeDays" = "ثلاثةُ أيام"; +"Scene.Compose.ReplyingToUser" = "رَدًا على %@"; "Scene.Compose.Title.NewPost" = "منشور جديد"; -"Scene.Compose.Title.NewReply" = "رد جديد"; -"Scene.Compose.Visibility.Direct" = "ففط للأشخاص المشار إليهم"; -"Scene.Compose.Visibility.Private" = "لمتابعيك فقط"; +"Scene.Compose.Title.NewReply" = "رَدٌّ جديد"; +"Scene.Compose.Visibility.Direct" = "للأشخاص المُشار إليهم فقط"; +"Scene.Compose.Visibility.Private" = "للمُتابِعينَ فقط"; "Scene.Compose.Visibility.Public" = "للعامة"; "Scene.Compose.Visibility.Unlisted" = "غير مُدرَج"; -"Scene.ConfirmEmail.Button.DontReceiveEmail" = "لم أستلم أبدًا بريدا إلكترونيا"; -"Scene.ConfirmEmail.Button.OpenEmailApp" = "افتح تطبيق البريد الإلكتروني"; -"Scene.ConfirmEmail.DontReceiveEmail.Description" = "تحقق ممَّ إذا كان عنوان بريدك الإلكتروني صحيحًا وكذلك تأكد مِن مجلد البريد غير الهام إذا لم تكن قد فعلت ذلك."; +"Scene.ConfirmEmail.Button.OpenEmailApp" = "فتح تطبيق البريد الإلكتروني"; +"Scene.ConfirmEmail.Button.Resend" = "إعادَةُ الإرسال"; +"Scene.ConfirmEmail.DontReceiveEmail.Description" = "تحقق ممَّ إذا كان عنوان بريدك الإلكتروني صحيحًا، وكذلك تأكد مِن مجلد البريد غير الهام إذا لم تكن قد فعلت ذلك."; "Scene.ConfirmEmail.DontReceiveEmail.ResendEmail" = "إعادة إرسال البريد الإلكتروني"; "Scene.ConfirmEmail.DontReceiveEmail.Title" = "تحقق من بريدك الإلكتروني"; "Scene.ConfirmEmail.OpenEmailApp.Description" = "لقد أرسلنا لك بريدًا إلكترونيًا للتو. تحقق من مجلد البريد غير الهام الخاص بك إذا لم تكن قد فعلت ذلك."; "Scene.ConfirmEmail.OpenEmailApp.Mail" = "البريد"; "Scene.ConfirmEmail.OpenEmailApp.OpenEmailClient" = "فتح عميل البريد الإلكتروني"; "Scene.ConfirmEmail.OpenEmailApp.Title" = "تحقَّق من بريدك الوارِد."; -"Scene.ConfirmEmail.Subtitle" = "لقد أرسلنا للتو رسالة بريد إلكتروني إلى %@، -اضغط على الرابط لتأكيد حسابك."; -"Scene.ConfirmEmail.Title" = "شيء واحد أخير."; -"Scene.Favorite.Title" = "مفضلتك"; +"Scene.ConfirmEmail.Subtitle" = "لقد أرسلنا للتو بريد إلكتروني إلى %@، +انقر على الرابط لتأكيد حسابك."; +"Scene.ConfirmEmail.Title" = "شيءٌ أخير."; +"Scene.Favorite.Title" = "مُفضَّلَتُك"; "Scene.Follower.Footer" = "لا يُمكِن عَرض المُتابِعين مِنَ الخوادم الأُخرى."; "Scene.Following.Footer" = "لا يُمكِن عَرض المُتابَعات مِنَ الخوادم الأُخرى."; "Scene.HomeTimeline.NavigationBarState.NewPosts" = "إظهار منشورات جديدة"; -"Scene.HomeTimeline.NavigationBarState.Offline" = "غير متصل"; -"Scene.HomeTimeline.NavigationBarState.Published" = "تم نشره!"; -"Scene.HomeTimeline.NavigationBarState.Publishing" = "جارٍ نشر المشاركة…"; -"Scene.HomeTimeline.Title" = "الخيط الرئيسي"; +"Scene.HomeTimeline.NavigationBarState.Offline" = "غَير مُتَّصِل"; +"Scene.HomeTimeline.NavigationBarState.Published" = "تمَّ النَّشر!"; +"Scene.HomeTimeline.NavigationBarState.Publishing" = "يَجري نَشر المُشارَكَة..."; +"Scene.HomeTimeline.Title" = "الرَّئِيسَة"; "Scene.Notification.Keyobard.ShowEverything" = "إظهار كل شيء"; "Scene.Notification.Keyobard.ShowMentions" = "إظهار الإشارات"; -"Scene.Notification.Title.Everything" = "الكل"; +"Scene.Notification.NotificationDescription.FavoritedYourPost" = "فَضَّلَ مَنشُورَك"; +"Scene.Notification.NotificationDescription.FollowedYou" = "بَدَأ بِمُتابَعَتِك"; +"Scene.Notification.NotificationDescription.MentionedYou" = "أشارَ إليك"; +"Scene.Notification.NotificationDescription.PollHasEnded" = "انتهى استطلاعُ الرأي"; +"Scene.Notification.NotificationDescription.RebloggedYourPost" = "أعادَ تَدوينَ مَنشُورَك"; +"Scene.Notification.NotificationDescription.RequestToFollowYou" = "طَلَبَ مُتابَعتَك"; +"Scene.Notification.Title.Everything" = "كُلُّ شيء"; "Scene.Notification.Title.Mentions" = "الإشارات"; -"Scene.Notification.UserFavorited Your Post" = "أضاف %@ منشورك إلى مفضلته"; -"Scene.Notification.UserFollowedYou" = "يتابعك %@"; -"Scene.Notification.UserMentionedYou" = "أشار إليك %@"; -"Scene.Notification.UserRebloggedYourPost" = "أعاد %@ تدوين مشاركتك"; -"Scene.Notification.UserRequestedToFollowYou" = "طلب %@ متابعتك"; -"Scene.Notification.UserYourPollHasEnded" = "%@ اِنتهى استطلاعُكَ للرأي"; "Scene.Preview.Keyboard.ClosePreview" = "إغلاق المُعايَنَة"; "Scene.Preview.Keyboard.ShowNext" = "إظهار التالي"; "Scene.Preview.Keyboard.ShowPrevious" = "إظهار السابق"; "Scene.Profile.Dashboard.Followers" = "متابِع"; "Scene.Profile.Dashboard.Following" = "مُتابَع"; -"Scene.Profile.Dashboard.Posts" = "منشورات"; +"Scene.Profile.Dashboard.Posts" = "مَنشورات"; "Scene.Profile.Fields.AddRow" = "إضافة صف"; -"Scene.Profile.Fields.Placeholder.Content" = "المحتوى"; +"Scene.Profile.Fields.Placeholder.Content" = "المُحتَوى"; "Scene.Profile.Fields.Placeholder.Label" = "التسمية"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Message" = "أكِّد لرفع حظر %@"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Title" = "إلغاء حظر الحساب"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Message" = "أكِّد لرفع كتمْ %@"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Title" = "إلغاء كتم الحساب"; -"Scene.Profile.SegmentedControl.Media" = "وسائط"; -"Scene.Profile.SegmentedControl.Posts" = "منشورات"; -"Scene.Profile.SegmentedControl.Replies" = "ردود"; -"Scene.Register.Error.Item.Agreement" = "الاتفاقية"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Message" = "تأكيدُ حَظر %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title" = "حَظرُ الحِساب"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Message" = "تأكيدُ كَتم %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Title" = "كَتمُ الحِساب"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Message" = "تأكيدُ رَفع الحَظرِ عَن %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Title" = "رَفعُ الحَظرِ عَنِ الحِساب"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Message" = "أكِّد لرفع الكتمْ عن %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Title" = "رفع الكتم عن الحساب"; +"Scene.Profile.SegmentedControl.About" = "حَول"; +"Scene.Profile.SegmentedControl.Media" = "وَسائِط"; +"Scene.Profile.SegmentedControl.Posts" = "مَنشورات"; +"Scene.Profile.SegmentedControl.PostsAndReplies" = "المَنشوراتُ وَالرُدود"; +"Scene.Profile.SegmentedControl.Replies" = "رُدُود"; +"Scene.Register.Error.Item.Agreement" = "الاِتِّفاقيَّة"; "Scene.Register.Error.Item.Email" = "البريد الإلكتروني"; "Scene.Register.Error.Item.Locale" = "اللغة المحلية"; -"Scene.Register.Error.Item.Password" = "الكلمة السرية"; +"Scene.Register.Error.Item.Password" = "الرمز السري"; "Scene.Register.Error.Item.Reason" = "السبب"; -"Scene.Register.Error.Item.Username" = "اسم المستخدم"; +"Scene.Register.Error.Item.Username" = "اِسم المُستَخدِم"; "Scene.Register.Error.Reason.Accepted" = "يجب أن يُقبل %@"; -"Scene.Register.Error.Reason.Blank" = "%@ مطلوب"; +"Scene.Register.Error.Reason.Blank" = "%@ مَطلوب"; "Scene.Register.Error.Reason.Blocked" = "يحتوي %@ على موفِّر خدمة بريد إلكتروني غير مسموح به"; "Scene.Register.Error.Reason.Inclusion" = "إنَّ %@ قيمة غير مدعومة"; "Scene.Register.Error.Reason.Invalid" = "%@ غير صالح"; "Scene.Register.Error.Reason.Reserved" = "إنَّ %@ عبارة عن كلمة مفتاحيَّة محجوزة"; "Scene.Register.Error.Reason.Taken" = "إنَّ %@ مُستخدَمٌ بالفعل"; "Scene.Register.Error.Reason.TooLong" = "%@ طويل جداً"; -"Scene.Register.Error.Reason.TooShort" = "%@ قصير جدا"; +"Scene.Register.Error.Reason.TooShort" = "%@ قصير جدًا"; "Scene.Register.Error.Reason.Unreachable" = "يبدوا أنَّ %@ غير موجود"; "Scene.Register.Error.Special.EmailInvalid" = "هذا عنوان بريد إلكتروني غير صالح"; -"Scene.Register.Error.Special.PasswordTooShort" = "كلمة المرور قصيرة جداً (يجب أن تكون 8 أحرف على الأقل)"; +"Scene.Register.Error.Special.PasswordTooShort" = "رمز السر قصير جدًا (يجب أن يتكون من ثمان خانات على الأقل)"; "Scene.Register.Error.Special.UsernameInvalid" = "يُمكِن أن يحتوي اسم المستخدم على أحرف أبجدية، أرقام وشرطات سفلية فقط"; -"Scene.Register.Error.Special.UsernameTooLong" = "اسم المستخدم طويل جداً (يجب ألّا يكون أطول من 30 رمز)"; -"Scene.Register.Input.Avatar.Delete" = "احذف"; -"Scene.Register.Input.DisplayName.Placeholder" = "الاسم المعروض"; -"Scene.Register.Input.Email.Placeholder" = "البريد الإلكتروني"; +"Scene.Register.Error.Special.UsernameTooLong" = "اِسم المُستَخدِم طويل جداً (يَجِبُ ألّا يكون أطول من ثلاثين خانة)"; +"Scene.Register.Input.Avatar.Delete" = "حذف"; +"Scene.Register.Input.DisplayName.Placeholder" = "اِسم العَرض"; +"Scene.Register.Input.Email.Placeholder" = "بريد إلكتروني"; "Scene.Register.Input.Invite.RegistrationUserInviteRequest" = "لماذا ترغب في الانضمام؟"; -"Scene.Register.Input.Password.Hint" = "يجب أن تكون كلمتك السرية متكونة من ثمانية أحرف على الأقل"; -"Scene.Register.Input.Password.Placeholder" = "الكلمة السرية"; -"Scene.Register.Input.Username.DuplicatePrompt" = "اسم المستخدم هذا غير متوفر."; -"Scene.Register.Input.Username.Placeholder" = "اسم المستخدم"; -"Scene.Register.Title" = "أخبرنا عنك."; -"Scene.Report.Content1" = "هل ترغب في إضافة أي مشاركات أُخرى إلى الشكوى؟"; -"Scene.Report.Content2" = "هل هناك أي شيء يجب أن يعرفه المُراقبين حول هذه الشكوى؟"; -"Scene.Report.Send" = "إرسال الشكوى"; +"Scene.Register.Input.Password.Accessibility.Checked" = "مُتَحَققٌ مِنه"; +"Scene.Register.Input.Password.Accessibility.Unchecked" = "غيرُ مُتَحَققٍ مِنه"; +"Scene.Register.Input.Password.CharacterLimit" = "ثمانيةُ خانات"; +"Scene.Register.Input.Password.Hint" = "يجب أن يكون رمزك السري مكوَّن من ثمان خانات على الأقل"; +"Scene.Register.Input.Password.Placeholder" = "رمز سري"; +"Scene.Register.Input.Password.Require" = "رمز المرور الخاص بك يجب أن يحتوي على الأقل:"; +"Scene.Register.Input.Username.DuplicatePrompt" = "اِسم المُستَخدِم هذا مأخوذٌ بالفعل."; +"Scene.Register.Input.Username.Placeholder" = "اِسم مُستَخدِم"; +"Scene.Register.Title" = "أخبرنا عن نفسك."; +"Scene.Report.Content1" = "هل ترغب في إضافة أي منشورات أُخرى إلى البلاغ؟"; +"Scene.Report.Content2" = "هل هناك أي شيء يجب أن يعرفه المُراقبين حول هذا البلاغ؟"; +"Scene.Report.ReportSentTitle" = "شُكرًا لَكَ على الإبلاغ، سَوفَ نَنظُرُ فِي هَذَا الأمر."; +"Scene.Report.Reported" = "مُبْلَغٌ عَنه"; +"Scene.Report.Send" = "إرسال البلاغ"; "Scene.Report.SkipToSend" = "إرسال بدون تعليق"; -"Scene.Report.Step1" = "الخطوة 1 من 2"; -"Scene.Report.Step2" = "الخطوة 2 من 2"; +"Scene.Report.Step1" = "الخطوة الأولى مِن أصل اثنتين"; +"Scene.Report.Step2" = "الخطوة الثانية والأخيرة"; "Scene.Report.TextPlaceholder" = "اكتب أو الصق تعليقات إضافيَّة"; -"Scene.Report.Title" = "ابلغ عن %@"; -"Scene.Search.Recommend.Accounts.Description" = "قد ترغب في متابعة هذه الحسابات"; -"Scene.Search.Recommend.Accounts.Follow" = "تابع"; -"Scene.Search.Recommend.Accounts.Title" = "حسابات قد تعجبك"; -"Scene.Search.Recommend.ButtonText" = "طالع الكل"; -"Scene.Search.Recommend.HashTag.Description" = "الوسوم التي تحظى بقدر كبير من الاهتمام"; +"Scene.Report.Title" = "الإبلاغ عن %@"; +"Scene.Report.TitleReport" = "إبلاغ"; +"Scene.Search.Recommend.Accounts.Description" = "قَد تَرغَب في مُتابَعَةِ هَذِهِ الحِسابات"; +"Scene.Search.Recommend.Accounts.Follow" = "مُتابَعَة"; +"Scene.Search.Recommend.Accounts.Title" = "حِساباتٍ قَد تُعجِبُك"; +"Scene.Search.Recommend.ButtonText" = "إظهار الكُل"; +"Scene.Search.Recommend.HashTag.Description" = "الوُسُومُ الَّتي تَحظى بقدرٍ كبيرٍ مِنَ الاِهتمام"; "Scene.Search.Recommend.HashTag.PeopleTalking" = "%@ أشخاص يتحدَّثوا"; -"Scene.Search.Recommend.HashTag.Title" = "ذات شعبية على ماستدون"; +"Scene.Search.Recommend.HashTag.Title" = "ذُو شعبيَّة على ماستودون"; "Scene.Search.SearchBar.Cancel" = "إلغاء"; -"Scene.Search.SearchBar.Placeholder" = "البحث عن وسوم أو مستخدمين·ات"; +"Scene.Search.SearchBar.Placeholder" = "البحث عن وسوم أو مستخدمين"; "Scene.Search.Searching.Clear" = "مَحو"; -"Scene.Search.Searching.EmptyState.NoResults" = "ليس هناك أية نتيجة"; -"Scene.Search.Searching.RecentSearch" = "عمليات البحث الأخيرة"; -"Scene.Search.Searching.Segment.All" = "الكل"; -"Scene.Search.Searching.Segment.Hashtags" = "الوسوم"; +"Scene.Search.Searching.EmptyState.NoResults" = "لا تُوجَدُ نتائِج"; +"Scene.Search.Searching.RecentSearch" = "عَمَليَّاُت البَحثِ الأخيرَة"; +"Scene.Search.Searching.Segment.All" = "الكُل"; +"Scene.Search.Searching.Segment.Hashtags" = "الوُسُوم"; "Scene.Search.Searching.Segment.People" = "الأشخاص"; -"Scene.Search.Searching.Segment.Posts" = "المنشورات"; -"Scene.Search.Title" = "بحث"; +"Scene.Search.Searching.Segment.Posts" = "المَنشورات"; +"Scene.Search.Title" = "البحث"; "Scene.ServerPicker.Button.Category.Academia" = "أكاديمي"; -"Scene.ServerPicker.Button.Category.Activism" = "للنشطاء"; +"Scene.ServerPicker.Button.Category.Activism" = "النشطاء"; "Scene.ServerPicker.Button.Category.All" = "الكل"; "Scene.ServerPicker.Button.Category.AllAccessiblityDescription" = "الفئة: الكل"; -"Scene.ServerPicker.Button.Category.Art" = "فن"; +"Scene.ServerPicker.Button.Category.Art" = "فنون"; "Scene.ServerPicker.Button.Category.Food" = "الطعام"; -"Scene.ServerPicker.Button.Category.Furry" = "فروي"; +"Scene.ServerPicker.Button.Category.Furry" = "مكسو بالفرو"; "Scene.ServerPicker.Button.Category.Games" = "ألعاب"; "Scene.ServerPicker.Button.Category.General" = "عام"; "Scene.ServerPicker.Button.Category.Journalism" = "صحافة"; "Scene.ServerPicker.Button.Category.Lgbt" = "مجتمع الشواذ"; "Scene.ServerPicker.Button.Category.Music" = "موسيقى"; -"Scene.ServerPicker.Button.Category.Regional" = "اقليمي"; -"Scene.ServerPicker.Button.Category.Tech" = "تكنولوجيا"; -"Scene.ServerPicker.Button.SeeLess" = "اعرض أقل"; -"Scene.ServerPicker.Button.SeeMore" = "اعرض المزيد"; +"Scene.ServerPicker.Button.Category.Regional" = "إقليمي"; +"Scene.ServerPicker.Button.Category.Tech" = "تقنية"; +"Scene.ServerPicker.Button.SeeLess" = "عرض عناصر أقل"; +"Scene.ServerPicker.Button.SeeMore" = "عرض عناصر أكثر"; "Scene.ServerPicker.EmptyState.BadNetwork" = "حدث خطأٌ ما أثناء تحميل البيانات. تحقَّق من اتصالك بالإنترنت."; -"Scene.ServerPicker.EmptyState.FindingServers" = "البحث عن خوادم متوفرة..."; +"Scene.ServerPicker.EmptyState.FindingServers" = "يجري إيجاد خوادم متوفِّرَة..."; "Scene.ServerPicker.EmptyState.NoResults" = "لا توجد نتائج"; -"Scene.ServerPicker.Input.Placeholder" = "ابحث عن خادم أو انضم إلى سيرفر خاص بك..."; +"Scene.ServerPicker.Input.Placeholder" = "اِبحَث عن خادِم أو انضم إلى آخر خاص بك..."; "Scene.ServerPicker.Label.Category" = "الفئة"; -"Scene.ServerPicker.Label.Language" = "اللغة"; -"Scene.ServerPicker.Label.Users" = "مستخدمون·ات"; +"Scene.ServerPicker.Label.Language" = "اللُّغة"; +"Scene.ServerPicker.Label.Users" = "مُستَخدِم"; +"Scene.ServerPicker.Subtitle" = "اختر مجتمعًا بناءً على اهتماماتك، منطقتك أو يمكنك حتى اختيارُ مجتمعٍ ذي غرضٍ عام."; +"Scene.ServerPicker.SubtitleExtend" = "اختر مجتمعًا بناءً على اهتماماتك، منطقتك أو يمكنك حتى اختيارُ مجتمعٍ ذي غرضٍ عام. تُشغَّل جميعُ المجتمعِ مِن قِبَلِ مُنظمَةٍ أو فردٍ مُستقلٍ تمامًا."; "Scene.ServerPicker.Title" = "اِختر خادِم، -أي خادِم."; -"Scene.ServerRules.Button.Confirm" = "انا أوافق"; -"Scene.ServerRules.PrivacyPolicy" = "سياسة الخصوصية"; -"Scene.ServerRules.Prompt" = "إن اخترت المواصلة، فإنك تخضع لشروط الخدمة وسياسة الخصوصية لـ %@."; -"Scene.ServerRules.Subtitle" = "تم سنّ هذه القواعد من قبل مشرفي %@."; -"Scene.ServerRules.TermsOfService" = "شروط الخدمة"; +أيًّا مِنهُم."; +"Scene.ServerRules.Button.Confirm" = "أنا مُوافِق"; +"Scene.ServerRules.PrivacyPolicy" = "سِياسَة الخُصُوصيَّة"; +"Scene.ServerRules.Prompt" = "في حال إختيارك للمواصلة، أنت تخضع لشروط الخدمة وسياسة الخصوصية لِـ%@."; +"Scene.ServerRules.Subtitle" = "سُنَّت هذه القواعد من قِبل مشرفي %@."; +"Scene.ServerRules.TermsOfService" = "شُرُوط الخِدمَة"; "Scene.ServerRules.Title" = "بعض القواعد الأساسية."; -"Scene.Settings.Footer.MastodonDescription" = "ماستدون برنامج مفتوح المصدر. يمكنك المساهمة، أو الإبلاغ عن تقارير الأخطاء على GitHub في %@ (%@)"; +"Scene.Settings.Footer.MastodonDescription" = "ماستودون بَرنامجٌ مَفتُوحُ المَصدَر. يُمكِنُكَ المُساهَمَةُ، أوِ الإبلاغُ عَنِ المُشكِلات عَن طريق مِنصَّة جيت هاب (GitHub) في %@ (%@)"; "Scene.Settings.Keyboard.CloseSettingsWindow" = "إغلاق نافذة الإعدادات"; "Scene.Settings.Section.Appearance.Automatic" = "تلقائي"; "Scene.Settings.Section.Appearance.Dark" = "مظلمٌ دائِمًا"; "Scene.Settings.Section.Appearance.Light" = "مضيءٌ دائمًا"; -"Scene.Settings.Section.Appearance.Title" = "المظهر"; -"Scene.Settings.Section.BoringZone.AccountSettings" = "إعدادات الحساب"; -"Scene.Settings.Section.BoringZone.Privacy" = "سياسة الخصوصية"; -"Scene.Settings.Section.BoringZone.Terms" = "شروط الخدمة"; -"Scene.Settings.Section.BoringZone.Title" = "المنطقة المملة"; -"Scene.Settings.Section.Notifications.Boosts" = "إعادة تدوين منشوراتي"; -"Scene.Settings.Section.Notifications.Favorites" = "الإعجاب بِمنشوراتي"; -"Scene.Settings.Section.Notifications.Follows" = "يتابعني"; -"Scene.Settings.Section.Notifications.Mentions" = "الإشارة لي"; +"Scene.Settings.Section.Appearance.Title" = "المَظهر"; +"Scene.Settings.Section.BoringZone.AccountSettings" = "إعداداتُ الحِساب"; +"Scene.Settings.Section.BoringZone.Privacy" = "سِياسَةُ الخُصوصيَّة"; +"Scene.Settings.Section.BoringZone.Terms" = "شُرُوطُ الخِدمَة"; +"Scene.Settings.Section.BoringZone.Title" = "المنطِقَةُ المُملَّة"; +"Scene.Settings.Section.LookAndFeel.Light" = "مُضيء"; +"Scene.Settings.Section.LookAndFeel.ReallyDark" = "مُظلمٌ حَقًّا"; +"Scene.Settings.Section.LookAndFeel.SortaDark" = "مُظلمٌ نوعًا ما"; +"Scene.Settings.Section.LookAndFeel.Title" = "المَظهَرُ وَالشُّعُور"; +"Scene.Settings.Section.LookAndFeel.UseSystem" = "استخدم النِظام"; +"Scene.Settings.Section.Notifications.Boosts" = "بِإعادَةِ تدوينِ مَنشوري"; +"Scene.Settings.Section.Notifications.Favorites" = "بِالإعْجاب بِمَنشوري"; +"Scene.Settings.Section.Notifications.Follows" = "بِمُتابَعَتي"; +"Scene.Settings.Section.Notifications.Mentions" = "بِالإشارَةِ إليّ"; "Scene.Settings.Section.Notifications.Title" = "الإشعارات"; -"Scene.Settings.Section.Notifications.Trigger.Anyone" = "أي شخص"; +"Scene.Settings.Section.Notifications.Trigger.Anyone" = "أيُّ شخصٍ"; "Scene.Settings.Section.Notifications.Trigger.Follow" = "أي شخص أُتابِعُه"; -"Scene.Settings.Section.Notifications.Trigger.Follower" = "مشترِك"; -"Scene.Settings.Section.Notifications.Trigger.Noone" = "لا أحد"; -"Scene.Settings.Section.Notifications.Trigger.Title" = "إشعاري عِندَ"; -"Scene.Settings.Section.Preference.DisableAvatarAnimation" = "تعطيل الصور الرمزية المتحرِّكة"; -"Scene.Settings.Section.Preference.DisableEmojiAnimation" = "تعطيل الرموز التعبيرية المتحرِّكَة"; -"Scene.Settings.Section.Preference.Title" = "التفضيلات"; -"Scene.Settings.Section.Preference.TrueBlackDarkMode" = "النمط الأسود الداكِن الحقيقي"; -"Scene.Settings.Section.Preference.UsingDefaultBrowser" = "اِستخدام المتصفح الافتراضي لفتح الروابط"; -"Scene.Settings.Section.SpicyZone.Clear" = "مسح ذاكرة التخزين المؤقت للوسائط"; -"Scene.Settings.Section.SpicyZone.Signout" = "تسجيل الخروج"; -"Scene.Settings.Section.SpicyZone.Title" = "المنطقة الحارة"; +"Scene.Settings.Section.Notifications.Trigger.Follower" = "مُتابِعٌ"; +"Scene.Settings.Section.Notifications.Trigger.Noone" = "لَا أحد"; +"Scene.Settings.Section.Notifications.Trigger.Title" = "أشعِرني عِندما يَقومُ"; +"Scene.Settings.Section.Preference.DisableAvatarAnimation" = "تَعطيلُ الصوَرِ الرمزيَّةِ المُتحرِّكَة"; +"Scene.Settings.Section.Preference.DisableEmojiAnimation" = "تَعطيلُ الرُموزِ التَّعبيريَّةِ المُتحرِّكَة"; +"Scene.Settings.Section.Preference.Title" = "التَّفضيلات"; +"Scene.Settings.Section.Preference.TrueBlackDarkMode" = "النَّمَطُ الأسوَدُ الداكِنُ الحَقيقي"; +"Scene.Settings.Section.Preference.UsingDefaultBrowser" = "اِستِخدامُ المُتصفِّحِ الاِفتراضي لِفتحِ الرَّوابِط"; +"Scene.Settings.Section.SpicyZone.Clear" = "مَحوُ ذاكِرَةُ التَّخزينِ المُؤقت لِلوسائِط"; +"Scene.Settings.Section.SpicyZone.Signout" = "تَسجيلُ الخُروج"; +"Scene.Settings.Section.SpicyZone.Title" = "المنطِقَةُ اللَّاذِعَة"; "Scene.Settings.Title" = "الإعدادات"; "Scene.SuggestionAccount.FollowExplain" = "عِندَ مُتابَعَتِكَ لأحدِهِم، سَوف تَرى مَنشوراته في تغذيَتِكَ الرئيسة."; "Scene.SuggestionAccount.Title" = "ابحث عن أشخاص لمتابعتهم"; "Scene.Thread.BackTitle" = "منشور"; "Scene.Thread.Title" = "مَنشور مِن %@"; +"Scene.Welcome.GetStarted" = "ابدأ الآن"; +"Scene.Welcome.LogIn" = "تسجيلُ الدخول"; "Scene.Welcome.Slogan" = "شبكات التواصل الاجتماعي مرة أُخرى بين يديك."; -"Scene.Wizard.AccessibilityHint" = "انقر نقرًا مزدوجًا لتجاهل النافذة المنبثقة"; +"Scene.Wizard.AccessibilityHint" = "انقر نقرًا مزدوجًا لتجاهُل النافذة المنبثقة"; "Scene.Wizard.MultipleAccountSwitchIntroDescription" = "بدِّل بين حسابات متعددة عبر الاستمرار بالضغط على زر الملف الشخصي."; "Scene.Wizard.NewInMastodon" = "جديد في ماستودون"; \ No newline at end of file diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/ca.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/ca.lproj/Localizable.strings index 1642fc8a..8213aa3d 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/ca.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/ca.lproj/Localizable.strings @@ -4,7 +4,7 @@ "Common.Alerts.CleanCache.Title" = "Neteja la memòria cau"; "Common.Alerts.Common.PleaseTryAgain" = "Si us plau intenta-ho de nou."; "Common.Alerts.Common.PleaseTryAgainLater" = "Si us plau, prova-ho més tard."; -"Common.Alerts.DeletePost.Delete" = "Esborra"; +"Common.Alerts.DeletePost.Message" = "Estàs segur que vols suprimir aquesta publicació?"; "Common.Alerts.DeletePost.Title" = "Estàs segur que vols suprimir aquesta publicació?"; "Common.Alerts.DiscardPostContent.Message" = "Confirma per a descartar el contingut de la publicació composta."; "Common.Alerts.DiscardPostContent.Title" = "Descarta l'esborrany"; @@ -41,6 +41,7 @@ Comprova la teva connexió a Internet."; "Common.Controls.Actions.Next" = "Següent"; "Common.Controls.Actions.Ok" = "D'acord"; "Common.Controls.Actions.Open" = "Obre"; +"Common.Controls.Actions.OpenInBrowser" = "Obre al navegador"; "Common.Controls.Actions.OpenInSafari" = "Obrir a Safari"; "Common.Controls.Actions.Preview" = "Vista prèvia"; "Common.Controls.Actions.Previous" = "Anterior"; @@ -93,6 +94,7 @@ Comprova la teva connexió a Internet."; "Common.Controls.Keyboard.Timeline.ToggleFavorite" = "Commuta el Favorit de la publicació"; "Common.Controls.Keyboard.Timeline.ToggleReblog" = "Commuta l'impuls de la publicació"; "Common.Controls.Status.Actions.Favorite" = "Favorit"; +"Common.Controls.Status.Actions.Hide" = "Amaga"; "Common.Controls.Status.Actions.Menu" = "Menú"; "Common.Controls.Status.Actions.Reblog" = "Impuls"; "Common.Controls.Status.Actions.Reply" = "Respon"; @@ -112,6 +114,10 @@ Comprova la teva connexió a Internet."; "Common.Controls.Status.Tag.Url" = "URL"; "Common.Controls.Status.UserReblogged" = "%@ ha impulsat"; "Common.Controls.Status.UserRepliedTo" = "Ha respòs a %@"; +"Common.Controls.Status.Visibility.Direct" = "Només l'usuari mencionat pot veure aquesta publicació."; +"Common.Controls.Status.Visibility.Private" = "Només els seus seguidors poden veure aquesta publicació."; +"Common.Controls.Status.Visibility.PrivateFromMe" = "Només els meus seguidors poden veure aquesta publicació."; +"Common.Controls.Status.Visibility.Unlisted" = "Tothom pot veure aquesta publicació però no es mostra en la línia de temps pública."; "Common.Controls.Tabs.Home" = "Inici"; "Common.Controls.Tabs.Notification" = "Notificació"; "Common.Controls.Tabs.Profile" = "Perfil"; @@ -178,8 +184,8 @@ carregat a Mastodon."; "Scene.Compose.Visibility.Private" = "Només seguidors"; "Scene.Compose.Visibility.Public" = "Públic"; "Scene.Compose.Visibility.Unlisted" = "No llistat"; -"Scene.ConfirmEmail.Button.DontReceiveEmail" = "No he rebut cap correu electrònic"; "Scene.ConfirmEmail.Button.OpenEmailApp" = "Obre l'aplicació de correu"; +"Scene.ConfirmEmail.Button.Resend" = "Reenvia"; "Scene.ConfirmEmail.DontReceiveEmail.Description" = "Comprova que la teva adreça de correu electrònic és correcte i revisa la carpeta de correu brossa si encara no ho has fet."; "Scene.ConfirmEmail.DontReceiveEmail.ResendEmail" = "Torna a enviar el correu"; "Scene.ConfirmEmail.DontReceiveEmail.Title" = "Comprova el teu correu"; @@ -200,14 +206,14 @@ toca l'enllaç per a confirmar el teu compte."; "Scene.HomeTimeline.Title" = "Inici"; "Scene.Notification.Keyobard.ShowEverything" = "Mostrar-ho tot"; "Scene.Notification.Keyobard.ShowMentions" = "Mostrar Mencions"; +"Scene.Notification.NotificationDescription.FavoritedYourPost" = "ha afavorit la teva publicació"; +"Scene.Notification.NotificationDescription.FollowedYou" = "et segueix"; +"Scene.Notification.NotificationDescription.MentionedYou" = "t'ha mencionat"; +"Scene.Notification.NotificationDescription.PollHasEnded" = "la enquesta ha finalitzat"; +"Scene.Notification.NotificationDescription.RebloggedYourPost" = "ha impulsat la teva publicació"; +"Scene.Notification.NotificationDescription.RequestToFollowYou" = "ha sol·licitat seguir-te"; "Scene.Notification.Title.Everything" = "Tot"; "Scene.Notification.Title.Mentions" = "Mencions"; -"Scene.Notification.UserFavorited Your Post" = "%@ ha afavorit el teu estat"; -"Scene.Notification.UserFollowedYou" = "%@ et segueix"; -"Scene.Notification.UserMentionedYou" = "%@ t'ha esmentat"; -"Scene.Notification.UserRebloggedYourPost" = "%@ ha impulsat el teu estat"; -"Scene.Notification.UserRequestedToFollowYou" = "%@ ha sol·licitat seguir-te"; -"Scene.Notification.UserYourPollHasEnded" = "%@ L'enquesta ha finalitzat"; "Scene.Preview.Keyboard.ClosePreview" = "Tanca la Vista Prèvia"; "Scene.Preview.Keyboard.ShowNext" = "Mostrar Següent"; "Scene.Preview.Keyboard.ShowPrevious" = "Mostrar Anterior"; @@ -217,12 +223,18 @@ toca l'enllaç per a confirmar el teu compte."; "Scene.Profile.Fields.AddRow" = "Afegeix fila"; "Scene.Profile.Fields.Placeholder.Content" = "Contingut"; "Scene.Profile.Fields.Placeholder.Label" = "Etiqueta"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Message" = "Confirma desbloquejar a %@"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Title" = "Desbloquejar Compte"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Message" = "Confirma per a bloquejar %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title" = "Bloqueja el Compte"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Message" = "Confirma per a silenciar %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Title" = "Silencia el Compte"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Message" = "Confirma per a desbloquejar %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Title" = "Desbloqueja el Compte"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Message" = "Confirma deixar de silenciar a %@"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Title" = "Desfer silenciar compte"; +"Scene.Profile.SegmentedControl.About" = "Quant a"; "Scene.Profile.SegmentedControl.Media" = "Mèdia"; "Scene.Profile.SegmentedControl.Posts" = "Publicacions"; +"Scene.Profile.SegmentedControl.PostsAndReplies" = "Publicacions i Respostes"; "Scene.Profile.SegmentedControl.Replies" = "Respostes"; "Scene.Register.Error.Item.Agreement" = "Acord"; "Scene.Register.Error.Item.Email" = "Correu electrònic"; @@ -248,19 +260,26 @@ toca l'enllaç per a confirmar el teu compte."; "Scene.Register.Input.DisplayName.Placeholder" = "nom visible"; "Scene.Register.Input.Email.Placeholder" = "correu electrònic"; "Scene.Register.Input.Invite.RegistrationUserInviteRequest" = "Perquè vols unir-te?"; +"Scene.Register.Input.Password.Accessibility.Checked" = "verificat"; +"Scene.Register.Input.Password.Accessibility.Unchecked" = "no verificat"; +"Scene.Register.Input.Password.CharacterLimit" = "8 caràcters"; "Scene.Register.Input.Password.Hint" = "La teva contrasenya ha de tenir com a mínim buit caràcters"; "Scene.Register.Input.Password.Placeholder" = "contrasenya"; +"Scene.Register.Input.Password.Require" = "La teva contrasenya com a mínim necessita:"; "Scene.Register.Input.Username.DuplicatePrompt" = "Aquest nom d'usuari ja està en ús."; "Scene.Register.Input.Username.Placeholder" = "nom d'usuari"; "Scene.Register.Title" = "Parla'ns de tu."; "Scene.Report.Content1" = "Hi ha alguna altre publicació que vulguis afegir a l'informe?"; "Scene.Report.Content2" = "Hi ha alguna cosa que els moderadors hagin de saber sobre aquest informe?"; +"Scene.Report.ReportSentTitle" = "Gràcies per informar, ho investigarem."; +"Scene.Report.Reported" = "REPORTAT"; "Scene.Report.Send" = "Envia Informe"; "Scene.Report.SkipToSend" = "Envia sense comentaris"; "Scene.Report.Step1" = "Pas 1 de 2"; "Scene.Report.Step2" = "Pas 2 de 2"; "Scene.Report.TextPlaceholder" = "Escriu o enganxa comentaris addicionals"; "Scene.Report.Title" = "Informa sobre %@"; +"Scene.Report.TitleReport" = "Informe"; "Scene.Search.Recommend.Accounts.Description" = "Potser t'agradaria seguir aquests comptes"; "Scene.Search.Recommend.Accounts.Follow" = "Segueix"; "Scene.Search.Recommend.Accounts.Title" = "Comptes que et podrien agradar"; @@ -301,6 +320,8 @@ toca l'enllaç per a confirmar el teu compte."; "Scene.ServerPicker.Label.Category" = "CATEGORIA"; "Scene.ServerPicker.Label.Language" = "LLENGUATGE"; "Scene.ServerPicker.Label.Users" = "USUARIS"; +"Scene.ServerPicker.Subtitle" = "Tria una comunitat segons els teus interessos, regió o una de propòsit general."; +"Scene.ServerPicker.SubtitleExtend" = "Tria una comunitat segons els teus interessos, regió o una de propòsit general. Cada comunitat és operada per una organització totalment independent o individualment."; "Scene.ServerPicker.Title" = "Tria un servidor, qualsevol servidor."; "Scene.ServerRules.Button.Confirm" = "Hi estic d'acord"; @@ -319,6 +340,11 @@ qualsevol servidor."; "Scene.Settings.Section.BoringZone.Privacy" = "Política de Privacitat"; "Scene.Settings.Section.BoringZone.Terms" = "Termes de Servei"; "Scene.Settings.Section.BoringZone.Title" = "La Zona Avorrida"; +"Scene.Settings.Section.LookAndFeel.Light" = "Clar"; +"Scene.Settings.Section.LookAndFeel.ReallyDark" = "Realment Negre"; +"Scene.Settings.Section.LookAndFeel.SortaDark" = "Una Mena de Fosc"; +"Scene.Settings.Section.LookAndFeel.Title" = "Aspecte i Comportament"; +"Scene.Settings.Section.LookAndFeel.UseSystem" = "Usa el del Sistema"; "Scene.Settings.Section.Notifications.Boosts" = "Ha impulsat el meu estat"; "Scene.Settings.Section.Notifications.Favorites" = "Ha afavorit el meu estat"; "Scene.Settings.Section.Notifications.Follows" = "Em segueix"; @@ -342,6 +368,8 @@ qualsevol servidor."; "Scene.SuggestionAccount.Title" = "Cerca Persones per Seguir"; "Scene.Thread.BackTitle" = "Publicació"; "Scene.Thread.Title" = "Publicació de %@"; +"Scene.Welcome.GetStarted" = "Comença"; +"Scene.Welcome.LogIn" = "Inicia sessió"; "Scene.Welcome.Slogan" = "Xarxa social de nou a les teves mans."; "Scene.Wizard.AccessibilityHint" = "Toca dues vegades per descartar l'assistent"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/de.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/de.lproj/Localizable.strings index 12fba538..8808e8d9 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/de.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/de.lproj/Localizable.strings @@ -4,7 +4,7 @@ "Common.Alerts.CleanCache.Title" = "Zwischenspeicher leeren"; "Common.Alerts.Common.PleaseTryAgain" = "Bitte versuche es erneut."; "Common.Alerts.Common.PleaseTryAgainLater" = "Bitte versuche es später nochmal."; -"Common.Alerts.DeletePost.Delete" = "Löschen"; +"Common.Alerts.DeletePost.Message" = "Bist du dir sicher, dass du diesen Beitrag löschen willst?"; "Common.Alerts.DeletePost.Title" = "Bist du dir sicher, dass du diesen Beitrag löschen möchtest?"; "Common.Alerts.DiscardPostContent.Message" = "Bestätige, um den Beitrag zu verwerfen."; "Common.Alerts.DiscardPostContent.Title" = "Entwurf verwerfen"; @@ -28,7 +28,7 @@ Bitte überprüfe deine Internetverbindung."; "Common.Controls.Actions.Back" = "Zurück"; "Common.Controls.Actions.BlockDomain" = "%@ blockieren"; "Common.Controls.Actions.Cancel" = "Abbrechen"; -"Common.Controls.Actions.Compose" = "Compose"; +"Common.Controls.Actions.Compose" = "Neue Nachricht"; "Common.Controls.Actions.Confirm" = "Bestätigen"; "Common.Controls.Actions.Continue" = "Fortfahren"; "Common.Controls.Actions.CopyPhoto" = "Foto kopieren"; @@ -41,6 +41,7 @@ Bitte überprüfe deine Internetverbindung."; "Common.Controls.Actions.Next" = "Weiter"; "Common.Controls.Actions.Ok" = "OK"; "Common.Controls.Actions.Open" = "Öffnen"; +"Common.Controls.Actions.OpenInBrowser" = "Im Browser anzeigen"; "Common.Controls.Actions.OpenInSafari" = "In Safari öffnen"; "Common.Controls.Actions.Preview" = "Vorschau"; "Common.Controls.Actions.Previous" = "Vorheriges"; @@ -93,6 +94,7 @@ Bitte überprüfe deine Internetverbindung."; "Common.Controls.Keyboard.Timeline.ToggleFavorite" = "Favorit vom Beitrag umschalten"; "Common.Controls.Keyboard.Timeline.ToggleReblog" = "Teilen vom Beitrag umschalten"; "Common.Controls.Status.Actions.Favorite" = "Favorit"; +"Common.Controls.Status.Actions.Hide" = "Verstecken"; "Common.Controls.Status.Actions.Menu" = "Menü"; "Common.Controls.Status.Actions.Reblog" = "Teilen"; "Common.Controls.Status.Actions.Reply" = "Antworten"; @@ -112,6 +114,10 @@ Bitte überprüfe deine Internetverbindung."; "Common.Controls.Status.Tag.Url" = "URL"; "Common.Controls.Status.UserReblogged" = "%@ teilte"; "Common.Controls.Status.UserRepliedTo" = "Antwortet auf %@"; +"Common.Controls.Status.Visibility.Direct" = "Nur erwähnte Benutzer können diesen Beitrag sehen."; +"Common.Controls.Status.Visibility.Private" = "Nur Follower des Authors können diesen Beitrag sehen."; +"Common.Controls.Status.Visibility.PrivateFromMe" = "Nur meine Follower können diesen Beitrag sehen."; +"Common.Controls.Status.Visibility.Unlisted" = "Jeder kann diesen Post sehen, aber nicht in der öffentlichen Timeline zeigen."; "Common.Controls.Tabs.Home" = "Startseite"; "Common.Controls.Tabs.Notification" = "Benachrichtigungen"; "Common.Controls.Tabs.Profile" = "Profil"; @@ -135,7 +141,7 @@ Dein Profil sieht für diesen Benutzer auch so aus."; "Common.Controls.Timeline.Loader.ShowMoreReplies" = "Weitere Antworten anzeigen"; "Common.Controls.Timeline.Timestamp.Now" = "Gerade"; "Scene.AccountList.AddAccount" = "Konto hinzufügen"; -"Scene.AccountList.DismissAccountSwitcher" = "Dismiss Account Switcher"; +"Scene.AccountList.DismissAccountSwitcher" = "Dialog zum Wechseln des Kontos schließen"; "Scene.AccountList.TabBarHint" = "Aktuell ausgewähltes Profil: %@. Doppeltippen dann gedrückt halten, um den Kontoschalter anzuzeigen"; "Scene.Compose.Accessibility.AppendAttachment" = "Anhang hinzufügen"; "Scene.Compose.Accessibility.AppendPoll" = "Umfrage hinzufügen"; @@ -178,8 +184,8 @@ kann nicht auf Mastodon hochgeladen werden."; "Scene.Compose.Visibility.Private" = "Nur für Folgende"; "Scene.Compose.Visibility.Public" = "Öffentlich"; "Scene.Compose.Visibility.Unlisted" = "Nicht gelistet"; -"Scene.ConfirmEmail.Button.DontReceiveEmail" = "Ich habe keine E-Mail erhalten."; "Scene.ConfirmEmail.Button.OpenEmailApp" = "E-Mail-App öffnen"; +"Scene.ConfirmEmail.Button.Resend" = "Erneut senden"; "Scene.ConfirmEmail.DontReceiveEmail.Description" = "Überprüfe, ob deine E-Mail-Adresse korrekt ist und sieh im Spam-Ordner nach, falls du es noch nicht getan hast."; "Scene.ConfirmEmail.DontReceiveEmail.ResendEmail" = "E-Mail erneut versenden"; "Scene.ConfirmEmail.DontReceiveEmail.Title" = "Bitte überprüfe deine E-Mails"; @@ -191,8 +197,8 @@ kann nicht auf Mastodon hochgeladen werden."; tippe darin auf den Link, um Dein Konto zu bestätigen."; "Scene.ConfirmEmail.Title" = "Noch eine letzte Sache."; "Scene.Favorite.Title" = "Deine Favoriten"; -"Scene.Follower.Footer" = "Followers from other servers are not displayed."; -"Scene.Following.Footer" = "Follows from other servers are not displayed."; +"Scene.Follower.Footer" = "Follower von anderen Servern werden nicht angezeigt."; +"Scene.Following.Footer" = "Wem das Konto folgt wird von anderen Servern werden nicht angezeigt."; "Scene.HomeTimeline.NavigationBarState.NewPosts" = "Neue Beiträge anzeigen"; "Scene.HomeTimeline.NavigationBarState.Offline" = "Offline"; "Scene.HomeTimeline.NavigationBarState.Published" = "Veröffentlicht!"; @@ -200,14 +206,14 @@ tippe darin auf den Link, um Dein Konto zu bestätigen."; "Scene.HomeTimeline.Title" = "Startseite"; "Scene.Notification.Keyobard.ShowEverything" = "Alles anzeigen"; "Scene.Notification.Keyobard.ShowMentions" = "Erwähnungen anzeigen"; +"Scene.Notification.NotificationDescription.FavoritedYourPost" = "hat deinen Beitrag favorisiert"; +"Scene.Notification.NotificationDescription.FollowedYou" = "folgt dir"; +"Scene.Notification.NotificationDescription.MentionedYou" = "hat dich erwähnt"; +"Scene.Notification.NotificationDescription.PollHasEnded" = "Umfrage wurde beendet"; +"Scene.Notification.NotificationDescription.RebloggedYourPost" = "hat deinen Beitrag geteilt"; +"Scene.Notification.NotificationDescription.RequestToFollowYou" = "Folgeanfrage"; "Scene.Notification.Title.Everything" = "Alles"; "Scene.Notification.Title.Mentions" = "Erwähnungen"; -"Scene.Notification.UserFavorited Your Post" = "%@ favorisierte deinen Beitrag"; -"Scene.Notification.UserFollowedYou" = "%@ folgte dir"; -"Scene.Notification.UserMentionedYou" = "%@ erwähnte dich"; -"Scene.Notification.UserRebloggedYourPost" = "%@ teilte deinen Beitrag"; -"Scene.Notification.UserRequestedToFollowYou" = "%@ beantragte dir zu folgen"; -"Scene.Notification.UserYourPollHasEnded" = "%@ deine Umfrage ist beendet"; "Scene.Preview.Keyboard.ClosePreview" = "Vorschau schließen"; "Scene.Preview.Keyboard.ShowNext" = "Nächstes anzeigen"; "Scene.Preview.Keyboard.ShowPrevious" = "Vorheriges anzeigen"; @@ -217,12 +223,18 @@ tippe darin auf den Link, um Dein Konto zu bestätigen."; "Scene.Profile.Fields.AddRow" = "Zeile hinzufügen"; "Scene.Profile.Fields.Placeholder.Content" = "Inhalt"; "Scene.Profile.Fields.Placeholder.Label" = "Bezeichnung"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Message" = "Bestätigen zum Entsperren von %@"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Title" = "Konto entsperren"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Message" = "Bestätige %@ zu blockieren"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title" = "Konto blockieren"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Message" = "Bestätige %@ stumm zu schalten"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Title" = "Konto stummschalten"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Message" = "Bestätige %@ zu entsperren"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Title" = "Konto entsperren"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Message" = "Bestätige um %@ nicht mehr stummzuschalten"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Title" = "Ton einschalten"; +"Scene.Profile.SegmentedControl.About" = "Über"; "Scene.Profile.SegmentedControl.Media" = "Medien"; "Scene.Profile.SegmentedControl.Posts" = "Beiträge"; +"Scene.Profile.SegmentedControl.PostsAndReplies" = "Beiträge und Antworten"; "Scene.Profile.SegmentedControl.Replies" = "Antworten"; "Scene.Register.Error.Item.Agreement" = "Vereinbarung"; "Scene.Register.Error.Item.Email" = "E-Mail"; @@ -248,19 +260,26 @@ tippe darin auf den Link, um Dein Konto zu bestätigen."; "Scene.Register.Input.DisplayName.Placeholder" = "Anzeigename"; "Scene.Register.Input.Email.Placeholder" = "E-Mail"; "Scene.Register.Input.Invite.RegistrationUserInviteRequest" = "Warum möchtest du beitreten?"; +"Scene.Register.Input.Password.Accessibility.Checked" = "Häkchen gesetzt"; +"Scene.Register.Input.Password.Accessibility.Unchecked" = "Häkchen entfernt"; +"Scene.Register.Input.Password.CharacterLimit" = "8 Zeichen"; "Scene.Register.Input.Password.Hint" = "Ihr Passwort muss mindestens 8 Zeichen lang sein"; "Scene.Register.Input.Password.Placeholder" = "Passwort"; +"Scene.Register.Input.Password.Require" = "Anforderungen an dein Passwort:"; "Scene.Register.Input.Username.DuplicatePrompt" = "Dieser Benutzername ist vergeben."; "Scene.Register.Input.Username.Placeholder" = "Benutzername"; "Scene.Register.Title" = "Erzähle uns von dir."; "Scene.Report.Content1" = "Gibt es noch weitere Beiträge, die du der Meldung hinzufügen möchtest?"; "Scene.Report.Content2" = "Gibt es etwas, was die Moderatoren über diese Meldung wissen sollten?"; +"Scene.Report.ReportSentTitle" = "Danke für deine Meldung, wir werden uns damit beschäftigen."; +"Scene.Report.Reported" = "GEMELDET"; "Scene.Report.Send" = "Meldung abschicken"; "Scene.Report.SkipToSend" = "Ohne Kommentar abschicken"; "Scene.Report.Step1" = "Schritt 1 von 2"; "Scene.Report.Step2" = "Schritt 2 von 2"; "Scene.Report.TextPlaceholder" = "Zusätzliche Kommentare eingeben oder einfügen"; "Scene.Report.Title" = "%@ melden"; +"Scene.Report.TitleReport" = "Melden"; "Scene.Search.Recommend.Accounts.Description" = "Vielleicht gefallen dir diese Benutzer"; "Scene.Search.Recommend.Accounts.Follow" = "Folgen"; "Scene.Search.Recommend.Accounts.Title" = "Konten, die dir gefallen könnten"; @@ -301,6 +320,8 @@ tippe darin auf den Link, um Dein Konto zu bestätigen."; "Scene.ServerPicker.Label.Category" = "KATEGORIE"; "Scene.ServerPicker.Label.Language" = "SPRACHE"; "Scene.ServerPicker.Label.Users" = "BENUTZER"; +"Scene.ServerPicker.Subtitle" = "Wähle eine Gemeinschaft, die auf deinen Interessen, Region oder einem allgemeinen Zweck basiert."; +"Scene.ServerPicker.SubtitleExtend" = "Wähle eine Gemeinschaft basierend auf deinen Interessen, deiner Region oder einem allgemeinen Zweck. Jede Gemeinschaft wird von einer völlig unabhängigen Organisation oder Einzelperson betrieben."; "Scene.ServerPicker.Title" = "Wähle einen Server, beliebigen Server."; "Scene.ServerRules.Button.Confirm" = "Ich stimme zu"; @@ -318,7 +339,12 @@ beliebigen Server."; "Scene.Settings.Section.BoringZone.AccountSettings" = "Kontoeinstellungen"; "Scene.Settings.Section.BoringZone.Privacy" = "Datenschutzerklärung"; "Scene.Settings.Section.BoringZone.Terms" = "Allgemeine Geschäftsbedingungen"; -"Scene.Settings.Section.BoringZone.Title" = "Der Langweiliger Bereich"; +"Scene.Settings.Section.BoringZone.Title" = "Der langweilige Bereich"; +"Scene.Settings.Section.LookAndFeel.Light" = "Hell"; +"Scene.Settings.Section.LookAndFeel.ReallyDark" = "Wirklich dunkel"; +"Scene.Settings.Section.LookAndFeel.SortaDark" = "Ziemlich dunkel"; +"Scene.Settings.Section.LookAndFeel.Title" = "Erscheinungsbild"; +"Scene.Settings.Section.LookAndFeel.UseSystem" = "Systemeinstellung benutzen"; "Scene.Settings.Section.Notifications.Boosts" = "Meinen Beitrag teilt"; "Scene.Settings.Section.Notifications.Favorites" = "Meinen Beitrag favorisiert"; "Scene.Settings.Section.Notifications.Follows" = "Mir folgt"; @@ -342,6 +368,8 @@ beliebigen Server."; "Scene.SuggestionAccount.Title" = "Finde Personen zum Folgen"; "Scene.Thread.BackTitle" = "Beitrag"; "Scene.Thread.Title" = "Beitrag von %@"; +"Scene.Welcome.GetStarted" = "Erste Schritte"; +"Scene.Welcome.LogIn" = "Anmelden"; "Scene.Welcome.Slogan" = "Soziale Netzwerke wieder in deinen Händen."; "Scene.Wizard.AccessibilityHint" = "Doppeltippen, um diesen Assistenten zu schließen"; "Scene.Wizard.MultipleAccountSwitchIntroDescription" = "Wechsel zwischen mehreren Konten durch drücken der Profil-Schaltfläche."; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/en.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/en.lproj/Localizable.strings index 0f3ed66a..1a03cd56 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/en.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/en.lproj/Localizable.strings @@ -4,8 +4,8 @@ "Common.Alerts.CleanCache.Title" = "Clean Cache"; "Common.Alerts.Common.PleaseTryAgain" = "Please try again."; "Common.Alerts.Common.PleaseTryAgainLater" = "Please try again later."; -"Common.Alerts.DeletePost.Delete" = "Delete"; -"Common.Alerts.DeletePost.Title" = "Are you sure you want to delete this post?"; +"Common.Alerts.DeletePost.Message" = "Are you sure you want to delete this post?"; +"Common.Alerts.DeletePost.Title" = "Delete Post"; "Common.Alerts.DiscardPostContent.Message" = "Confirm to discard composed post content."; "Common.Alerts.DiscardPostContent.Title" = "Discard Draft"; "Common.Alerts.EditProfileFailure.Message" = "Cannot edit profile. Please try again."; @@ -41,6 +41,7 @@ Please check your internet connection."; "Common.Controls.Actions.Next" = "Next"; "Common.Controls.Actions.Ok" = "OK"; "Common.Controls.Actions.Open" = "Open"; +"Common.Controls.Actions.OpenInBrowser" = "Open in Browser"; "Common.Controls.Actions.OpenInSafari" = "Open in Safari"; "Common.Controls.Actions.Preview" = "Preview"; "Common.Controls.Actions.Previous" = "Previous"; @@ -93,6 +94,7 @@ Please check your internet connection."; "Common.Controls.Keyboard.Timeline.ToggleFavorite" = "Toggle Favorite on Post"; "Common.Controls.Keyboard.Timeline.ToggleReblog" = "Toggle Reblog on Post"; "Common.Controls.Status.Actions.Favorite" = "Favorite"; +"Common.Controls.Status.Actions.Hide" = "Hide"; "Common.Controls.Status.Actions.Menu" = "Menu"; "Common.Controls.Status.Actions.Reblog" = "Reblog"; "Common.Controls.Status.Actions.Reply" = "Reply"; @@ -112,6 +114,10 @@ Please check your internet connection."; "Common.Controls.Status.Tag.Url" = "URL"; "Common.Controls.Status.UserReblogged" = "%@ reblogged"; "Common.Controls.Status.UserRepliedTo" = "Replied to %@"; +"Common.Controls.Status.Visibility.Direct" = "Only mentioned user can see this post."; +"Common.Controls.Status.Visibility.Private" = "Only their followers can see this post."; +"Common.Controls.Status.Visibility.PrivateFromMe" = "Only my followers can see this post."; +"Common.Controls.Status.Visibility.Unlisted" = "Everyone can see this post but not display in the public timeline."; "Common.Controls.Tabs.Home" = "Home"; "Common.Controls.Tabs.Notification" = "Notification"; "Common.Controls.Tabs.Profile" = "Profile"; @@ -178,8 +184,8 @@ uploaded to Mastodon."; "Scene.Compose.Visibility.Private" = "Followers only"; "Scene.Compose.Visibility.Public" = "Public"; "Scene.Compose.Visibility.Unlisted" = "Unlisted"; -"Scene.ConfirmEmail.Button.DontReceiveEmail" = "I never got an email"; "Scene.ConfirmEmail.Button.OpenEmailApp" = "Open Email App"; +"Scene.ConfirmEmail.Button.Resend" = "Resend"; "Scene.ConfirmEmail.DontReceiveEmail.Description" = "Check if your email address is correct as well as your junk folder if you haven’t."; "Scene.ConfirmEmail.DontReceiveEmail.ResendEmail" = "Resend Email"; "Scene.ConfirmEmail.DontReceiveEmail.Title" = "Check your email"; @@ -187,8 +193,7 @@ uploaded to Mastodon."; "Scene.ConfirmEmail.OpenEmailApp.Mail" = "Mail"; "Scene.ConfirmEmail.OpenEmailApp.OpenEmailClient" = "Open Email Client"; "Scene.ConfirmEmail.OpenEmailApp.Title" = "Check your inbox."; -"Scene.ConfirmEmail.Subtitle" = "We just sent an email to %@, -tap the link to confirm your account."; +"Scene.ConfirmEmail.Subtitle" = "Tap the link we emailed to you to verify your account."; "Scene.ConfirmEmail.Title" = "One last thing."; "Scene.Favorite.Title" = "Your Favorites"; "Scene.Follower.Footer" = "Followers from other servers are not displayed."; @@ -200,14 +205,14 @@ tap the link to confirm your account."; "Scene.HomeTimeline.Title" = "Home"; "Scene.Notification.Keyobard.ShowEverything" = "Show Everything"; "Scene.Notification.Keyobard.ShowMentions" = "Show Mentions"; +"Scene.Notification.NotificationDescription.FavoritedYourPost" = "favorited your post"; +"Scene.Notification.NotificationDescription.FollowedYou" = "followed you"; +"Scene.Notification.NotificationDescription.MentionedYou" = "mentioned you"; +"Scene.Notification.NotificationDescription.PollHasEnded" = "poll has ended"; +"Scene.Notification.NotificationDescription.RebloggedYourPost" = "reblogged your post"; +"Scene.Notification.NotificationDescription.RequestToFollowYou" = "request to follow you"; "Scene.Notification.Title.Everything" = "Everything"; "Scene.Notification.Title.Mentions" = "Mentions"; -"Scene.Notification.UserFavorited Your Post" = "%@ favorited your post"; -"Scene.Notification.UserFollowedYou" = "%@ followed you"; -"Scene.Notification.UserMentionedYou" = "%@ mentioned you"; -"Scene.Notification.UserRebloggedYourPost" = "%@ reblogged your post"; -"Scene.Notification.UserRequestedToFollowYou" = "%@ requested to follow you"; -"Scene.Notification.UserYourPollHasEnded" = "%@ Your poll has ended"; "Scene.Preview.Keyboard.ClosePreview" = "Close Preview"; "Scene.Preview.Keyboard.ShowNext" = "Show Next"; "Scene.Preview.Keyboard.ShowPrevious" = "Show Previous"; @@ -217,12 +222,18 @@ tap the link to confirm your account."; "Scene.Profile.Fields.AddRow" = "Add Row"; "Scene.Profile.Fields.Placeholder.Content" = "Content"; "Scene.Profile.Fields.Placeholder.Label" = "Label"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Message" = "Confirm to unblock %@"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Title" = "Unblock Account"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Message" = "Confirm to block %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title" = "Block Account"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Message" = "Confirm to mute %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Title" = "Mute Account"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Message" = "Confirm to unblock %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Title" = "Unblock Account"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Message" = "Confirm to unmute %@"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Title" = "Unmute Account"; +"Scene.Profile.SegmentedControl.About" = "About"; "Scene.Profile.SegmentedControl.Media" = "Media"; "Scene.Profile.SegmentedControl.Posts" = "Posts"; +"Scene.Profile.SegmentedControl.PostsAndReplies" = "Posts and Replies"; "Scene.Profile.SegmentedControl.Replies" = "Replies"; "Scene.Register.Error.Item.Agreement" = "Agreement"; "Scene.Register.Error.Item.Email" = "Email"; @@ -248,19 +259,26 @@ tap the link to confirm your account."; "Scene.Register.Input.DisplayName.Placeholder" = "display name"; "Scene.Register.Input.Email.Placeholder" = "email"; "Scene.Register.Input.Invite.RegistrationUserInviteRequest" = "Why do you want to join?"; +"Scene.Register.Input.Password.Accessibility.Checked" = "checked"; +"Scene.Register.Input.Password.Accessibility.Unchecked" = "unchecked"; +"Scene.Register.Input.Password.CharacterLimit" = "8 characters"; "Scene.Register.Input.Password.Hint" = "Your password needs at least eight characters"; "Scene.Register.Input.Password.Placeholder" = "password"; +"Scene.Register.Input.Password.Require" = "Your password needs at least:"; "Scene.Register.Input.Username.DuplicatePrompt" = "This username is taken."; "Scene.Register.Input.Username.Placeholder" = "username"; -"Scene.Register.Title" = "Tell us about you."; +"Scene.Register.Title" = "Let’s get you set up on %@"; "Scene.Report.Content1" = "Are there any other posts you’d like to add to the report?"; "Scene.Report.Content2" = "Is there anything the moderators should know about this report?"; +"Scene.Report.ReportSentTitle" = "Thanks for reporting, we’ll look into this."; +"Scene.Report.Reported" = "REPORTED"; "Scene.Report.Send" = "Send Report"; "Scene.Report.SkipToSend" = "Send without comment"; "Scene.Report.Step1" = "Step 1 of 2"; "Scene.Report.Step2" = "Step 2 of 2"; "Scene.Report.TextPlaceholder" = "Type or paste additional comments"; "Scene.Report.Title" = "Report %@"; +"Scene.Report.TitleReport" = "Report"; "Scene.Search.Recommend.Accounts.Description" = "You may like to follow these accounts"; "Scene.Search.Recommend.Accounts.Follow" = "Follow"; "Scene.Search.Recommend.Accounts.Title" = "Accounts you might like"; @@ -297,16 +315,17 @@ tap the link to confirm your account."; "Scene.ServerPicker.EmptyState.BadNetwork" = "Something went wrong while loading the data. Check your internet connection."; "Scene.ServerPicker.EmptyState.FindingServers" = "Finding available servers..."; "Scene.ServerPicker.EmptyState.NoResults" = "No results"; -"Scene.ServerPicker.Input.Placeholder" = "Find a server or join your own..."; +"Scene.ServerPicker.Input.Placeholder" = "Search communities"; "Scene.ServerPicker.Label.Category" = "CATEGORY"; "Scene.ServerPicker.Label.Language" = "LANGUAGE"; "Scene.ServerPicker.Label.Users" = "USERS"; -"Scene.ServerPicker.Title" = "Pick a server, -any server."; +"Scene.ServerPicker.Subtitle" = "Pick a community based on your interests, region, or a general purpose one."; +"Scene.ServerPicker.SubtitleExtend" = "Pick a community based on your interests, region, or a general purpose one. Each community is operated by an entirely independent organization or individual."; +"Scene.ServerPicker.Title" = "Mastodon is made of users in different communities."; "Scene.ServerRules.Button.Confirm" = "I Agree"; "Scene.ServerRules.PrivacyPolicy" = "privacy policy"; "Scene.ServerRules.Prompt" = "By continuing, you’re subject to the terms of service and privacy policy for %@."; -"Scene.ServerRules.Subtitle" = "These rules are set by the admins of %@."; +"Scene.ServerRules.Subtitle" = "These are set and enforced by the %@ moderators."; "Scene.ServerRules.TermsOfService" = "terms of service"; "Scene.ServerRules.Title" = "Some ground rules."; "Scene.Settings.Footer.MastodonDescription" = "Mastodon is open source software. You can report issues on GitHub at %@ (%@)"; @@ -319,6 +338,11 @@ any server."; "Scene.Settings.Section.BoringZone.Privacy" = "Privacy Policy"; "Scene.Settings.Section.BoringZone.Terms" = "Terms of Service"; "Scene.Settings.Section.BoringZone.Title" = "The Boring Zone"; +"Scene.Settings.Section.LookAndFeel.Light" = "Light"; +"Scene.Settings.Section.LookAndFeel.ReallyDark" = "Really Dark"; +"Scene.Settings.Section.LookAndFeel.SortaDark" = "Sorta Dark"; +"Scene.Settings.Section.LookAndFeel.Title" = "Look and Feel"; +"Scene.Settings.Section.LookAndFeel.UseSystem" = "Use System"; "Scene.Settings.Section.Notifications.Boosts" = "Reblogs my post"; "Scene.Settings.Section.Notifications.Favorites" = "Favorites my post"; "Scene.Settings.Section.Notifications.Follows" = "Follows me"; @@ -342,6 +366,8 @@ any server."; "Scene.SuggestionAccount.Title" = "Find People to Follow"; "Scene.Thread.BackTitle" = "Post"; "Scene.Thread.Title" = "Post from %@"; +"Scene.Welcome.GetStarted" = "Get Started"; +"Scene.Welcome.LogIn" = "Log In"; "Scene.Welcome.Slogan" = "Social networking back in your hands."; "Scene.Wizard.AccessibilityHint" = "Double tap to dismiss this wizard"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/es-419.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/es-419.lproj/Localizable.strings index cf97fe80..d149865a 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/es-419.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/es-419.lproj/Localizable.strings @@ -4,7 +4,7 @@ "Common.Alerts.CleanCache.Title" = "Limpiar caché"; "Common.Alerts.Common.PleaseTryAgain" = "Por favor, intentá de nuevo."; "Common.Alerts.Common.PleaseTryAgainLater" = "Por favor, intentá de nuevo más tarde."; -"Common.Alerts.DeletePost.Delete" = "Eliminar"; +"Common.Alerts.DeletePost.Message" = "¿Estás seguro que querés eliminar este mensaje?"; "Common.Alerts.DeletePost.Title" = "¿Estás seguro que querés eliminar este mensaje?"; "Common.Alerts.DiscardPostContent.Message" = "Confirmá para descartar el contenido del mensaje redactado."; "Common.Alerts.DiscardPostContent.Title" = "Descartar borrador"; @@ -41,6 +41,7 @@ Por favor, revisá tu conexión a Internet."; "Common.Controls.Actions.Next" = "Siguiente"; "Common.Controls.Actions.Ok" = "Aceptar"; "Common.Controls.Actions.Open" = "Abrir"; +"Common.Controls.Actions.OpenInBrowser" = "Abrir en el navegador"; "Common.Controls.Actions.OpenInSafari" = "Abrir en Safari"; "Common.Controls.Actions.Preview" = "Previsualización"; "Common.Controls.Actions.Previous" = "Anterior"; @@ -93,6 +94,7 @@ Por favor, revisá tu conexión a Internet."; "Common.Controls.Keyboard.Timeline.ToggleFavorite" = "Cambiar la marca de favorito en el mensaje"; "Common.Controls.Keyboard.Timeline.ToggleReblog" = "Cambiar la adhesión en el mensaje"; "Common.Controls.Status.Actions.Favorite" = "Marcar como favorito"; +"Common.Controls.Status.Actions.Hide" = "Ocultar"; "Common.Controls.Status.Actions.Menu" = "Menú"; "Common.Controls.Status.Actions.Reblog" = "Adherir"; "Common.Controls.Status.Actions.Reply" = "Responder"; @@ -112,6 +114,10 @@ Por favor, revisá tu conexión a Internet."; "Common.Controls.Status.Tag.Url" = "Dirección web"; "Common.Controls.Status.UserReblogged" = "%@ adhirió"; "Common.Controls.Status.UserRepliedTo" = "Respondió a %@"; +"Common.Controls.Status.Visibility.Direct" = "Sólo el usuario mencionado puede ver este mensaje."; +"Common.Controls.Status.Visibility.Private" = "Sólo sus seguidores pueden ver este mensaje."; +"Common.Controls.Status.Visibility.PrivateFromMe" = "Sólo mis seguidores pueden ver este mensaje."; +"Common.Controls.Status.Visibility.Unlisted" = "Todo el mundo puede ver este mensaje pero no mostrarse en la línea temporal pública."; "Common.Controls.Tabs.Home" = "Principal"; "Common.Controls.Tabs.Notification" = "Notificación"; "Common.Controls.Tabs.Profile" = "Perfil"; @@ -178,8 +184,8 @@ y no se puede subir a Mastodon."; "Scene.Compose.Visibility.Private" = "Sólo para seguidores"; "Scene.Compose.Visibility.Public" = "Público"; "Scene.Compose.Visibility.Unlisted" = "No listado"; -"Scene.ConfirmEmail.Button.DontReceiveEmail" = "Nunca recibí un correo electrónico"; "Scene.ConfirmEmail.Button.OpenEmailApp" = "Abrir aplicación de correo electrónico"; +"Scene.ConfirmEmail.Button.Resend" = "Reenviar"; "Scene.ConfirmEmail.DontReceiveEmail.Description" = "Revisá si tu dirección de correo electrónico es correcta así como tu carpeta de correo basura / correo no deseado / spam, si todavía no lo hiciste."; "Scene.ConfirmEmail.DontReceiveEmail.ResendEmail" = "Reenviar correo electrónico"; "Scene.ConfirmEmail.DontReceiveEmail.Title" = "Revisá tu correo electrónico"; @@ -200,14 +206,14 @@ pulsá en el enlace para confirmar tu cuenta."; "Scene.HomeTimeline.Title" = "Principal"; "Scene.Notification.Keyobard.ShowEverything" = "Mostrar todo"; "Scene.Notification.Keyobard.ShowMentions" = "Mostrar menciones"; +"Scene.Notification.NotificationDescription.FavoritedYourPost" = "marcó como favorito tu mensaje"; +"Scene.Notification.NotificationDescription.FollowedYou" = "te sigue"; +"Scene.Notification.NotificationDescription.MentionedYou" = "te mencionó"; +"Scene.Notification.NotificationDescription.PollHasEnded" = "la encuesta terminó"; +"Scene.Notification.NotificationDescription.RebloggedYourPost" = "adhirió a tu mensaje"; +"Scene.Notification.NotificationDescription.RequestToFollowYou" = "solicitó seguirte"; "Scene.Notification.Title.Everything" = "Todo"; "Scene.Notification.Title.Mentions" = "Menciones"; -"Scene.Notification.UserFavorited Your Post" = "%@ marcó tu msj. como favorito"; -"Scene.Notification.UserFollowedYou" = "%@ te sigue"; -"Scene.Notification.UserMentionedYou" = "%@ te mencionó"; -"Scene.Notification.UserRebloggedYourPost" = "%@ adhirió a tu mensaje"; -"Scene.Notification.UserRequestedToFollowYou" = "%@ solicitó seguirte"; -"Scene.Notification.UserYourPollHasEnded" = "%@, tu encuesta finalizó"; "Scene.Preview.Keyboard.ClosePreview" = "Cerrar previsualización"; "Scene.Preview.Keyboard.ShowNext" = "Mostrar siguiente"; "Scene.Preview.Keyboard.ShowPrevious" = "Mostrar anterior"; @@ -217,12 +223,18 @@ pulsá en el enlace para confirmar tu cuenta."; "Scene.Profile.Fields.AddRow" = "Agregar fila"; "Scene.Profile.Fields.Placeholder.Content" = "Valor de campo"; "Scene.Profile.Fields.Placeholder.Label" = "Nombre de campo"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Message" = "Confirmá para desbloquear a %@"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Title" = "Desbloquear cuenta"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Message" = "Confirmá para desbloquear a %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title" = "Bloquear cuenta"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Message" = "Confirmá para silenciar a %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Title" = "Silenciar cuenta"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Message" = "Confirmá para desbloquear a %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Title" = "Desbloquear cuenta"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Message" = "Confirmá para dejar de silenciar a %@"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Title" = "Dejar de silenciar cuenta"; +"Scene.Profile.SegmentedControl.About" = "Información"; "Scene.Profile.SegmentedControl.Media" = "Medios"; "Scene.Profile.SegmentedControl.Posts" = "Mensajes"; +"Scene.Profile.SegmentedControl.PostsAndReplies" = "Mensajes y respuestas"; "Scene.Profile.SegmentedControl.Replies" = "Respuestas"; "Scene.Register.Error.Item.Agreement" = "Acuerdo"; "Scene.Register.Error.Item.Email" = "Correo electrónico"; @@ -248,19 +260,26 @@ pulsá en el enlace para confirmar tu cuenta."; "Scene.Register.Input.DisplayName.Placeholder" = "nombre para mostrar"; "Scene.Register.Input.Email.Placeholder" = "correo electrónico"; "Scene.Register.Input.Invite.RegistrationUserInviteRequest" = "¿Por qué querés unirte?"; +"Scene.Register.Input.Password.Accessibility.Checked" = "marcado"; +"Scene.Register.Input.Password.Accessibility.Unchecked" = "sin marcar"; +"Scene.Register.Input.Password.CharacterLimit" = "8 caracteres"; "Scene.Register.Input.Password.Hint" = "Tu contraseña necesita al menos ocho caracteres"; "Scene.Register.Input.Password.Placeholder" = "contraseña"; +"Scene.Register.Input.Password.Require" = "Tu contraseña necesita al menos:"; "Scene.Register.Input.Username.DuplicatePrompt" = "Este nombre de usuario ya está en uso."; "Scene.Register.Input.Username.Placeholder" = "nombre de usuario"; "Scene.Register.Title" = "Contanos sobre vos."; "Scene.Report.Content1" = "¿Hay otros mensajes que te gustaría agregar a la denuncia?"; "Scene.Report.Content2" = "¿Hay algo que los moderadores deban saber sobre esta denuncia?"; +"Scene.Report.ReportSentTitle" = "Gracias por tu denuncia, vamos a revisarla."; +"Scene.Report.Reported" = "DENUNCIADA"; "Scene.Report.Send" = "Enviar denuncia"; "Scene.Report.SkipToSend" = "Enviar sin comentarios"; "Scene.Report.Step1" = "Paso 1 de 2"; "Scene.Report.Step2" = "Paso 2 de 2"; "Scene.Report.TextPlaceholder" = "Escribí o pegá comentarios adicionales"; "Scene.Report.Title" = "Denunciar a %@"; +"Scene.Report.TitleReport" = "Denunciar"; "Scene.Search.Recommend.Accounts.Description" = "Puede que te guste seguir estas cuentas"; "Scene.Search.Recommend.Accounts.Follow" = "Seguir"; "Scene.Search.Recommend.Accounts.Title" = "Cuentas que te pueden gustar"; @@ -301,6 +320,8 @@ pulsá en el enlace para confirmar tu cuenta."; "Scene.ServerPicker.Label.Category" = "CATEGORÍA"; "Scene.ServerPicker.Label.Language" = "IDIOMA"; "Scene.ServerPicker.Label.Users" = "CUENTAS"; +"Scene.ServerPicker.Subtitle" = "Elegí una comunidad basada en tus intereses, región o una de propósitos generales."; +"Scene.ServerPicker.SubtitleExtend" = "Elegí una comunidad basada en tus intereses, región o una de propósitos generales. Cada comunidad es operada por una organización o individuo totalmente independiente."; "Scene.ServerPicker.Title" = "Elegí un servidor, el que quieras."; "Scene.ServerRules.Button.Confirm" = "Estoy de acuerdo"; @@ -319,6 +340,11 @@ el que quieras."; "Scene.Settings.Section.BoringZone.Privacy" = "Política de privacidad"; "Scene.Settings.Section.BoringZone.Terms" = "Términos del servicio"; "Scene.Settings.Section.BoringZone.Title" = "La zona aburrida"; +"Scene.Settings.Section.LookAndFeel.Light" = "Claro"; +"Scene.Settings.Section.LookAndFeel.ReallyDark" = "Oscuro de verdad"; +"Scene.Settings.Section.LookAndFeel.SortaDark" = "Algo oscuro"; +"Scene.Settings.Section.LookAndFeel.Title" = "Apariencia"; +"Scene.Settings.Section.LookAndFeel.UseSystem" = "Usar sistema"; "Scene.Settings.Section.Notifications.Boosts" = "Adhirió a mi mensaje"; "Scene.Settings.Section.Notifications.Favorites" = "Marcó como favorito mi mensaje"; "Scene.Settings.Section.Notifications.Follows" = "Me sigue"; @@ -342,6 +368,8 @@ el que quieras."; "Scene.SuggestionAccount.Title" = "Encontrá cuentas para seguir"; "Scene.Thread.BackTitle" = "Mensaje"; "Scene.Thread.Title" = "Mensaje de %@"; +"Scene.Welcome.GetStarted" = "Comenzá"; +"Scene.Welcome.LogIn" = "Iniciar sesión"; "Scene.Welcome.Slogan" = "La red social, nuevamente en tu poder."; "Scene.Wizard.AccessibilityHint" = "Tocá dos veces para descartar este asistente"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/es.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/es.lproj/Localizable.strings index dcf12dfe..09814c91 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/es.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/es.lproj/Localizable.strings @@ -4,7 +4,7 @@ "Common.Alerts.CleanCache.Title" = "Limpiar Caché"; "Common.Alerts.Common.PleaseTryAgain" = "Por favor, vuelve a intentarlo."; "Common.Alerts.Common.PleaseTryAgainLater" = "Por favor, vuelve a intentarlo más tarde."; -"Common.Alerts.DeletePost.Delete" = "Eliminar"; +"Common.Alerts.DeletePost.Message" = "¿Estás seguro de que quieres borrar esta publicación?"; "Common.Alerts.DeletePost.Title" = "¿Estás seguro de que deseas eliminar esta publicación?"; "Common.Alerts.DiscardPostContent.Message" = "Confirma para descartar el contenido de la publicación."; "Common.Alerts.DiscardPostContent.Title" = "Descartar borrador"; @@ -41,6 +41,7 @@ Por favor, revise su conexión a internet."; "Common.Controls.Actions.Next" = "Siguiente"; "Common.Controls.Actions.Ok" = "Aceptar"; "Common.Controls.Actions.Open" = "Abrir"; +"Common.Controls.Actions.OpenInBrowser" = "Abrir en el navegador"; "Common.Controls.Actions.OpenInSafari" = "Abrir en Safari"; "Common.Controls.Actions.Preview" = "Vista previa"; "Common.Controls.Actions.Previous" = "Anterior"; @@ -93,6 +94,7 @@ Por favor, revise su conexión a internet."; "Common.Controls.Keyboard.Timeline.ToggleFavorite" = "Conmutar la Marca de Favorito en la Publicación"; "Common.Controls.Keyboard.Timeline.ToggleReblog" = "Conmutar el Reblogueo en la Publicación"; "Common.Controls.Status.Actions.Favorite" = "Favorito"; +"Common.Controls.Status.Actions.Hide" = "Ocultar"; "Common.Controls.Status.Actions.Menu" = "Menú"; "Common.Controls.Status.Actions.Reblog" = "Rebloguear"; "Common.Controls.Status.Actions.Reply" = "Responder"; @@ -112,6 +114,10 @@ Por favor, revise su conexión a internet."; "Common.Controls.Status.Tag.Url" = "URL"; "Common.Controls.Status.UserReblogged" = "%@ lo reblogueó"; "Common.Controls.Status.UserRepliedTo" = "En respuesta a %@"; +"Common.Controls.Status.Visibility.Direct" = "Sólo el usuario mencionado puede ver este mensaje."; +"Common.Controls.Status.Visibility.Private" = "Sólo sus seguidores pueden ver este mensaje."; +"Common.Controls.Status.Visibility.PrivateFromMe" = "Sólo mis seguidores pueden ver este mensaje."; +"Common.Controls.Status.Visibility.Unlisted" = "Todo el mundo puede ver este post pero no mostrar en la línea de tiempo pública."; "Common.Controls.Tabs.Home" = "Inicio"; "Common.Controls.Tabs.Notification" = "Notificación"; "Common.Controls.Tabs.Profile" = "Perfil"; @@ -134,9 +140,9 @@ Tu perfil se ve así para él."; "Common.Controls.Timeline.Loader.LoadingMissingPosts" = "Cargando publicaciones faltantes..."; "Common.Controls.Timeline.Loader.ShowMoreReplies" = "Mostrar más respuestas"; "Common.Controls.Timeline.Timestamp.Now" = "Ahora"; -"Scene.AccountList.AddAccount" = "Add Account"; -"Scene.AccountList.DismissAccountSwitcher" = "Dismiss Account Switcher"; -"Scene.AccountList.TabBarHint" = "Current selected profile: %@. Double tap then hold to show account switcher"; +"Scene.AccountList.AddAccount" = "Añadir cuenta"; +"Scene.AccountList.DismissAccountSwitcher" = "Descartar el selector de cuentas"; +"Scene.AccountList.TabBarHint" = "Perfil seleccionado actualmente: %@. Haz un doble toque y mantén pulsado para mostrar el selector de cuentas"; "Scene.Compose.Accessibility.AppendAttachment" = "Añadir Adjunto"; "Scene.Compose.Accessibility.AppendPoll" = "Añadir Encuesta"; "Scene.Compose.Accessibility.CustomEmojiPicker" = "Selector de Emojis Personalizados"; @@ -178,8 +184,8 @@ subirse a Mastodon."; "Scene.Compose.Visibility.Private" = "Solo seguidores"; "Scene.Compose.Visibility.Public" = "Pública"; "Scene.Compose.Visibility.Unlisted" = "Sin listar"; -"Scene.ConfirmEmail.Button.DontReceiveEmail" = "No he recibido el correo electrónico"; "Scene.ConfirmEmail.Button.OpenEmailApp" = "Abrir Aplicación de Correo Electrónico"; +"Scene.ConfirmEmail.Button.Resend" = "Reenviar"; "Scene.ConfirmEmail.DontReceiveEmail.Description" = "Comprueba que tu dirección de correo electrónico sea correcta y revisa la carpeta de correo no deseado si no lo has hecho ya."; "Scene.ConfirmEmail.DontReceiveEmail.ResendEmail" = "Volver a Enviar Correo Electrónico"; "Scene.ConfirmEmail.DontReceiveEmail.Title" = "Revisa tu correo electrónico"; @@ -200,14 +206,14 @@ pulsa en el enlace para confirmar tu cuenta."; "Scene.HomeTimeline.Title" = "Inicio"; "Scene.Notification.Keyobard.ShowEverything" = "Mostrar Todo"; "Scene.Notification.Keyobard.ShowMentions" = "Mostrar Menciones"; +"Scene.Notification.NotificationDescription.FavoritedYourPost" = "ha marcado como favorita tu publicación"; +"Scene.Notification.NotificationDescription.FollowedYou" = "te siguió"; +"Scene.Notification.NotificationDescription.MentionedYou" = "te mencionó"; +"Scene.Notification.NotificationDescription.PollHasEnded" = "encuesta ha terminado"; +"Scene.Notification.NotificationDescription.RebloggedYourPost" = "reblogueó tu publicación"; +"Scene.Notification.NotificationDescription.RequestToFollowYou" = "solicitó seguirte"; "Scene.Notification.Title.Everything" = "Todo"; "Scene.Notification.Title.Mentions" = "Menciones"; -"Scene.Notification.UserFavorited Your Post" = "%@ marcó tu post como favorito"; -"Scene.Notification.UserFollowedYou" = "%@ te ha empezado a seguir"; -"Scene.Notification.UserMentionedYou" = "%@ te ha mencionado"; -"Scene.Notification.UserRebloggedYourPost" = "%@ reblogueó tu publicación"; -"Scene.Notification.UserRequestedToFollowYou" = "%@ ha solicitado seguirte"; -"Scene.Notification.UserYourPollHasEnded" = "%@ Tu encuesta ha terminado"; "Scene.Preview.Keyboard.ClosePreview" = "Cerrar Previsualización"; "Scene.Preview.Keyboard.ShowNext" = "Mostrar Siguiente"; "Scene.Preview.Keyboard.ShowPrevious" = "Mostrar Anterior"; @@ -217,12 +223,18 @@ pulsa en el enlace para confirmar tu cuenta."; "Scene.Profile.Fields.AddRow" = "Añadir Fila"; "Scene.Profile.Fields.Placeholder.Content" = "Contenido"; "Scene.Profile.Fields.Placeholder.Label" = "Nombre para el campo"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Message" = "Confirmar para desbloquear a %@"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Title" = "Desbloquear Cuenta"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Message" = "Confirmar para bloquear a %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title" = "Bloquear cuenta"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Message" = "Confirmar para silenciar %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Title" = "Silenciar cuenta"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Message" = "Confirmar para desbloquear a %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Title" = "Desbloquear cuenta"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Message" = "Confirmar para dejar de silenciar a %@"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Title" = "Dejar de Silenciar Cuenta"; +"Scene.Profile.SegmentedControl.About" = "Acerca de"; "Scene.Profile.SegmentedControl.Media" = "Multimedia"; "Scene.Profile.SegmentedControl.Posts" = "Publicaciones"; +"Scene.Profile.SegmentedControl.PostsAndReplies" = "Publicaciones y respuestas"; "Scene.Profile.SegmentedControl.Replies" = "Respuestas"; "Scene.Register.Error.Item.Agreement" = "Aceptación"; "Scene.Register.Error.Item.Email" = "Correo electrónico"; @@ -248,19 +260,26 @@ pulsa en el enlace para confirmar tu cuenta."; "Scene.Register.Input.DisplayName.Placeholder" = "nombre a mostrar"; "Scene.Register.Input.Email.Placeholder" = "correo electrónico"; "Scene.Register.Input.Invite.RegistrationUserInviteRequest" = "¿Por qué quieres unirte?"; +"Scene.Register.Input.Password.Accessibility.Checked" = "marcado"; +"Scene.Register.Input.Password.Accessibility.Unchecked" = "sin marcar"; +"Scene.Register.Input.Password.CharacterLimit" = "8 caracteres"; "Scene.Register.Input.Password.Hint" = "Tu contraseña necesita tener al menos ocho caracteres"; "Scene.Register.Input.Password.Placeholder" = "contraseña"; +"Scene.Register.Input.Password.Require" = "Tu contraseña debe contener como mínimo:"; "Scene.Register.Input.Username.DuplicatePrompt" = "Este nombre de usuario ya está en uso."; "Scene.Register.Input.Username.Placeholder" = "nombre de usuario"; "Scene.Register.Title" = "Háblanos de ti."; "Scene.Report.Content1" = "¿Hay alguna otra publicación que te gustaría añadir al reporte?"; "Scene.Report.Content2" = "¿Hay algo que los moderadores deberían saber acerca de este reporte?"; +"Scene.Report.ReportSentTitle" = "Gracias por reportar, estudiaremos esto."; +"Scene.Report.Reported" = "REPORTADO"; "Scene.Report.Send" = "Enviar Reporte"; "Scene.Report.SkipToSend" = "Enviar sin comentarios"; "Scene.Report.Step1" = "Paso 1 de 2"; "Scene.Report.Step2" = "Paso 2 de 2"; "Scene.Report.TextPlaceholder" = "Escribe o pega comentarios adicionales"; "Scene.Report.Title" = "Reportar %@"; +"Scene.Report.TitleReport" = "Reportar"; "Scene.Search.Recommend.Accounts.Description" = "Puede que guste seguir estas cuentas"; "Scene.Search.Recommend.Accounts.Follow" = "Seguir"; "Scene.Search.Recommend.Accounts.Title" = "Cuentas que quizá quieras seguir"; @@ -301,6 +320,8 @@ pulsa en el enlace para confirmar tu cuenta."; "Scene.ServerPicker.Label.Category" = "CATEGORÍA"; "Scene.ServerPicker.Label.Language" = "IDIOMA"; "Scene.ServerPicker.Label.Users" = "USUARIOS"; +"Scene.ServerPicker.Subtitle" = "Elige una comunidad relacionada con tus intereses, con tu región o una más genérica."; +"Scene.ServerPicker.SubtitleExtend" = "Elige una comunidad relacionada con tus intereses, con tu región o una más genérica. Cada comunidad está operada por una organización o individuo completamente independiente."; "Scene.ServerPicker.Title" = "Elige un servidor, cualquier servidor."; "Scene.ServerRules.Button.Confirm" = "Acepto"; @@ -319,6 +340,11 @@ cualquier servidor."; "Scene.Settings.Section.BoringZone.Privacy" = "Política de Privacidad"; "Scene.Settings.Section.BoringZone.Terms" = "Términos de Servicio"; "Scene.Settings.Section.BoringZone.Title" = "La Zona Aburrida"; +"Scene.Settings.Section.LookAndFeel.Light" = "Claro"; +"Scene.Settings.Section.LookAndFeel.ReallyDark" = "Realmente Oscuro"; +"Scene.Settings.Section.LookAndFeel.SortaDark" = "Más o Menos Oscuro"; +"Scene.Settings.Section.LookAndFeel.Title" = "Apariencia"; +"Scene.Settings.Section.LookAndFeel.UseSystem" = "Uso del sistema"; "Scene.Settings.Section.Notifications.Boosts" = "Rebloguee mi publicación"; "Scene.Settings.Section.Notifications.Favorites" = "Marque como favorita mi publicación"; "Scene.Settings.Section.Notifications.Follows" = "Me siga"; @@ -342,8 +368,10 @@ cualquier servidor."; "Scene.SuggestionAccount.Title" = "Encuentra Gente a la que Seguir"; "Scene.Thread.BackTitle" = "Publicación"; "Scene.Thread.Title" = "Publicación de %@"; +"Scene.Welcome.GetStarted" = "Empezar"; +"Scene.Welcome.LogIn" = "Iniciar sesión"; "Scene.Welcome.Slogan" = "Las redes sociales de nuevo en tus manos."; -"Scene.Wizard.AccessibilityHint" = "Double tap to dismiss this wizard"; -"Scene.Wizard.MultipleAccountSwitchIntroDescription" = "Switch between multiple accounts by holding the profile button."; -"Scene.Wizard.NewInMastodon" = "New in Mastodon"; \ No newline at end of file +"Scene.Wizard.AccessibilityHint" = "Haz doble toque para descartar este asistente"; +"Scene.Wizard.MultipleAccountSwitchIntroDescription" = "Cambie entre varias cuentas manteniendo presionado el botón de perfil."; +"Scene.Wizard.NewInMastodon" = "Nuevo en Mastodon"; \ No newline at end of file diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/es.lproj/Localizable.stringsdict b/MastodonSDK/Sources/MastodonLocalization/Resources/es.lproj/Localizable.stringsdict index d31d8825..186218af 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/es.lproj/Localizable.stringsdict +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/es.lproj/Localizable.stringsdict @@ -13,9 +13,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 unread notification</string> + <string>1 notificación no leída</string> <key>other</key> - <string>%ld unread notification</string> + <string>%ld notificaciones no leídas</string> </dict> </dict> <key>a11y.plural.count.input_limit_exceeds</key> diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/eu-ES.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/eu-ES.lproj/Localizable.strings new file mode 100644 index 00000000..7feec0a7 --- /dev/null +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/eu-ES.lproj/Localizable.strings @@ -0,0 +1,377 @@ +"Common.Alerts.BlockDomain.BlockEntireDomain" = "Blokeatu domeinua"; +"Common.Alerts.BlockDomain.Title" = "Ziur, erabat ziur, %@ domeinu osoa blokeatu nahi duzula? Gehienetan erabiltzaile gutxi batzuk blokeatu edo mututzearekin nahikoa da. Ez duzu domeinu horretako edukirik ikusiko eta domeinu horretako zure jarraitzaileak kenduko dira."; +"Common.Alerts.CleanCache.Message" = "Behar bezala garbitu da %@ cache-a."; +"Common.Alerts.CleanCache.Title" = "Garbitu cache-a"; +"Common.Alerts.Common.PleaseTryAgain" = "Mesedez, saiatu berriro."; +"Common.Alerts.Common.PleaseTryAgainLater" = "Mesedez beranduago saiatu."; +"Common.Alerts.DeletePost.Message" = "Ziur bidalketa hau ezabatu nahi duzula?"; +"Common.Alerts.DeletePost.Title" = "Ziur zaude bidalketa hau ezabatu nahi duzula?"; +"Common.Alerts.DiscardPostContent.Message" = "Berretsi idatzitako bidalketaren edukia baztertzea."; +"Common.Alerts.DiscardPostContent.Title" = "Baztertu zirriborroa"; +"Common.Alerts.EditProfileFailure.Message" = "Ezin da profila editatu. Mesedez saiatu berriro."; +"Common.Alerts.EditProfileFailure.Title" = "Errorea profila editatzean"; +"Common.Alerts.PublishPostFailure.AttachmentsMessage.MoreThanOneVideo" = "Ezin da bideo bat baino gehiago erantsi."; +"Common.Alerts.PublishPostFailure.AttachmentsMessage.VideoAttachWithPhoto" = "Ezin da irudiak dituen bidalketa batean bideo bat erantsi."; +"Common.Alerts.PublishPostFailure.Message" = "Huts egin du bidalketa argitaratzean. +Egiaztatu Interneteko konexioa."; +"Common.Alerts.PublishPostFailure.Title" = "Hutsegitea argitaratzean"; +"Common.Alerts.SavePhotoFailure.Message" = "Gaitu argazki galeriarako sarbidearen baimena argazkia gordetzeko."; +"Common.Alerts.SavePhotoFailure.Title" = "Hutsegitea argazkia gordetzean"; +"Common.Alerts.ServerError.Title" = "Zerbitzari-errorea"; +"Common.Alerts.SignOut.Confirm" = "Amaitu saioa"; +"Common.Alerts.SignOut.Message" = "Ziur saioa amaitu nahi duzula?"; +"Common.Alerts.SignOut.Title" = "Amaitu saioa"; +"Common.Alerts.SignUpFailure.Title" = "Hutsegitea izen-ematean"; +"Common.Alerts.VoteFailure.PollEnded" = "Inkesta amaitu da"; +"Common.Alerts.VoteFailure.Title" = "Hutsegitea botoa ematean"; +"Common.Controls.Actions.Add" = "Gehitu"; +"Common.Controls.Actions.Back" = "Atzera"; +"Common.Controls.Actions.BlockDomain" = "Blokeatu %@"; +"Common.Controls.Actions.Cancel" = "Utzi"; +"Common.Controls.Actions.Compose" = "Idatzi"; +"Common.Controls.Actions.Confirm" = "Berretsi"; +"Common.Controls.Actions.Continue" = "Jarraitu"; +"Common.Controls.Actions.CopyPhoto" = "Kopiatu argazkia"; +"Common.Controls.Actions.Delete" = "Ezabatu"; +"Common.Controls.Actions.Discard" = "Baztertu"; +"Common.Controls.Actions.Done" = "Egina"; +"Common.Controls.Actions.Edit" = "Editatu"; +"Common.Controls.Actions.FindPeople" = "Bilatu jarraitzeko jendea"; +"Common.Controls.Actions.ManuallySearch" = "Eskuz bilatu"; +"Common.Controls.Actions.Next" = "Hurrengoa"; +"Common.Controls.Actions.Ok" = "Ados"; +"Common.Controls.Actions.Open" = "Ireki"; +"Common.Controls.Actions.OpenInBrowser" = "Ireki nabigatzailean"; +"Common.Controls.Actions.OpenInSafari" = "Ireki Safarin"; +"Common.Controls.Actions.Preview" = "Aurrebista"; +"Common.Controls.Actions.Previous" = "Aurrekoa"; +"Common.Controls.Actions.Remove" = "Kendu"; +"Common.Controls.Actions.Reply" = "Erantzun"; +"Common.Controls.Actions.ReportUser" = "Salatu %@"; +"Common.Controls.Actions.Save" = "Gorde"; +"Common.Controls.Actions.SavePhoto" = "Gorde argazkia"; +"Common.Controls.Actions.SeeMore" = "Ikusi gehiago"; +"Common.Controls.Actions.Settings" = "Ezarpenak"; +"Common.Controls.Actions.Share" = "Partekatu"; +"Common.Controls.Actions.SharePost" = "Partekatu bidalketa"; +"Common.Controls.Actions.ShareUser" = "Partekatu %@"; +"Common.Controls.Actions.SignIn" = "Hasi saioa"; +"Common.Controls.Actions.SignUp" = "Eman Izena"; +"Common.Controls.Actions.Skip" = "Saltatu"; +"Common.Controls.Actions.TakePhoto" = "Atera argazkia"; +"Common.Controls.Actions.TryAgain" = "Saiatu berriro"; +"Common.Controls.Actions.UnblockDomain" = "Desblokeatu %@"; +"Common.Controls.Friendship.Block" = "Blokeatu"; +"Common.Controls.Friendship.BlockDomain" = "Blokeatu %@"; +"Common.Controls.Friendship.BlockUser" = "Blokeatu %@"; +"Common.Controls.Friendship.Blocked" = "Blokeatuta"; +"Common.Controls.Friendship.EditInfo" = "Editatu informazioa"; +"Common.Controls.Friendship.Follow" = "Jarraitu"; +"Common.Controls.Friendship.Following" = "Jarraitzen"; +"Common.Controls.Friendship.Mute" = "Mututu"; +"Common.Controls.Friendship.MuteUser" = "Mututu %@"; +"Common.Controls.Friendship.Muted" = "Mutututa"; +"Common.Controls.Friendship.Pending" = "Zain"; +"Common.Controls.Friendship.Request" = "Eskaera"; +"Common.Controls.Friendship.Unblock" = "Desblokeatu"; +"Common.Controls.Friendship.UnblockUser" = "Desblokeatu %@"; +"Common.Controls.Friendship.Unmute" = "Desmututu"; +"Common.Controls.Friendship.UnmuteUser" = "Desmututu %@"; +"Common.Controls.Keyboard.Common.ComposeNewPost" = "Idatzi bidalketa berria"; +"Common.Controls.Keyboard.Common.OpenSettings" = "Ireki ezarpenak"; +"Common.Controls.Keyboard.Common.ShowFavorites" = "Erakutsi gogokoak"; +"Common.Controls.Keyboard.Common.SwitchToTab" = "Aldatu %@(e)ra"; +"Common.Controls.Keyboard.SegmentedControl.NextSection" = "Hurrengo sekzioa"; +"Common.Controls.Keyboard.SegmentedControl.PreviousSection" = "Aurreko sekzioa"; +"Common.Controls.Keyboard.Timeline.NextStatus" = "Hurrengo bidalketa"; +"Common.Controls.Keyboard.Timeline.OpenAuthorProfile" = "Ireki egilearen profila"; +"Common.Controls.Keyboard.Timeline.OpenRebloggerProfile" = "Ireki bultzada eman duenaren profila"; +"Common.Controls.Keyboard.Timeline.OpenStatus" = "Ireki bidalketa"; +"Common.Controls.Keyboard.Timeline.PreviewImage" = "Aurreikusi irudia"; +"Common.Controls.Keyboard.Timeline.PreviousStatus" = "Aurreko bidalketa"; +"Common.Controls.Keyboard.Timeline.ReplyStatus" = "Erantzun bidalketari"; +"Common.Controls.Keyboard.Timeline.ToggleContentWarning" = "Txandakatu edukiaren abisua"; +"Common.Controls.Keyboard.Timeline.ToggleFavorite" = "Txandakatu bidalketa gogoko egitea"; +"Common.Controls.Keyboard.Timeline.ToggleReblog" = "Txandakatu bidalketaren bultzada"; +"Common.Controls.Status.Actions.Favorite" = "Gogokoa"; +"Common.Controls.Status.Actions.Hide" = "Ezkutatu"; +"Common.Controls.Status.Actions.Menu" = "Menua"; +"Common.Controls.Status.Actions.Reblog" = "Bultzada"; +"Common.Controls.Status.Actions.Reply" = "Erantzun"; +"Common.Controls.Status.Actions.Unfavorite" = "Kendu gogokoa"; +"Common.Controls.Status.Actions.Unreblog" = "Desegin bultzada"; +"Common.Controls.Status.ContentWarning" = "Edukiaren abisua"; +"Common.Controls.Status.MediaContentWarning" = "Ukitu edonon bistaratzeko"; +"Common.Controls.Status.Poll.Closed" = "Itxita"; +"Common.Controls.Status.Poll.Vote" = "Bozkatu"; +"Common.Controls.Status.ShowPost" = "Erakutsi bidalketa"; +"Common.Controls.Status.ShowUserProfile" = "Erakutsi erabiltzailearen profila"; +"Common.Controls.Status.Tag.Email" = "Eposta"; +"Common.Controls.Status.Tag.Emoji" = "Emojia"; +"Common.Controls.Status.Tag.Hashtag" = "Traola"; +"Common.Controls.Status.Tag.Link" = "Esteka"; +"Common.Controls.Status.Tag.Mention" = "Aipatu"; +"Common.Controls.Status.Tag.Url" = "URLa"; +"Common.Controls.Status.UserReblogged" = "%@ erabiltzaileak bultzada eman dio"; +"Common.Controls.Status.UserRepliedTo" = "%@(r)i erantzuten"; +"Common.Controls.Status.Visibility.Direct" = "Aipatutako erabiltzaileek soilik ikus dezakete bidalketa hau."; +"Common.Controls.Status.Visibility.Private" = "Beren jarraitzaileek soilik ikus dezakete bidalketa hau."; +"Common.Controls.Status.Visibility.PrivateFromMe" = "Nire jarraitzaileek soilik ikus dezakete bidalketa hau."; +"Common.Controls.Status.Visibility.Unlisted" = "Edozeinek ikusi dezake bidalketa hau baina ez da denbora-lerro publikoan bistaratuko."; +"Common.Controls.Tabs.Home" = "Hasiera"; +"Common.Controls.Tabs.Notification" = "Jakinarazpena"; +"Common.Controls.Tabs.Profile" = "Profila"; +"Common.Controls.Tabs.Search" = "Bilatu"; +"Common.Controls.Timeline.Filtered" = "Iragazita"; +"Common.Controls.Timeline.Header.BlockedWarning" = "Ezin duzu erabiltzaile honen profila ikusi +desblokeatzen zaituen arte."; +"Common.Controls.Timeline.Header.BlockingWarning" = "Ezin duzu erabiltzaile honen profila ikusi +desblokeatzen duzun arte. +Zure profilak itxura hau du berarentzat."; +"Common.Controls.Timeline.Header.NoStatusFound" = "Ez da bidalketa aurkitu"; +"Common.Controls.Timeline.Header.SuspendedWarning" = "Erabiltzaile hau kanporatua izan da."; +"Common.Controls.Timeline.Header.UserBlockedWarning" = "Ezin duzu %@ erabiltzailearen +profila ikusi desblokeatzen zaituen arte."; +"Common.Controls.Timeline.Header.UserBlockingWarning" = "Ezin duzu %@ erabiltzailearen +profila ikusi desblokeatzen duzun arte. +Zure profilak itxura hau du berarentzat."; +"Common.Controls.Timeline.Header.UserSuspendedWarning" = "%@ kontua kanporatua izan da."; +"Common.Controls.Timeline.Loader.LoadMissingPosts" = "Kargatu falta diren bidalketak"; +"Common.Controls.Timeline.Loader.LoadingMissingPosts" = "Falta diren bidalketak kargatzen..."; +"Common.Controls.Timeline.Loader.ShowMoreReplies" = "Erakutsi erantzun gehiago"; +"Common.Controls.Timeline.Timestamp.Now" = "Orain"; +"Scene.AccountList.AddAccount" = "Gehitu kontua"; +"Scene.AccountList.DismissAccountSwitcher" = "Baztertu kontu-aldatzailea"; +"Scene.AccountList.TabBarHint" = "Unean hautatutako profila: %@. Ukitu birritan, ondoren eduki sakatuta kontu-aldatzailea erakusteko"; +"Scene.Compose.Accessibility.AppendAttachment" = "Gehitu eranskina"; +"Scene.Compose.Accessibility.AppendPoll" = "Gehitu inkesta"; +"Scene.Compose.Accessibility.CustomEmojiPicker" = "Emoji pertsonalizatuen hautatzailea"; +"Scene.Compose.Accessibility.DisableContentWarning" = "Desgaitu edukiaren abisua"; +"Scene.Compose.Accessibility.EnableContentWarning" = "Gaitu edukiaren abisua"; +"Scene.Compose.Accessibility.PostVisibilityMenu" = "Bidalketaren ikusgaitasunaren menua"; +"Scene.Compose.Accessibility.RemovePoll" = "Kendu inkesta"; +"Scene.Compose.Attachment.AttachmentBroken" = "%@ hondatuta dago eta ezin da +Mastodonera igo."; +"Scene.Compose.Attachment.DescriptionPhoto" = "Deskribatu argazkia ikusmen arazoak dituztenentzat..."; +"Scene.Compose.Attachment.DescriptionVideo" = "Deskribatu bideoa ikusmen arazoak dituztenentzat..."; +"Scene.Compose.Attachment.Photo" = "argazkia"; +"Scene.Compose.Attachment.Video" = "bideoa"; +"Scene.Compose.AutoComplete.SpaceToAdd" = "Sakatu zuriunea gehitzeko"; +"Scene.Compose.ComposeAction" = "Argitaratu"; +"Scene.Compose.ContentInputPlaceholder" = "Idatzi edo itsatsi buruan duzuna"; +"Scene.Compose.ContentWarning.Placeholder" = "Idatzi abisu zehatz bat hemen..."; +"Scene.Compose.Keyboard.AppendAttachmentEntry" = "Gehitu eranskina - %@"; +"Scene.Compose.Keyboard.DiscardPost" = "Baztertu bidalketa"; +"Scene.Compose.Keyboard.PublishPost" = "Argitaratu bidalketa"; +"Scene.Compose.Keyboard.SelectVisibilityEntry" = "Hautatu ikusgaitasuna - %@"; +"Scene.Compose.Keyboard.ToggleContentWarning" = "Txandakatu edukiaren abisua"; +"Scene.Compose.Keyboard.TogglePoll" = "Txandakatu inkesta"; +"Scene.Compose.MediaSelection.Browse" = "Arakatu"; +"Scene.Compose.MediaSelection.Camera" = "Atera argazkia"; +"Scene.Compose.MediaSelection.PhotoLibrary" = "Argazki-liburutegia"; +"Scene.Compose.Poll.DurationTime" = "Iraupena: %@"; +"Scene.Compose.Poll.OneDay" = "Egun 1"; +"Scene.Compose.Poll.OneHour" = "Ordu 1"; +"Scene.Compose.Poll.OptionNumber" = "%ld aukera"; +"Scene.Compose.Poll.SevenDays" = "7 egun"; +"Scene.Compose.Poll.SixHours" = "6 ordu"; +"Scene.Compose.Poll.ThirtyMinutes" = "30 minutu"; +"Scene.Compose.Poll.ThreeDays" = "3 egun"; +"Scene.Compose.ReplyingToUser" = "%@(r)i erantzuten"; +"Scene.Compose.Title.NewPost" = "Bidalketa berria"; +"Scene.Compose.Title.NewReply" = "Erantzun berria"; +"Scene.Compose.Visibility.Direct" = "Aipatzen dudan jendea soilik"; +"Scene.Compose.Visibility.Private" = "Jarraitzaileak soilik"; +"Scene.Compose.Visibility.Public" = "Publikoa"; +"Scene.Compose.Visibility.Unlisted" = "Zerrendatu gabea"; +"Scene.ConfirmEmail.Button.OpenEmailApp" = "Ireki eposta aplikazioa"; +"Scene.ConfirmEmail.Button.Resend" = "Berbidali"; +"Scene.ConfirmEmail.DontReceiveEmail.Description" = "Egiaztatu zure eposta helbidea zuzena den eta begiratu zaborraren karpeta."; +"Scene.ConfirmEmail.DontReceiveEmail.ResendEmail" = "Birbidali eposta"; +"Scene.ConfirmEmail.DontReceiveEmail.Title" = "Begiratu zure eposta"; +"Scene.ConfirmEmail.OpenEmailApp.Description" = "Eposta bat bidali dizugu. Egiaztatu zure zaborraren karpeta."; +"Scene.ConfirmEmail.OpenEmailApp.Mail" = "Posta"; +"Scene.ConfirmEmail.OpenEmailApp.OpenEmailClient" = "Ireki eposta bezeroa"; +"Scene.ConfirmEmail.OpenEmailApp.Title" = "Egiaztatu zure sarrerako ontzia."; +"Scene.ConfirmEmail.Subtitle" = "Eposta bat bidali dizugu %@ helbidera, +sakatu kontua berresteko esteka."; +"Scene.ConfirmEmail.Title" = "Eta azkenik..."; +"Scene.Favorite.Title" = "Zure gogokoak"; +"Scene.Follower.Footer" = "Beste zerbitzarietako jarraitzaileak ez dira bistaratzen."; +"Scene.Following.Footer" = "Beste zerbitzarietan jarraitutakoak ez dira bistaratzen."; +"Scene.HomeTimeline.NavigationBarState.NewPosts" = "Ikusi bidal. berriak"; +"Scene.HomeTimeline.NavigationBarState.Offline" = "Konexio gabe"; +"Scene.HomeTimeline.NavigationBarState.Published" = "Argitaratua!"; +"Scene.HomeTimeline.NavigationBarState.Publishing" = "Bidalketa argitaratzen..."; +"Scene.HomeTimeline.Title" = "Hasiera"; +"Scene.Notification.Keyobard.ShowEverything" = "Erakutsi guztia"; +"Scene.Notification.Keyobard.ShowMentions" = "Erakutsi aipamenak"; +"Scene.Notification.NotificationDescription.FavoritedYourPost" = "erabiltzaileak zure bidalketa gogoko du"; +"Scene.Notification.NotificationDescription.FollowedYou" = "zu jarraitzen hasi da"; +"Scene.Notification.NotificationDescription.MentionedYou" = "erabiltzaileak aipatu zaitu"; +"Scene.Notification.NotificationDescription.PollHasEnded" = "inkesta amaitu da"; +"Scene.Notification.NotificationDescription.RebloggedYourPost" = "erabiltzaileak bultzada eman dio zure bidalketari"; +"Scene.Notification.NotificationDescription.RequestToFollowYou" = "erabiltzaileak zu jarraitzea eskatu du"; +"Scene.Notification.Title.Everything" = "Dena"; +"Scene.Notification.Title.Mentions" = "Aipamenak"; +"Scene.Preview.Keyboard.ClosePreview" = "Itxi aurrebista"; +"Scene.Preview.Keyboard.ShowNext" = "Erakutsi hurrengoa"; +"Scene.Preview.Keyboard.ShowPrevious" = "Erakutsi aurrekoa"; +"Scene.Profile.Dashboard.Followers" = "jarraitzaile"; +"Scene.Profile.Dashboard.Following" = "jarraitzen"; +"Scene.Profile.Dashboard.Posts" = "bidalketa"; +"Scene.Profile.Fields.AddRow" = "Gehitu errenkada"; +"Scene.Profile.Fields.Placeholder.Content" = "Edukia"; +"Scene.Profile.Fields.Placeholder.Label" = "Etiketa"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Message" = "Berretsi %@ blokeatzea"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title" = "Blokeatu kontua"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Message" = "Berretsi %@ mututzea"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Title" = "Mututu kontua"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Message" = "Berretsi %@ desblokeatzea"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Title" = "Desblokeatu kontua"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Message" = "Berretsi %@ desmututzea"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Title" = "Desmututu kontua"; +"Scene.Profile.SegmentedControl.About" = "Honi buruz"; +"Scene.Profile.SegmentedControl.Media" = "Multimedia"; +"Scene.Profile.SegmentedControl.Posts" = "Bidalketak"; +"Scene.Profile.SegmentedControl.PostsAndReplies" = "Bidalketak eta erantzunak"; +"Scene.Profile.SegmentedControl.Replies" = "Erantzunak"; +"Scene.Register.Error.Item.Agreement" = "Adostasuna"; +"Scene.Register.Error.Item.Email" = "Eposta"; +"Scene.Register.Error.Item.Locale" = "Eskualdeko ezarpenak"; +"Scene.Register.Error.Item.Password" = "Pasahitza"; +"Scene.Register.Error.Item.Reason" = "Arrazoia"; +"Scene.Register.Error.Item.Username" = "Erabiltzaile-izena"; +"Scene.Register.Error.Reason.Accepted" = "%@ onartu behar da"; +"Scene.Register.Error.Reason.Blank" = "%@ beharrezkoa da"; +"Scene.Register.Error.Reason.Blocked" = "%@(e)k onartu gabeko eposta hornitzaile bat erabiltzen du"; +"Scene.Register.Error.Reason.Inclusion" = "%@ ez da onartutako balio bat"; +"Scene.Register.Error.Reason.Invalid" = "%@ baliogabea da"; +"Scene.Register.Error.Reason.Reserved" = "%@ gako-hitz erreserbatu bat da"; +"Scene.Register.Error.Reason.Taken" = "%@ dagoeneko erabiltzen da"; +"Scene.Register.Error.Reason.TooLong" = "%@ luzeegia da"; +"Scene.Register.Error.Reason.TooShort" = "%@ laburregia da"; +"Scene.Register.Error.Reason.Unreachable" = "dirudienez %@ ez da existitzen"; +"Scene.Register.Error.Special.EmailInvalid" = "Hau ez da baliozko eposta helbidea"; +"Scene.Register.Error.Special.PasswordTooShort" = "Pasahitza laburregia da (gutxienez 8 karaktere izan behar ditu)"; +"Scene.Register.Error.Special.UsernameInvalid" = "Erabiltzaile-izenak karaktere alfanumerikoak eta azpimarrak soilik eduki ditzake"; +"Scene.Register.Error.Special.UsernameTooLong" = "Erabiltzaile-izena luzeegia da (ezin ditu 30 karaktere baino gehiago izan)"; +"Scene.Register.Input.Avatar.Delete" = "Ezabatu"; +"Scene.Register.Input.DisplayName.Placeholder" = "pantaila-izena"; +"Scene.Register.Input.Email.Placeholder" = "eposta"; +"Scene.Register.Input.Invite.RegistrationUserInviteRequest" = "Zergatik elkartu nahi duzu?"; +"Scene.Register.Input.Password.Accessibility.Checked" = "hautatuta"; +"Scene.Register.Input.Password.Accessibility.Unchecked" = "hautatu gabe"; +"Scene.Register.Input.Password.CharacterLimit" = "8 karaktere"; +"Scene.Register.Input.Password.Hint" = "Pasahitzak zortzi karaktere izan behar ditu gutxienez"; +"Scene.Register.Input.Password.Placeholder" = "pasahitza"; +"Scene.Register.Input.Password.Require" = "Zure pasahitzak izan behar ditu gutxienez:"; +"Scene.Register.Input.Username.DuplicatePrompt" = "Erabiltzaile-izen hau hartuta dago."; +"Scene.Register.Input.Username.Placeholder" = "erabiltzaile-izena"; +"Scene.Register.Title" = "Hitz egin iezaguzu zuri buruz."; +"Scene.Report.Content1" = "Salaketan beste bidalketarik gehitu nahi duzu?"; +"Scene.Report.Content2" = "Moderatzaileek besterik jakin behar dute salaketa honi buruz?"; +"Scene.Report.ReportSentTitle" = "Mila esker salaketagatik, berrikusiko dugu."; +"Scene.Report.Reported" = "SALATUA"; +"Scene.Report.Send" = "Bidali salaketa"; +"Scene.Report.SkipToSend" = "Bidali iruzkinik gabe"; +"Scene.Report.Step1" = "1. urratsa 2tik"; +"Scene.Report.Step2" = "2. urratsa 2tik"; +"Scene.Report.TextPlaceholder" = "Idatzi edo itsatsi iruzkin gehigarriak"; +"Scene.Report.Title" = "Salatu %@"; +"Scene.Report.TitleReport" = "Salatu"; +"Scene.Search.Recommend.Accounts.Description" = "Kontu hauek jarraitu nahiko dituzu behar bada"; +"Scene.Search.Recommend.Accounts.Follow" = "Jarraitu"; +"Scene.Search.Recommend.Accounts.Title" = "Gustuko izan ditzakezun kontuak"; +"Scene.Search.Recommend.ButtonText" = "Ikusi guztiak"; +"Scene.Search.Recommend.HashTag.Description" = "Deigarri gertatzen ari diren traolak"; +"Scene.Search.Recommend.HashTag.PeopleTalking" = "%@ pertsona hizketan"; +"Scene.Search.Recommend.HashTag.Title" = "Mastodoneko joerak"; +"Scene.Search.SearchBar.Cancel" = "Utzi"; +"Scene.Search.SearchBar.Placeholder" = "Bilatu traolak eta erabiltzaileak"; +"Scene.Search.Searching.Clear" = "Garbitu"; +"Scene.Search.Searching.EmptyState.NoResults" = "Emaitzarik ez"; +"Scene.Search.Searching.RecentSearch" = "Azken bilaketak"; +"Scene.Search.Searching.Segment.All" = "Guztiak"; +"Scene.Search.Searching.Segment.Hashtags" = "Traolak"; +"Scene.Search.Searching.Segment.People" = "Jendea"; +"Scene.Search.Searching.Segment.Posts" = "Bidalketak"; +"Scene.Search.Title" = "Bilatu"; +"Scene.ServerPicker.Button.Category.Academia" = "akademia"; +"Scene.ServerPicker.Button.Category.Activism" = "aktibismoa"; +"Scene.ServerPicker.Button.Category.All" = "Guztiak"; +"Scene.ServerPicker.Button.Category.AllAccessiblityDescription" = "Kategoria: Guztiak"; +"Scene.ServerPicker.Button.Category.Art" = "artea"; +"Scene.ServerPicker.Button.Category.Food" = "janaria"; +"Scene.ServerPicker.Button.Category.Furry" = "furry"; +"Scene.ServerPicker.Button.Category.Games" = "jokoak"; +"Scene.ServerPicker.Button.Category.General" = "orokorra"; +"Scene.ServerPicker.Button.Category.Journalism" = "kazetaritza"; +"Scene.ServerPicker.Button.Category.Lgbt" = "LGBTQ+"; +"Scene.ServerPicker.Button.Category.Music" = "musika"; +"Scene.ServerPicker.Button.Category.Regional" = "herrialdekoa"; +"Scene.ServerPicker.Button.Category.Tech" = "teknologia"; +"Scene.ServerPicker.Button.SeeLess" = "Ikusi gutxiago"; +"Scene.ServerPicker.Button.SeeMore" = "Ikusi gehiago"; +"Scene.ServerPicker.EmptyState.BadNetwork" = "Arazoren bat egon da datuak kargatzean. Egiaztatu zure Interneteko konexioa."; +"Scene.ServerPicker.EmptyState.FindingServers" = "Erabilgarri dauden zerbitzariak bilatzen..."; +"Scene.ServerPicker.EmptyState.NoResults" = "Emaitzarik ez"; +"Scene.ServerPicker.Input.Placeholder" = "Bilatu zerbitzari bat edo sortu zurea..."; +"Scene.ServerPicker.Label.Category" = "KATEGORIA"; +"Scene.ServerPicker.Label.Language" = "HIZKUNTZA"; +"Scene.ServerPicker.Label.Users" = "ERABILTZAILEAK"; +"Scene.ServerPicker.Subtitle" = "Aukeratu komunitate bat zure interes edo lurraldearen arabera, edo erabilera orokorreko bat."; +"Scene.ServerPicker.SubtitleExtend" = "Aukeratu komunitate bat zure interes edo lurraldearen arabera, edo erabilera orokorreko bat. Komunitate bakoitza erakunde edo norbanako independente batek kudeatzen du."; +"Scene.ServerPicker.Title" = "Aukeratu zerbitzari bat, +edozein zerbitzari."; +"Scene.ServerRules.Button.Confirm" = "Ados nago"; +"Scene.ServerRules.PrivacyPolicy" = "pribatutasun-gidalerroak"; +"Scene.ServerRules.Prompt" = "Jarraituz gero, %@ instantziaren zerbitzu-baldintzak eta pribatutasun-gidalerroak onartzen dituzu."; +"Scene.ServerRules.Subtitle" = "Arau hauek %@ instantziako administratzaileek ezarri dituzte."; +"Scene.ServerRules.TermsOfService" = "zerbitzu-baldintzak"; +"Scene.ServerRules.Title" = "Oinarrizko arau batzuk."; +"Scene.Settings.Footer.MastodonDescription" = "Mastodon software librea da. Arazoen berri eman dezakezu GitHub bidez: %@ (%@)"; +"Scene.Settings.Keyboard.CloseSettingsWindow" = "Itxi ezarpenen leihoa"; +"Scene.Settings.Section.Appearance.Automatic" = "Automatikoa"; +"Scene.Settings.Section.Appearance.Dark" = "Beti iluna"; +"Scene.Settings.Section.Appearance.Light" = "Beti argia"; +"Scene.Settings.Section.Appearance.Title" = "Itxura"; +"Scene.Settings.Section.BoringZone.AccountSettings" = "Kontuaren ezarpenak"; +"Scene.Settings.Section.BoringZone.Privacy" = "Pribatutasun-gidalerroak"; +"Scene.Settings.Section.BoringZone.Terms" = "Zerbitzu-baldintzak"; +"Scene.Settings.Section.BoringZone.Title" = "Eremu aspergarria"; +"Scene.Settings.Section.LookAndFeel.Light" = "Argia"; +"Scene.Settings.Section.LookAndFeel.ReallyDark" = "Oso iluna"; +"Scene.Settings.Section.LookAndFeel.SortaDark" = "Ilun antzekoa"; +"Scene.Settings.Section.LookAndFeel.Title" = "Itxura"; +"Scene.Settings.Section.LookAndFeel.UseSystem" = "Erabili sistemakoa"; +"Scene.Settings.Section.Notifications.Boosts" = "Nire bidalketa bultzatu du"; +"Scene.Settings.Section.Notifications.Favorites" = "Nire bidalketa gogoko egitean"; +"Scene.Settings.Section.Notifications.Follows" = "Jarraitzen nau"; +"Scene.Settings.Section.Notifications.Mentions" = "Aipatu nau"; +"Scene.Settings.Section.Notifications.Title" = "Jakinarazpenak"; +"Scene.Settings.Section.Notifications.Trigger.Anyone" = "edozein"; +"Scene.Settings.Section.Notifications.Trigger.Follow" = "jarraitzen dudan edonor"; +"Scene.Settings.Section.Notifications.Trigger.Follower" = "jarraitzaile bat"; +"Scene.Settings.Section.Notifications.Trigger.Noone" = "inor ez"; +"Scene.Settings.Section.Notifications.Trigger.Title" = "Noiz jakinarazi:"; +"Scene.Settings.Section.Preference.DisableAvatarAnimation" = "Desgaitu abatar animatuak"; +"Scene.Settings.Section.Preference.DisableEmojiAnimation" = "Desgaitu emoji animatuak"; +"Scene.Settings.Section.Preference.Title" = "Hobespenak"; +"Scene.Settings.Section.Preference.TrueBlackDarkMode" = "Benetako modu beltz iluna"; +"Scene.Settings.Section.Preference.UsingDefaultBrowser" = "Erabili nabigatzaile lehenetsia estekak irekitzeko"; +"Scene.Settings.Section.SpicyZone.Clear" = "Garbitu multimediaren cachea"; +"Scene.Settings.Section.SpicyZone.Signout" = "Amaitu saioa"; +"Scene.Settings.Section.SpicyZone.Title" = "Eremu beroa"; +"Scene.Settings.Title" = "Ezarpenak"; +"Scene.SuggestionAccount.FollowExplain" = "Norbait jarraitzen duzunean, bere bidalketak zure hasierako denbora-lerroan agertuko zaizkizu."; +"Scene.SuggestionAccount.Title" = "Bilatu jarraitzeko jendea"; +"Scene.Thread.BackTitle" = "Bidalketa"; +"Scene.Thread.Title" = "%@(e)n bidalketa"; +"Scene.Welcome.GetStarted" = "Nola hasi"; +"Scene.Welcome.LogIn" = "Hasi saioa"; +"Scene.Welcome.Slogan" = "Sare sozialak +berriz zure eskuetan."; +"Scene.Wizard.AccessibilityHint" = "Ukitu birritan morroi hau baztertzeko"; +"Scene.Wizard.MultipleAccountSwitchIntroDescription" = "Aldatu hainbat konturen artean profilaren botoia sakatuta edukiz."; +"Scene.Wizard.NewInMastodon" = "Berria Mastodonen"; \ No newline at end of file diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/eu-ES.lproj/Localizable.stringsdict b/MastodonSDK/Sources/MastodonLocalization/Resources/eu-ES.lproj/Localizable.stringsdict new file mode 100644 index 00000000..817e8372 --- /dev/null +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/eu-ES.lproj/Localizable.stringsdict @@ -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>Irakurri gabeko jakinarazpen bat</string> + <key>other</key> + <string>Irakurri gabeko %ld jakinarazpen</string> + </dict> + </dict> + <key>a11y.plural.count.input_limit_exceeds</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>Sarrerak %#@character_count@ karaktereko muga gainditzen du</string> + <key>character_count</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>ld</string> + <key>one</key> + <string>karaktere bat</string> + <key>other</key> + <string>%ld karaktere</string> + </dict> + </dict> + <key>a11y.plural.count.input_limit_remains</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>Sarreraren karaktere muga %#@character_count@ da oraindik</string> + <key>character_count</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>ld</string> + <key>one</key> + <string>karaktere bat</string> + <key>other</key> + <string>%ld karaktere</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>bidalketa</string> + <key>other</key> + <string>bidalketa</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>Bidalketa bat</string> + <key>other</key> + <string>%ld bidalketa</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>Gogoko bat</string> + <key>other</key> + <string>%ld gogoko</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>Bultzada bat</string> + <key>other</key> + <string>%ld bultzada</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>Boto bat</string> + <key>other</key> + <string>%ld boto</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>Boto-emaile bat</string> + <key>other</key> + <string>%ld boto-emaile</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>Pertsona bat hizketan</string> + <key>other</key> + <string>%ld pertsona hizketan</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>Bat jarraitzen</string> + <key>other</key> + <string>%ld jarraitzen</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>Jarraitzaile bat</string> + <key>other</key> + <string>%ld jarraitzaile</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>Urte bat geratzen da</string> + <key>other</key> + <string>%ld urte geratzen dira</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>Hilabete bat geratzen da</string> + <key>other</key> + <string>%ld hilabete geratzen dira</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>Egun bat geratzen da</string> + <key>other</key> + <string>%ld egun geratzen dira</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>Ordu 1 geratzen da</string> + <key>other</key> + <string>%ld ordu geratzen dira</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>Minutu 1 geratzen da</string> + <key>other</key> + <string>%ld minutu geratzen dira</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>Segundo 1 geratzen da</string> + <key>other</key> + <string>%ld segundo geratzen dira</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>Duela urtebete</string> + <key>other</key> + <string>Duela %ld urte</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>Duela hilabete</string> + <key>other</key> + <string>Duela %ld hilabete</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>Duela egun bat</string> + <key>other</key> + <string>Duela %ld egun</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>Duela ordubete</string> + <key>other</key> + <string>Duela %ld ordu</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>Duela minutu bat</string> + <key>other</key> + <string>Duela %ld minutu</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>Duela segundo bat</string> + <key>other</key> + <string>Duela %ld segundo</string> + </dict> + </dict> + </dict> +</plist> diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/fr.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/fr.lproj/Localizable.strings index a4dbfdb6..ffcd2846 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/fr.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/fr.lproj/Localizable.strings @@ -4,7 +4,7 @@ "Common.Alerts.CleanCache.Title" = "Vider le cache"; "Common.Alerts.Common.PleaseTryAgain" = "Merci de réessayer."; "Common.Alerts.Common.PleaseTryAgainLater" = "Merci de réessayer plus tard."; -"Common.Alerts.DeletePost.Delete" = "Supprimer"; +"Common.Alerts.DeletePost.Message" = "Voulez-vous vraiment supprimer ce message ?"; "Common.Alerts.DeletePost.Title" = "Voulez-vous vraiment supprimer ce message ?"; "Common.Alerts.DiscardPostContent.Message" = "Confirmez pour abandonner le contenu de votre message."; "Common.Alerts.DiscardPostContent.Title" = "Abandonner le brouillon"; @@ -28,7 +28,7 @@ Veuillez vérifier votre accès à Internet."; "Common.Controls.Actions.Back" = "Retour"; "Common.Controls.Actions.BlockDomain" = "Bloquer %@"; "Common.Controls.Actions.Cancel" = "Annuler"; -"Common.Controls.Actions.Compose" = "Compose"; +"Common.Controls.Actions.Compose" = "Rédiger"; "Common.Controls.Actions.Confirm" = "Confirmer"; "Common.Controls.Actions.Continue" = "Continuer"; "Common.Controls.Actions.CopyPhoto" = "Copier la photo"; @@ -41,6 +41,7 @@ Veuillez vérifier votre accès à Internet."; "Common.Controls.Actions.Next" = "Suivant"; "Common.Controls.Actions.Ok" = "OK"; "Common.Controls.Actions.Open" = "Ouvrir"; +"Common.Controls.Actions.OpenInBrowser" = "Ouvrir dans le navigateur"; "Common.Controls.Actions.OpenInSafari" = "Ouvrir dans Safari"; "Common.Controls.Actions.Preview" = "Aperçu"; "Common.Controls.Actions.Previous" = "Précédent"; @@ -93,6 +94,7 @@ Veuillez vérifier votre accès à Internet."; "Common.Controls.Keyboard.Timeline.ToggleFavorite" = "Basculer le favori lors de la publication"; "Common.Controls.Keyboard.Timeline.ToggleReblog" = "Basculer le reblogue lors de la publication"; "Common.Controls.Status.Actions.Favorite" = "Favori"; +"Common.Controls.Status.Actions.Hide" = "Cacher"; "Common.Controls.Status.Actions.Menu" = "Menu"; "Common.Controls.Status.Actions.Reblog" = "Rebloguer"; "Common.Controls.Status.Actions.Reply" = "Répondre"; @@ -112,6 +114,10 @@ Veuillez vérifier votre accès à Internet."; "Common.Controls.Status.Tag.Url" = "URL"; "Common.Controls.Status.UserReblogged" = "%@ a reblogué"; "Common.Controls.Status.UserRepliedTo" = "À répondu à %@"; +"Common.Controls.Status.Visibility.Direct" = "Seul·e l’utilisateur·rice mentionnée peut voir ce message."; +"Common.Controls.Status.Visibility.Private" = "Seul·e·s leurs abonné·e·s peuvent voir ce message."; +"Common.Controls.Status.Visibility.PrivateFromMe" = "Seul·e·s mes abonné·e·s peuvent voir ce message."; +"Common.Controls.Status.Visibility.Unlisted" = "Tout le monde peut voir ce message mais ne sera pas affiché sur le fil public."; "Common.Controls.Tabs.Home" = "Accueil"; "Common.Controls.Tabs.Notification" = "Notification"; "Common.Controls.Tabs.Profile" = "Profil"; @@ -135,8 +141,8 @@ Votre profil ressemble à ça pour lui."; "Common.Controls.Timeline.Loader.ShowMoreReplies" = "Charger plus de réponses"; "Common.Controls.Timeline.Timestamp.Now" = "À l’instant"; "Scene.AccountList.AddAccount" = "Ajouter un compte"; -"Scene.AccountList.DismissAccountSwitcher" = "Dismiss Account Switcher"; -"Scene.AccountList.TabBarHint" = "Current selected profile: %@. Double tap then hold to show account switcher"; +"Scene.AccountList.DismissAccountSwitcher" = "Rejeter le commutateur de compte"; +"Scene.AccountList.TabBarHint" = "Profil sélectionné actuel: %@. Double appui puis maintenez enfoncé pour afficher le changement de compte"; "Scene.Compose.Accessibility.AppendAttachment" = "Joindre un document"; "Scene.Compose.Accessibility.AppendPoll" = "Ajouter un Sondage"; "Scene.Compose.Accessibility.CustomEmojiPicker" = "Sélecteur d’émojis personnalisés"; @@ -178,8 +184,8 @@ téléversé sur Mastodon."; "Scene.Compose.Visibility.Private" = "Abonnés seulement"; "Scene.Compose.Visibility.Public" = "Public"; "Scene.Compose.Visibility.Unlisted" = "Non listé"; -"Scene.ConfirmEmail.Button.DontReceiveEmail" = "Je n’ai jamais reçu de courriel"; "Scene.ConfirmEmail.Button.OpenEmailApp" = "Ouvrir l’application de courriel"; +"Scene.ConfirmEmail.Button.Resend" = "Renvoyer"; "Scene.ConfirmEmail.DontReceiveEmail.Description" = "Vérifiez que votre adresse courriel est valide ainsi que votre fichier spam si ce n’est pas déjà fait."; "Scene.ConfirmEmail.DontReceiveEmail.ResendEmail" = "Renvoyer le courriel"; "Scene.ConfirmEmail.DontReceiveEmail.Title" = "Vérifier vos courriels"; @@ -192,7 +198,7 @@ tapotez le lien pour confirmer votre compte."; "Scene.ConfirmEmail.Title" = "Une dernière chose."; "Scene.Favorite.Title" = "Vos favoris"; "Scene.Follower.Footer" = "Les abonné·e·s issus des autres serveurs ne sont pas affiché·e·s."; -"Scene.Following.Footer" = "Follows from other servers are not displayed."; +"Scene.Following.Footer" = "Les abonnés issus des autres serveurs ne sont pas affichés."; "Scene.HomeTimeline.NavigationBarState.NewPosts" = "Voir les nouvelles publications"; "Scene.HomeTimeline.NavigationBarState.Offline" = "Hors ligne"; "Scene.HomeTimeline.NavigationBarState.Published" = "Publié!"; @@ -200,14 +206,14 @@ tapotez le lien pour confirmer votre compte."; "Scene.HomeTimeline.Title" = "Accueil"; "Scene.Notification.Keyobard.ShowEverything" = "Tout Afficher"; "Scene.Notification.Keyobard.ShowMentions" = "Afficher les mentions"; +"Scene.Notification.NotificationDescription.FavoritedYourPost" = "a ajouté votre message à ses favoris"; +"Scene.Notification.NotificationDescription.FollowedYou" = "s’est abonné à vous"; +"Scene.Notification.NotificationDescription.MentionedYou" = "vous a mentionné"; +"Scene.Notification.NotificationDescription.PollHasEnded" = "le sondage est terminé"; +"Scene.Notification.NotificationDescription.RebloggedYourPost" = "a partagé votre message"; +"Scene.Notification.NotificationDescription.RequestToFollowYou" = "vous a envoyé une demande d’abonnement"; "Scene.Notification.Title.Everything" = "Tout"; "Scene.Notification.Title.Mentions" = "Mentions"; -"Scene.Notification.UserFavorited Your Post" = "%@ a mis votre pouet en favori"; -"Scene.Notification.UserFollowedYou" = "%@ s’est abonné à vous"; -"Scene.Notification.UserMentionedYou" = "%@ vous a mentionné"; -"Scene.Notification.UserRebloggedYourPost" = "%@ a partagé votre publication"; -"Scene.Notification.UserRequestedToFollowYou" = "%@ a demandé à vous suivre"; -"Scene.Notification.UserYourPollHasEnded" = "%@ votre sondage est terminé"; "Scene.Preview.Keyboard.ClosePreview" = "Fermer l'aperçu"; "Scene.Preview.Keyboard.ShowNext" = "Afficher le suivant"; "Scene.Preview.Keyboard.ShowPrevious" = "Afficher le précédent"; @@ -217,12 +223,18 @@ tapotez le lien pour confirmer votre compte."; "Scene.Profile.Fields.AddRow" = "Ajouter une rangée"; "Scene.Profile.Fields.Placeholder.Content" = "Contenu"; "Scene.Profile.Fields.Placeholder.Label" = "Étiquette"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Message" = "Confirmer le déblocage de %@"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Title" = "Débloquer le compte"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Message" = "Confirmer le blocage de %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title" = "Bloquer le compte"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Message" = "Êtes-vous sûr de vouloir mettre en sourdine %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Title" = "Masquer le compte"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Message" = "Confirmer le déblocage de %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Title" = "Débloquer le compte"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Message" = "Êtes-vous sûr de vouloir désactiver la sourdine de %@"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Title" = "Ne plus mettre en sourdine ce compte"; +"Scene.Profile.SegmentedControl.About" = "À propos"; "Scene.Profile.SegmentedControl.Media" = "Média"; "Scene.Profile.SegmentedControl.Posts" = "Publications"; +"Scene.Profile.SegmentedControl.PostsAndReplies" = "Messages et réponses"; "Scene.Profile.SegmentedControl.Replies" = "Réponses"; "Scene.Register.Error.Item.Agreement" = "Accord"; "Scene.Register.Error.Item.Email" = "Courriel"; @@ -248,19 +260,26 @@ tapotez le lien pour confirmer votre compte."; "Scene.Register.Input.DisplayName.Placeholder" = "nom affiché"; "Scene.Register.Input.Email.Placeholder" = "courriel"; "Scene.Register.Input.Invite.RegistrationUserInviteRequest" = "Pourquoi voulez-vous vous inscrire ?"; +"Scene.Register.Input.Password.Accessibility.Checked" = "vérifié"; +"Scene.Register.Input.Password.Accessibility.Unchecked" = "non vérifié"; +"Scene.Register.Input.Password.CharacterLimit" = "8 caractères"; "Scene.Register.Input.Password.Hint" = "Votre mot de passe doit contenir au moins 8 caractères"; "Scene.Register.Input.Password.Placeholder" = "mot de passe"; +"Scene.Register.Input.Password.Require" = "Votre mot de passe doit être composé d’au moins :"; "Scene.Register.Input.Username.DuplicatePrompt" = "Ce nom d'utilisateur est déjà pris."; "Scene.Register.Input.Username.Placeholder" = "nom d'utilisateur"; "Scene.Register.Title" = "Parlez-nous de vous."; "Scene.Report.Content1" = "Y a-t-il d’autres messages que vous aimeriez ajouter au signalement?"; "Scene.Report.Content2" = "Y a-t-il quelque chose que les modérateurs devraient savoir sur ce rapport ?"; +"Scene.Report.ReportSentTitle" = "Merci de nous l’avoir signalé, nous allons examiner cela."; +"Scene.Report.Reported" = "SIGNALÉ"; "Scene.Report.Send" = "Envoyer le rapport"; "Scene.Report.SkipToSend" = "Envoyer sans commentaire"; "Scene.Report.Step1" = "Étape 1 de 2"; "Scene.Report.Step2" = "Étape 2 de 2"; "Scene.Report.TextPlaceholder" = "Tapez ou collez des informations supplémentaires"; "Scene.Report.Title" = "Signaler %@"; +"Scene.Report.TitleReport" = "Signalement"; "Scene.Search.Recommend.Accounts.Description" = "Vous aimeriez peut-être suivre ces comptes"; "Scene.Search.Recommend.Accounts.Follow" = "Suivre"; "Scene.Search.Recommend.Accounts.Title" = "Comptes que vous pourriez aimer"; @@ -301,6 +320,8 @@ tapotez le lien pour confirmer votre compte."; "Scene.ServerPicker.Label.Category" = "CATÉGORIE"; "Scene.ServerPicker.Label.Language" = "LANGUE"; "Scene.ServerPicker.Label.Users" = "UTILISATEUR·RICE·S"; +"Scene.ServerPicker.Subtitle" = "Choisissez une communauté en fonction de vos intérêts, de votre région ou de votre objectif général."; +"Scene.ServerPicker.SubtitleExtend" = "Choisissez une communauté basée sur vos intérêts, votre région ou un but général. Chaque communauté est gérée par une organisation ou un individu entièrement indépendant."; "Scene.ServerPicker.Title" = "Choisissez un serveur, n'importe quel serveur."; "Scene.ServerRules.Button.Confirm" = "J’accepte"; @@ -319,6 +340,11 @@ n'importe quel serveur."; "Scene.Settings.Section.BoringZone.Privacy" = "Politique de confidentialité"; "Scene.Settings.Section.BoringZone.Terms" = "Entente de service"; "Scene.Settings.Section.BoringZone.Title" = "La zone ennuyante"; +"Scene.Settings.Section.LookAndFeel.Light" = "Clair"; +"Scene.Settings.Section.LookAndFeel.ReallyDark" = "Très sombre"; +"Scene.Settings.Section.LookAndFeel.SortaDark" = "Légèrement sombre"; +"Scene.Settings.Section.LookAndFeel.Title" = "Apparence"; +"Scene.Settings.Section.LookAndFeel.UseSystem" = "Utiliser le thème du système"; "Scene.Settings.Section.Notifications.Boosts" = "Reblogue mon message"; "Scene.Settings.Section.Notifications.Favorites" = "Ajoute l’une de mes publications à ses favoris"; "Scene.Settings.Section.Notifications.Follows" = "Me suit"; @@ -342,6 +368,8 @@ n'importe quel serveur."; "Scene.SuggestionAccount.Title" = "Trouver des personnes à suivre"; "Scene.Thread.BackTitle" = "Publication"; "Scene.Thread.Title" = "Publication de %@"; +"Scene.Welcome.GetStarted" = "Prise en main"; +"Scene.Welcome.LogIn" = "Se connecter"; "Scene.Welcome.Slogan" = "Le réseau social qui vous rend le contrôle."; "Scene.Wizard.AccessibilityHint" = "Tapotez deux fois pour fermer cet assistant"; "Scene.Wizard.MultipleAccountSwitchIntroDescription" = "Basculez entre plusieurs comptes en appuyant de maniere prolongée sur le bouton profil."; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/fr.lproj/Localizable.stringsdict b/MastodonSDK/Sources/MastodonLocalization/Resources/fr.lproj/Localizable.stringsdict index 4a912e4b..37f07e67 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/fr.lproj/Localizable.stringsdict +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/fr.lproj/Localizable.stringsdict @@ -37,7 +37,7 @@ <key>a11y.plural.count.input_limit_remains</key> <dict> <key>NSStringLocalizedFormatKey</key> - <string>Input limit remains %#@character_count@</string> + <string>La limite d'entrée reste %#@character_count@</string> <key>character_count</key> <dict> <key>NSStringFormatSpecTypeKey</key> diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/gd-GB.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/gd-GB.lproj/Localizable.strings index 3f80f641..be6ea23a 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/gd-GB.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/gd-GB.lproj/Localizable.strings @@ -4,7 +4,7 @@ "Common.Alerts.CleanCache.Title" = "Falamhaich an tasgadan"; "Common.Alerts.Common.PleaseTryAgain" = "Feuch ris a-rithist."; "Common.Alerts.Common.PleaseTryAgainLater" = "Feuch ris a-rithist an ceann greis."; -"Common.Alerts.DeletePost.Delete" = "Sguab às"; +"Common.Alerts.DeletePost.Message" = "A bheil thu cinnteach gu bheil thu airson am post seo a sguabadh às?"; "Common.Alerts.DeletePost.Title" = "A bheil thu cinnteach gu bheil thu airson am post seo a sguabadh às?"; "Common.Alerts.DiscardPostContent.Message" = "Dearbh tilgeil air falbh susbaint a’ phuist a sgrìobh thu."; "Common.Alerts.DiscardPostContent.Title" = "Tilg air falbh an dreachd"; @@ -41,6 +41,7 @@ Thoir sùil air a’ cheangal agad ris an eadar-lìon."; "Common.Controls.Actions.Next" = "Air adhart"; "Common.Controls.Actions.Ok" = "Ceart ma-thà"; "Common.Controls.Actions.Open" = "Fosgail"; +"Common.Controls.Actions.OpenInBrowser" = "Fosgail sa bhrabhsair"; "Common.Controls.Actions.OpenInSafari" = "Fosgail ann an Safari"; "Common.Controls.Actions.Preview" = "Ro-sheall"; "Common.Controls.Actions.Previous" = "Air ais"; @@ -93,6 +94,7 @@ Thoir sùil air a’ cheangal agad ris an eadar-lìon."; "Common.Controls.Keyboard.Timeline.ToggleFavorite" = "Toglaich annsachd a’ phuist"; "Common.Controls.Keyboard.Timeline.ToggleReblog" = "Toglaich brosnachadh a’ phuist"; "Common.Controls.Status.Actions.Favorite" = "Cuir ris na h-annsachdan"; +"Common.Controls.Status.Actions.Hide" = "Falaich"; "Common.Controls.Status.Actions.Menu" = "Clàr-taice"; "Common.Controls.Status.Actions.Reblog" = "Brosnaich"; "Common.Controls.Status.Actions.Reply" = "Freagair"; @@ -112,6 +114,10 @@ Thoir sùil air a’ cheangal agad ris an eadar-lìon."; "Common.Controls.Status.Tag.Url" = "URL"; "Common.Controls.Status.UserReblogged" = "Tha %@ ’ga bhrosnachadh"; "Common.Controls.Status.UserRepliedTo" = "Air %@ fhreagairt"; +"Common.Controls.Status.Visibility.Direct" = "Chan fhaic ach an cleachdaiche air an dugadh iomradh am post seo."; +"Common.Controls.Status.Visibility.Private" = "Chan fhaic ach an luchd-leantainn aca am post seo."; +"Common.Controls.Status.Visibility.PrivateFromMe" = "Chan fhaic ach an luchd-leantainn agam am post seo."; +"Common.Controls.Status.Visibility.Unlisted" = "Chì a h-uile duine am post seo ach cha nochd e air an loidhne-ama phoblach."; "Common.Controls.Tabs.Home" = "Dachaigh"; "Common.Controls.Tabs.Notification" = "Brath"; "Common.Controls.Tabs.Profile" = "Pròifil"; @@ -178,8 +184,8 @@ a luchdadh suas gu Mastodon."; "Scene.Compose.Visibility.Private" = "Luchd-leantainn a-mhàin"; "Scene.Compose.Visibility.Public" = "Poblach"; "Scene.Compose.Visibility.Unlisted" = "Falaichte o liostaichean"; -"Scene.ConfirmEmail.Button.DontReceiveEmail" = "Cha d’ fhuair mi post-d a-riamh"; "Scene.ConfirmEmail.Button.OpenEmailApp" = "Fosgail aplacaid a’ phuist-d"; +"Scene.ConfirmEmail.Button.Resend" = "Ath-chuir"; "Scene.ConfirmEmail.DontReceiveEmail.Description" = "Dearbh gu bheil an seòladh puist-d agad mar bu chòir agus nach eil dad ann am pasgan an truilleis."; "Scene.ConfirmEmail.DontReceiveEmail.ResendEmail" = "Cuir am post-d a-rithist"; "Scene.ConfirmEmail.DontReceiveEmail.Title" = "Thoir sùil air a’ phost-d agad"; @@ -200,14 +206,14 @@ thoir gnogag air a’ chunntas a dhearbhadh a’ chunntais agad."; "Scene.HomeTimeline.Title" = "Dachaigh"; "Scene.Notification.Keyobard.ShowEverything" = "Seall a h-uile càil"; "Scene.Notification.Keyobard.ShowMentions" = "Seall na h-iomraidhean"; +"Scene.Notification.NotificationDescription.FavoritedYourPost" = "– ’s iad air am post agad a chur ris na h-annsachdan aca"; +"Scene.Notification.NotificationDescription.FollowedYou" = "– ’s iad ’gad leantainn a-nis"; +"Scene.Notification.NotificationDescription.MentionedYou" = "– ’s iad air iomradh a thoirt ort"; +"Scene.Notification.NotificationDescription.PollHasEnded" = "thàinig cunntas-bheachd gu crìoch"; +"Scene.Notification.NotificationDescription.RebloggedYourPost" = "– ’s iad air am post agad a bhrosnachadh"; +"Scene.Notification.NotificationDescription.RequestToFollowYou" = "iarrtas leantainn ort"; "Scene.Notification.Title.Everything" = "A h-uile rud"; "Scene.Notification.Title.Mentions" = "Iomraidhean"; -"Scene.Notification.UserFavorited Your Post" = "Is annsa le %@ am post agad"; -"Scene.Notification.UserFollowedYou" = "Tha %@ a’ leantainn ort a-nis"; -"Scene.Notification.UserMentionedYou" = "Thug %@ iomradh ort"; -"Scene.Notification.UserRebloggedYourPost" = "Bhrosnaich %@ am post agad"; -"Scene.Notification.UserRequestedToFollowYou" = "Dh’iarr %@ leantainn ort"; -"Scene.Notification.UserYourPollHasEnded" = "Crìoch cunntais-bheachd aig %@"; "Scene.Preview.Keyboard.ClosePreview" = "Dùin an ro-shealladh"; "Scene.Preview.Keyboard.ShowNext" = "Air adhart"; "Scene.Preview.Keyboard.ShowPrevious" = "Air ais"; @@ -217,12 +223,18 @@ thoir gnogag air a’ chunntas a dhearbhadh a’ chunntais agad."; "Scene.Profile.Fields.AddRow" = "Cuir ràgh ris"; "Scene.Profile.Fields.Placeholder.Content" = "Susbaint"; "Scene.Profile.Fields.Placeholder.Label" = "Leubail"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Message" = "Dearbh dì-bhacadh %@"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Title" = "Dì-bhac an cunntas"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Message" = "Dearbh bacadh %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title" = "Bac an cunntas"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Message" = "Dearbh mùchadh %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Title" = "Mùch an cunntas"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Message" = "Dearbh dì-bhacadh %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Title" = "Dì-bhac an cunntas"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Message" = "Dearbh dì-mhùchadh %@"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Title" = "Dì-mhùch an cunntas"; +"Scene.Profile.SegmentedControl.About" = "Mu dhèidhinn"; "Scene.Profile.SegmentedControl.Media" = "Meadhanan"; "Scene.Profile.SegmentedControl.Posts" = "Postaichean"; +"Scene.Profile.SegmentedControl.PostsAndReplies" = "Postaichean ’s freagairtean"; "Scene.Profile.SegmentedControl.Replies" = "Freagairtean"; "Scene.Register.Error.Item.Agreement" = "Aonta"; "Scene.Register.Error.Item.Email" = "Post-d"; @@ -248,19 +260,26 @@ thoir gnogag air a’ chunntas a dhearbhadh a’ chunntais agad."; "Scene.Register.Input.DisplayName.Placeholder" = "ainm-taisbeanaidh"; "Scene.Register.Input.Email.Placeholder" = "post-d"; "Scene.Register.Input.Invite.RegistrationUserInviteRequest" = "Carson a bu mhiann leat ballrachd fhaighinn?"; +"Scene.Register.Input.Password.Accessibility.Checked" = "le cromag"; +"Scene.Register.Input.Password.Accessibility.Unchecked" = "gun chromag"; +"Scene.Register.Input.Password.CharacterLimit" = "8 caractaran"; "Scene.Register.Input.Password.Hint" = "Feumaidh ochd caractaran a bhith san fhacal-fhaire agad air a char as giorra"; "Scene.Register.Input.Password.Placeholder" = "facal-faire"; +"Scene.Register.Input.Password.Require" = "Feumaidh am facal-faire agad co-dhiù:"; "Scene.Register.Input.Username.DuplicatePrompt" = "Tha an t-ainm-cleachdaiche seo aig cuideigin eile."; "Scene.Register.Input.Username.Placeholder" = "ainm-cleachdaiche"; "Scene.Register.Title" = "Innis dhuinn mu do dhèidhinn."; "Scene.Report.Content1" = "A bheil post sam bith eile ann a bu mhiann leat cur ris a’ ghearan?"; "Scene.Report.Content2" = "A bheil rud sam bith ann a bu mhiann leat innse dha na maoir mun ghearan seo?"; +"Scene.Report.ReportSentTitle" = "Mòran taing airson a’ ghearain, bheir sinn sùil air."; +"Scene.Report.Reported" = "CHAIDH GEARAN A DHÈANAMH"; "Scene.Report.Send" = "Cuir an gearan"; "Scene.Report.SkipToSend" = "Cuir gun bheachd ris"; "Scene.Report.Step1" = "Ceum 1 à 2"; "Scene.Report.Step2" = "Ceum 2 à 2"; "Scene.Report.TextPlaceholder" = "Sgrìobh no cuir ann beachdan a bharrachd"; "Scene.Report.Title" = "Dèan gearan mu %@"; +"Scene.Report.TitleReport" = "Dèan gearan"; "Scene.Search.Recommend.Accounts.Description" = "Saoil am bu toigh leat leantainn air na cunntasan seo?"; "Scene.Search.Recommend.Accounts.Follow" = "Lean air"; "Scene.Search.Recommend.Accounts.Title" = "Cunntasan a chòrdas riut ma dh’fhaoidte"; @@ -301,6 +320,8 @@ thoir gnogag air a’ chunntas a dhearbhadh a’ chunntais agad."; "Scene.ServerPicker.Label.Category" = "ROINN-SEÒRSA"; "Scene.ServerPicker.Label.Language" = "CÀNAN"; "Scene.ServerPicker.Label.Users" = "CLEACHDAICHEAN"; +"Scene.ServerPicker.Subtitle" = "Tagh coimhearsnachd stèidhichte air d’ ùidhean no an roinn-dùthcha agad no tè choitcheann."; +"Scene.ServerPicker.SubtitleExtend" = "Tagh coimhearsnachd stèidhichte air d’ ùidhean no an roinn-dùthcha agad no tè choitcheann. Tha gach coimhearsnachd ’ga stiùireadh le buidheann no neach gu neo-eisimeileach."; "Scene.ServerPicker.Title" = "Tagh frithealaiche sam bith."; "Scene.ServerRules.Button.Confirm" = "Gabhaidh mi ris"; "Scene.ServerRules.PrivacyPolicy" = "poileasaidh prìobhaideachd"; @@ -318,6 +339,11 @@ thoir gnogag air a’ chunntas a dhearbhadh a’ chunntais agad."; "Scene.Settings.Section.BoringZone.Privacy" = "Am poileasaidh prìobhaideachd"; "Scene.Settings.Section.BoringZone.Terms" = "Teirmichean na seirbheise"; "Scene.Settings.Section.BoringZone.Title" = "An earrann ràsanach"; +"Scene.Settings.Section.LookAndFeel.Light" = "Soilleir"; +"Scene.Settings.Section.LookAndFeel.ReallyDark" = "Glè dhorcha"; +"Scene.Settings.Section.LookAndFeel.SortaDark" = "Caran dorcha"; +"Scene.Settings.Section.LookAndFeel.Title" = "Coltas"; +"Scene.Settings.Section.LookAndFeel.UseSystem" = "Cleachd coltas an t-siostaim"; "Scene.Settings.Section.Notifications.Boosts" = "Nuair a bhrosnaicheas iad post uam"; "Scene.Settings.Section.Notifications.Favorites" = "Nuair as annsa leotha am post agam"; "Scene.Settings.Section.Notifications.Follows" = "Nuair a leanas iad orm"; @@ -341,6 +367,8 @@ thoir gnogag air a’ chunntas a dhearbhadh a’ chunntais agad."; "Scene.SuggestionAccount.Title" = "Lorg daoine a leanas tu"; "Scene.Thread.BackTitle" = "Post"; "Scene.Thread.Title" = "Post le %@"; +"Scene.Welcome.GetStarted" = "Dèan toiseach-tòiseachaidh"; +"Scene.Welcome.LogIn" = "Clàraich a-steach"; "Scene.Welcome.Slogan" = "A’ cur nan lìonraidhean sòisealta ’nad làmhan fhèin."; "Scene.Wizard.AccessibilityHint" = "Thoir gnogag dhùbailte a’ leigeil seachad an draoidh seo"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/ja.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/ja.lproj/Localizable.strings index 98bf7163..cb037936 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/ja.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/ja.lproj/Localizable.strings @@ -4,14 +4,14 @@ "Common.Alerts.CleanCache.Title" = "キャッシュを消去"; "Common.Alerts.Common.PleaseTryAgain" = "もう一度お試しください。"; "Common.Alerts.Common.PleaseTryAgainLater" = "後でもう一度お試しください。"; -"Common.Alerts.DeletePost.Delete" = "消去"; +"Common.Alerts.DeletePost.Message" = "本当に削除しますか?"; "Common.Alerts.DeletePost.Title" = "この投稿を消去しますか?"; "Common.Alerts.DiscardPostContent.Message" = "この操作は取り消しできません。下書きは失われます。"; "Common.Alerts.DiscardPostContent.Title" = "投稿を破棄しますか?"; "Common.Alerts.EditProfileFailure.Message" = "プロフィールを編集できません。もう一度お試しください。"; "Common.Alerts.EditProfileFailure.Title" = "プロフィールを編集できませんでした"; "Common.Alerts.PublishPostFailure.AttachmentsMessage.MoreThanOneVideo" = "複数の動画を添付することはできません。"; -"Common.Alerts.PublishPostFailure.AttachmentsMessage.VideoAttachWithPhoto" = "すでに画像が含まれている投稿に、動画を添付することができません。"; +"Common.Alerts.PublishPostFailure.AttachmentsMessage.VideoAttachWithPhoto" = "すでに画像が含まれている投稿に、動画を添付することはできません。"; "Common.Alerts.PublishPostFailure.Message" = "投稿に失敗しました。 インターネットに接続されているか確認してください。"; "Common.Alerts.PublishPostFailure.Title" = "失敗"; @@ -28,7 +28,7 @@ "Common.Controls.Actions.Back" = "戻る"; "Common.Controls.Actions.BlockDomain" = "%@をブロック"; "Common.Controls.Actions.Cancel" = "キャンセル"; -"Common.Controls.Actions.Compose" = "Compose"; +"Common.Controls.Actions.Compose" = "新規作成"; "Common.Controls.Actions.Confirm" = "確認"; "Common.Controls.Actions.Continue" = "続ける"; "Common.Controls.Actions.CopyPhoto" = "写真をコピー"; @@ -41,12 +41,13 @@ "Common.Controls.Actions.Next" = "次"; "Common.Controls.Actions.Ok" = "OK"; "Common.Controls.Actions.Open" = "開く"; +"Common.Controls.Actions.OpenInBrowser" = "ブラウザで開く"; "Common.Controls.Actions.OpenInSafari" = "Safariで開く"; "Common.Controls.Actions.Preview" = "プレビュー"; "Common.Controls.Actions.Previous" = "前"; "Common.Controls.Actions.Remove" = "消去"; "Common.Controls.Actions.Reply" = "リプライ"; -"Common.Controls.Actions.ReportUser" = "%@を報告"; +"Common.Controls.Actions.ReportUser" = "%@を通報"; "Common.Controls.Actions.Save" = "保存"; "Common.Controls.Actions.SavePhoto" = "写真を撮る"; "Common.Controls.Actions.SeeMore" = "もっと見る"; @@ -93,6 +94,7 @@ "Common.Controls.Keyboard.Timeline.ToggleFavorite" = "お気に入り登録を切り替える"; "Common.Controls.Keyboard.Timeline.ToggleReblog" = "ブーストを切り替える"; "Common.Controls.Status.Actions.Favorite" = "お気に入り"; +"Common.Controls.Status.Actions.Hide" = "非表示"; "Common.Controls.Status.Actions.Menu" = "メニュー"; "Common.Controls.Status.Actions.Reblog" = "ブースト"; "Common.Controls.Status.Actions.Reply" = "リプライ"; @@ -112,6 +114,10 @@ "Common.Controls.Status.Tag.Url" = "URL"; "Common.Controls.Status.UserReblogged" = "%@がブースト"; "Common.Controls.Status.UserRepliedTo" = "%@がリプライ"; +"Common.Controls.Status.Visibility.Direct" = "この投稿はメンションされたユーザーに限り見ることができます。"; +"Common.Controls.Status.Visibility.Private" = "この投稿はフォロワーに限り見ることができます。"; +"Common.Controls.Status.Visibility.PrivateFromMe" = "この投稿はフォロワーに限り見ることができます。"; +"Common.Controls.Status.Visibility.Unlisted" = "この投稿は誰でも見ることができますが、公開タイムラインには表示されません。"; "Common.Controls.Tabs.Home" = "ホーム"; "Common.Controls.Tabs.Notification" = "通知"; "Common.Controls.Tabs.Profile" = "プロフィール"; @@ -131,8 +137,8 @@ "Common.Controls.Timeline.Loader.ShowMoreReplies" = "リプライをもっとみる"; "Common.Controls.Timeline.Timestamp.Now" = "今"; "Scene.AccountList.AddAccount" = "アカウントを追加"; -"Scene.AccountList.DismissAccountSwitcher" = "Dismiss Account Switcher"; -"Scene.AccountList.TabBarHint" = "Current selected profile: %@. Double tap then hold to show account switcher"; +"Scene.AccountList.DismissAccountSwitcher" = "アカウント切替画面を閉じます"; +"Scene.AccountList.TabBarHint" = "現在のアカウント: %@. ダブルタップしてアカウント切替画面を表示します"; "Scene.Compose.Accessibility.AppendAttachment" = "アタッチメントの追加"; "Scene.Compose.Accessibility.AppendPoll" = "投票を追加"; "Scene.Compose.Accessibility.CustomEmojiPicker" = "カスタム絵文字ピッカー"; @@ -141,8 +147,8 @@ "Scene.Compose.Accessibility.PostVisibilityMenu" = "投稿の表示メニュー"; "Scene.Compose.Accessibility.RemovePoll" = "投票を消去"; "Scene.Compose.Attachment.AttachmentBroken" = "%@は壊れていてMastodonにアップロードできません。"; -"Scene.Compose.Attachment.DescriptionPhoto" = "視覚障がい者のために写真を説明"; -"Scene.Compose.Attachment.DescriptionVideo" = "視覚障がい者のための映像の説明"; +"Scene.Compose.Attachment.DescriptionPhoto" = "閲覧が難しいユーザーへの画像説明"; +"Scene.Compose.Attachment.DescriptionVideo" = "閲覧が難しいユーザーへの映像説明"; "Scene.Compose.Attachment.Photo" = "写真"; "Scene.Compose.Attachment.Video" = "動画"; "Scene.Compose.AutoComplete.SpaceToAdd" = "スペースを追加"; @@ -173,8 +179,8 @@ "Scene.Compose.Visibility.Private" = "フォロワーのみ"; "Scene.Compose.Visibility.Public" = "パブリック"; "Scene.Compose.Visibility.Unlisted" = "非表示"; -"Scene.ConfirmEmail.Button.DontReceiveEmail" = "メールがこない"; "Scene.ConfirmEmail.Button.OpenEmailApp" = "メールアプリを開く"; +"Scene.ConfirmEmail.Button.Resend" = "Resend"; "Scene.ConfirmEmail.DontReceiveEmail.Description" = "メールアドレスが正しいかどうか、また、迷惑メールフォルダに入っていないかどうかも確認してください。"; "Scene.ConfirmEmail.DontReceiveEmail.ResendEmail" = "もう一度メールを送信"; "Scene.ConfirmEmail.DontReceiveEmail.Title" = "メールをチェックしてください"; @@ -185,8 +191,8 @@ "Scene.ConfirmEmail.Subtitle" = "先程 %@ にメールを送信しました。リンクをタップしてアカウントを確認してください。"; "Scene.ConfirmEmail.Title" = "さいごにもうひとつ。"; "Scene.Favorite.Title" = "お気に入り"; -"Scene.Follower.Footer" = "Followers from other servers are not displayed."; -"Scene.Following.Footer" = "Follows from other servers are not displayed."; +"Scene.Follower.Footer" = "他のサーバーからのフォロワーは表示されません。"; +"Scene.Following.Footer" = "他のサーバーにいるフォローは表示されません。"; "Scene.HomeTimeline.NavigationBarState.NewPosts" = "新しい投稿を見る"; "Scene.HomeTimeline.NavigationBarState.Offline" = "オフライン"; "Scene.HomeTimeline.NavigationBarState.Published" = "投稿しました!"; @@ -194,14 +200,14 @@ "Scene.HomeTimeline.Title" = "ホーム"; "Scene.Notification.Keyobard.ShowEverything" = "すべて見る"; "Scene.Notification.Keyobard.ShowMentions" = "メンションを見る"; +"Scene.Notification.NotificationDescription.FavoritedYourPost" = "favorited your post"; +"Scene.Notification.NotificationDescription.FollowedYou" = "followed you"; +"Scene.Notification.NotificationDescription.MentionedYou" = "mentioned you"; +"Scene.Notification.NotificationDescription.PollHasEnded" = "poll has ended"; +"Scene.Notification.NotificationDescription.RebloggedYourPost" = "reblogged your post"; +"Scene.Notification.NotificationDescription.RequestToFollowYou" = "request to follow you"; "Scene.Notification.Title.Everything" = "すべて"; "Scene.Notification.Title.Mentions" = "メンション"; -"Scene.Notification.UserFavorited Your Post" = "%@ がお気に入り登録しました"; -"Scene.Notification.UserFollowedYou" = "%@ にフォローされました"; -"Scene.Notification.UserMentionedYou" = "%@ に返信されました"; -"Scene.Notification.UserRebloggedYourPost" = "%@ がブーストしました"; -"Scene.Notification.UserRequestedToFollowYou" = "%@ がフォローリクエストを送信しました"; -"Scene.Notification.UserYourPollHasEnded" = "%@ 投票が終了しました"; "Scene.Preview.Keyboard.ClosePreview" = "プレビューを閉じる"; "Scene.Preview.Keyboard.ShowNext" = "次を見る"; "Scene.Preview.Keyboard.ShowPrevious" = "前を見る"; @@ -211,12 +217,18 @@ "Scene.Profile.Fields.AddRow" = "行追加"; "Scene.Profile.Fields.Placeholder.Content" = "コンテンツ"; "Scene.Profile.Fields.Placeholder.Label" = "ラベル"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Message" = "%@のブロックを解除しますか?"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Title" = "ブロックを解除"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Message" = "Confirm to block %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title" = "Block Account"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Message" = "Confirm to mute %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Title" = "Mute Account"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Message" = "Confirm to unblock %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Title" = "Unblock Account"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Message" = "%@をミュートしますか?"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Title" = "ミュートを解除"; +"Scene.Profile.SegmentedControl.About" = "About"; "Scene.Profile.SegmentedControl.Media" = "メディア"; "Scene.Profile.SegmentedControl.Posts" = "投稿"; +"Scene.Profile.SegmentedControl.PostsAndReplies" = "Posts and Replies"; "Scene.Profile.SegmentedControl.Replies" = "リプライ"; "Scene.Register.Error.Item.Agreement" = "契約"; "Scene.Register.Error.Item.Email" = "メール"; @@ -242,19 +254,26 @@ "Scene.Register.Input.DisplayName.Placeholder" = "表示名"; "Scene.Register.Input.Email.Placeholder" = "メール"; "Scene.Register.Input.Invite.RegistrationUserInviteRequest" = "なぜ参加したいと思ったのですか?"; +"Scene.Register.Input.Password.Accessibility.Checked" = "checked"; +"Scene.Register.Input.Password.Accessibility.Unchecked" = "unchecked"; +"Scene.Register.Input.Password.CharacterLimit" = "8 characters"; "Scene.Register.Input.Password.Hint" = "パスワードは最低でも8文字必要です。"; "Scene.Register.Input.Password.Placeholder" = "パスワード"; +"Scene.Register.Input.Password.Require" = "Your password needs at least:"; "Scene.Register.Input.Username.DuplicatePrompt" = "このユーザー名は使用されています"; "Scene.Register.Input.Username.Placeholder" = "ユーザー名"; "Scene.Register.Title" = "あなたのことを教えてください"; -"Scene.Report.Content1" = "他に報告したい投稿はありますか?"; -"Scene.Report.Content2" = "この報告についてモデレーターに言いたいことはありますか?"; -"Scene.Report.Send" = "報告を送信"; +"Scene.Report.Content1" = "他に通報したい投稿はありますか?"; +"Scene.Report.Content2" = "この通報についてモデレーターに伝達しておきたい事項はありますか?"; +"Scene.Report.ReportSentTitle" = "Thanks for reporting, we’ll look into this."; +"Scene.Report.Reported" = "REPORTED"; +"Scene.Report.Send" = "通報を送信"; "Scene.Report.SkipToSend" = "コメントなしで送信"; "Scene.Report.Step1" = "ステップ 1/2"; "Scene.Report.Step2" = "ステップ 2/2"; "Scene.Report.TextPlaceholder" = "追加コメントを入力"; -"Scene.Report.Title" = "%@を報告"; +"Scene.Report.Title" = "%@を通報"; +"Scene.Report.TitleReport" = "Report"; "Scene.Search.Recommend.Accounts.Description" = "以下のアカウントをフォローしてみてはいかがでしょうか?"; "Scene.Search.Recommend.Accounts.Follow" = "フォロー"; "Scene.Search.Recommend.Accounts.Title" = "おすすめのアカウント"; @@ -278,7 +297,7 @@ "Scene.ServerPicker.Button.Category.AllAccessiblityDescription" = "カテゴリ: すべて"; "Scene.ServerPicker.Button.Category.Art" = "アート"; "Scene.ServerPicker.Button.Category.Food" = "食べ物"; -"Scene.ServerPicker.Button.Category.Furry" = "furry"; +"Scene.ServerPicker.Button.Category.Furry" = "ケモノ"; "Scene.ServerPicker.Button.Category.Games" = "ゲーム"; "Scene.ServerPicker.Button.Category.General" = "全般"; "Scene.ServerPicker.Button.Category.Journalism" = "言論"; @@ -295,6 +314,8 @@ "Scene.ServerPicker.Label.Category" = "カテゴリー"; "Scene.ServerPicker.Label.Language" = "言語"; "Scene.ServerPicker.Label.Users" = "ユーザー"; +"Scene.ServerPicker.Subtitle" = "あなたの興味分野・地域に合ったコミュニティや、汎用のものを選択してください。"; +"Scene.ServerPicker.SubtitleExtend" = "あなたの興味分野・地域に合ったコミュニティや、汎用のものを選択してください。各コミュニティはそれぞれ完全に独立した組織や個人によって運営されています。"; "Scene.ServerPicker.Title" = "サーバーを選択"; "Scene.ServerRules.Button.Confirm" = "同意する"; "Scene.ServerRules.PrivacyPolicy" = "プライバシーポリシー"; @@ -312,6 +333,11 @@ "Scene.Settings.Section.BoringZone.Privacy" = "プライバシーポリシー"; "Scene.Settings.Section.BoringZone.Terms" = "利用規約"; "Scene.Settings.Section.BoringZone.Title" = "アプリについて"; +"Scene.Settings.Section.LookAndFeel.Light" = "Light"; +"Scene.Settings.Section.LookAndFeel.ReallyDark" = "Really Dark"; +"Scene.Settings.Section.LookAndFeel.SortaDark" = "Sorta Dark"; +"Scene.Settings.Section.LookAndFeel.Title" = "Look and Feel"; +"Scene.Settings.Section.LookAndFeel.UseSystem" = "Use System"; "Scene.Settings.Section.Notifications.Boosts" = "ブースト"; "Scene.Settings.Section.Notifications.Favorites" = "お気に入り登録"; "Scene.Settings.Section.Notifications.Follows" = "フォロー"; @@ -322,7 +348,7 @@ "Scene.Settings.Section.Notifications.Trigger.Follower" = "フォロワー"; "Scene.Settings.Section.Notifications.Trigger.Noone" = "なし"; "Scene.Settings.Section.Notifications.Trigger.Title" = "通知を受け取る"; -"Scene.Settings.Section.Preference.DisableAvatarAnimation" = "アニメーションアバターの無効化する"; +"Scene.Settings.Section.Preference.DisableAvatarAnimation" = "アバターのアニメーションを無効化する"; "Scene.Settings.Section.Preference.DisableEmojiAnimation" = "絵文字のアニメーションを無効化する"; "Scene.Settings.Section.Preference.Title" = "環境設定"; "Scene.Settings.Section.Preference.TrueBlackDarkMode" = "真っ黒なダークテーマを使用する"; @@ -335,7 +361,9 @@ "Scene.SuggestionAccount.Title" = "フォローする人を探す"; "Scene.Thread.BackTitle" = "投稿"; "Scene.Thread.Title" = "%@の投稿"; +"Scene.Welcome.GetStarted" = "Get Started"; +"Scene.Welcome.LogIn" = "ログイン"; "Scene.Welcome.Slogan" = "ソーシャルネットワーキングを、あなたの手の中に."; -"Scene.Wizard.AccessibilityHint" = "Double tap to dismiss this wizard"; +"Scene.Wizard.AccessibilityHint" = "チュートリアルを閉じるには、ダブルタップしてください"; "Scene.Wizard.MultipleAccountSwitchIntroDescription" = "プロフィールボタンを押して複数のアカウントを切り替えます。"; "Scene.Wizard.NewInMastodon" = "Mastodon の新機能"; \ No newline at end of file diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/ja.lproj/Localizable.stringsdict b/MastodonSDK/Sources/MastodonLocalization/Resources/ja.lproj/Localizable.stringsdict index c51a9a29..f1c5e6e2 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/ja.lproj/Localizable.stringsdict +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/ja.lproj/Localizable.stringsdict @@ -279,7 +279,7 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>other</key> - <string>%ld分前</string> + <string>%ldか月前</string> </dict> </dict> <key>date.day.ago.abbr</key> diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/ku-TR.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/ku-TR.lproj/Localizable.strings index d0d0f294..6e629cb0 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/ku-TR.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/ku-TR.lproj/Localizable.strings @@ -4,8 +4,8 @@ "Common.Alerts.CleanCache.Title" = "Pêşbîrê pak bike"; "Common.Alerts.Common.PleaseTryAgain" = "Ji kerema xwe dîsa biceribîne."; "Common.Alerts.Common.PleaseTryAgainLater" = "Ji kerema xwe paşê dîsa biceribîne."; -"Common.Alerts.DeletePost.Delete" = "Jê bibe"; -"Common.Alerts.DeletePost.Title" = "Ma tu dixwazî vê şandiyê jê bibî?"; +"Common.Alerts.DeletePost.Message" = "Ma tu dixwazî vê şandiyê jê bibî?"; +"Common.Alerts.DeletePost.Title" = "Şandiyê jê bibe"; "Common.Alerts.DiscardPostContent.Message" = "Bipejrîne ku naveroka şandiyê ya hatiye nivîsandin paşguh bikî."; "Common.Alerts.DiscardPostContent.Title" = "Reşnivîsê paşguh bike"; "Common.Alerts.EditProfileFailure.Message" = "Nikare profîlê serrast bike. Jkx dîsa biceribîne."; @@ -41,6 +41,7 @@ Jkx girêdana înternetê xwe kontrol bike."; "Common.Controls.Actions.Next" = "Pêş"; "Common.Controls.Actions.Ok" = "BAŞ E"; "Common.Controls.Actions.Open" = "Veke"; +"Common.Controls.Actions.OpenInBrowser" = "Di gerokê de veke"; "Common.Controls.Actions.OpenInSafari" = "Di Safariyê de veke"; "Common.Controls.Actions.Preview" = "Pêşdîtin"; "Common.Controls.Actions.Previous" = "Paş"; @@ -91,8 +92,9 @@ Jkx girêdana înternetê xwe kontrol bike."; "Common.Controls.Keyboard.Timeline.ReplyStatus" = "Bersivê bide şandiyê"; "Common.Controls.Keyboard.Timeline.ToggleContentWarning" = "Hişyariya naverokê biguherîne"; "Common.Controls.Keyboard.Timeline.ToggleFavorite" = "Li ser şandiyê bijarte biguherîne"; -"Common.Controls.Keyboard.Timeline.ToggleReblog" = "Ji vû nivîsandin di şandiyê de biguherîne"; +"Common.Controls.Keyboard.Timeline.ToggleReblog" = "Ji nû ve nivîsandin di şandiyê de biguherîne"; "Common.Controls.Status.Actions.Favorite" = "Bijarte"; +"Common.Controls.Status.Actions.Hide" = "Veşêre"; "Common.Controls.Status.Actions.Menu" = "Kulîn"; "Common.Controls.Status.Actions.Reblog" = "Ji nû ve nivîsandin"; "Common.Controls.Status.Actions.Reply" = "Bersivê bide"; @@ -110,8 +112,12 @@ Jkx girêdana înternetê xwe kontrol bike."; "Common.Controls.Status.Tag.Link" = "Girêdan"; "Common.Controls.Status.Tag.Mention" = "Qalkirin"; "Common.Controls.Status.Tag.Url" = "URL"; -"Common.Controls.Status.UserReblogged" = "%@ ji nû ve hate nivîsandin"; +"Common.Controls.Status.UserReblogged" = "%@ ji nû ve nivîsand"; "Common.Controls.Status.UserRepliedTo" = "Bersiv da %@"; +"Common.Controls.Status.Visibility.Direct" = "Tenê bikarhênerê qalkirî dikare vê şandiyê bibîne."; +"Common.Controls.Status.Visibility.Private" = "Tenê şopînerên wan dikarin vê şandiyê bibînin."; +"Common.Controls.Status.Visibility.PrivateFromMe" = "Tenê şopînerên min dikarin vê şandiyê bibînin."; +"Common.Controls.Status.Visibility.Unlisted" = "Her kes dikare vê şandiyê bibîne lê nayê nîşandan di demnameya gelemperî de."; "Common.Controls.Tabs.Home" = "Serrûpel"; "Common.Controls.Tabs.Notification" = "Agahdarî"; "Common.Controls.Tabs.Profile" = "Profîl"; @@ -178,8 +184,8 @@ Profîla te ji wan ra wiha xuya dike."; "Scene.Compose.Visibility.Private" = "Tenê şopîneran"; "Scene.Compose.Visibility.Public" = "Gelemperî"; "Scene.Compose.Visibility.Unlisted" = "Nerêzokkirî"; -"Scene.ConfirmEmail.Button.DontReceiveEmail" = "Min hîç e-nameyeke nesitand"; "Scene.ConfirmEmail.Button.OpenEmailApp" = "Sepana e-nameyê veke"; +"Scene.ConfirmEmail.Button.Resend" = "Ji nû ve bişîne"; "Scene.ConfirmEmail.DontReceiveEmail.Description" = "Kontrol bike ka navnîşana e-nameya te rast e û her wiha peldanka xwe ya spam."; "Scene.ConfirmEmail.DontReceiveEmail.ResendEmail" = "E-namyê yê dîsa bişîne"; "Scene.ConfirmEmail.DontReceiveEmail.Title" = "E-nameyê xwe kontrol bike"; @@ -200,14 +206,14 @@ girêdanê bitikne da ku ajimêra xwe bidî piştrastkirin."; "Scene.HomeTimeline.Title" = "Serrûpel"; "Scene.Notification.Keyobard.ShowEverything" = "Her tiştî nîşan bide"; "Scene.Notification.Keyobard.ShowMentions" = "Qalkirinan nîşan bike"; +"Scene.Notification.NotificationDescription.FavoritedYourPost" = "şandiya te hez kir"; +"Scene.Notification.NotificationDescription.FollowedYou" = "te şopand"; +"Scene.Notification.NotificationDescription.MentionedYou" = "qale te kir"; +"Scene.Notification.NotificationDescription.PollHasEnded" = "rapirsî qediya"; +"Scene.Notification.NotificationDescription.RebloggedYourPost" = "şandiya te ji nû ve nivisand"; +"Scene.Notification.NotificationDescription.RequestToFollowYou" = "dixwazê te bişopîne"; "Scene.Notification.Title.Everything" = "Her tişt"; "Scene.Notification.Title.Mentions" = "Qalkirin"; -"Scene.Notification.UserFavorited Your Post" = "%@ şandiya te hez kir"; -"Scene.Notification.UserFollowedYou" = "%@ te şopand"; -"Scene.Notification.UserMentionedYou" = "%@ qale te kir"; -"Scene.Notification.UserRebloggedYourPost" = "%@ posta we ji nû ve tomar kir"; -"Scene.Notification.UserRequestedToFollowYou" = "%@ dixwazê te bişopîne"; -"Scene.Notification.UserYourPollHasEnded" = "Rapirsîya te qediya"; "Scene.Preview.Keyboard.ClosePreview" = "Pêşdîtin bigire"; "Scene.Preview.Keyboard.ShowNext" = "A pêş nîşan bide"; "Scene.Preview.Keyboard.ShowPrevious" = "A paş nîşan bide"; @@ -217,12 +223,18 @@ girêdanê bitikne da ku ajimêra xwe bidî piştrastkirin."; "Scene.Profile.Fields.AddRow" = "Rêzê tevlî bike"; "Scene.Profile.Fields.Placeholder.Content" = "Naverok"; "Scene.Profile.Fields.Placeholder.Label" = "Nîşan"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Message" = "Ji bo rakirina astengkirinê bipejirîne %@"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Title" = "Astengiyê li ser ajimêr rake"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Message" = "Ji bo vekirina bêdengkirinê bipejirîne %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Message" = "Ji bo rakirina astengkirinê %@ bipejirîne"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title" = "Ajimêr asteng bike"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Message" = "Ji bo bêdengkirina %@ bipejirîne"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Title" = "Ajimêrê bêdeng bike"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Message" = "Ji bo rakirina astengkirinê %@ bipejirîne"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Title" = "Astengiyê li ser ajimêr rake"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Message" = "Ji bo vekirina bêdengkirinê %@ bipejirîne"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Title" = "Ajimêrê bêdeng neke"; +"Scene.Profile.SegmentedControl.About" = "Derbar"; "Scene.Profile.SegmentedControl.Media" = "Medya"; "Scene.Profile.SegmentedControl.Posts" = "Şandî"; +"Scene.Profile.SegmentedControl.PostsAndReplies" = "Şandî û bersiv"; "Scene.Profile.SegmentedControl.Replies" = "Bersiv"; "Scene.Register.Error.Item.Agreement" = "Peyman"; "Scene.Register.Error.Item.Email" = "E-name"; @@ -248,19 +260,26 @@ girêdanê bitikne da ku ajimêra xwe bidî piştrastkirin."; "Scene.Register.Input.DisplayName.Placeholder" = "navê nîşanê"; "Scene.Register.Input.Email.Placeholder" = "e-name"; "Scene.Register.Input.Invite.RegistrationUserInviteRequest" = "Tu çima dixwazî beşdar bibî?"; +"Scene.Register.Input.Password.Accessibility.Checked" = "hate kontrolkirin"; +"Scene.Register.Input.Password.Accessibility.Unchecked" = "nehate kontrolkirin"; +"Scene.Register.Input.Password.CharacterLimit" = "8 tîp"; "Scene.Register.Input.Password.Hint" = "Pêborîna te herî kêm divê ji 8 tîpan pêk bê"; "Scene.Register.Input.Password.Placeholder" = "pêborîn"; +"Scene.Register.Input.Password.Require" = "Pêdiviya pêborîna te ya herî kêm:"; "Scene.Register.Input.Username.DuplicatePrompt" = "Navê vê bikarhêner tê girtin."; "Scene.Register.Input.Username.Placeholder" = "navê bikarhêner"; -"Scene.Register.Title" = "Ji me re hinekî qala xwe bike."; +"Scene.Register.Title" = "Ji me re hinekî qala xwe bike %@"; "Scene.Report.Content1" = "Şandiyên din hene ku tu dixwazî tevlî ragihandinê bikî?"; "Scene.Report.Content2" = "Derbarê vê ragihandinê de tiştek heye ku divê çavdêr bizanin?"; +"Scene.Report.ReportSentTitle" = "Spas ji bo ragihandina te, em ê binirxînin."; +"Scene.Report.Reported" = "HATE RAGIHANDIN"; "Scene.Report.Send" = "Ragihandinê bişîne"; "Scene.Report.SkipToSend" = "Bêyî şirove bişîne"; "Scene.Report.Step1" = "Gav 1 ji 2"; "Scene.Report.Step2" = "Gav 2 ji 2"; "Scene.Report.TextPlaceholder" = "Şiroveyên daxwazkirê binivîsine an jî pê ve bike"; "Scene.Report.Title" = "%@ ragihîne"; +"Scene.Report.TitleReport" = "Ragihandin"; "Scene.Search.Recommend.Accounts.Description" = "Dibe ku tu bixwazî van ajimêran bişopînî"; "Scene.Search.Recommend.Accounts.Follow" = "Bişopîne"; "Scene.Search.Recommend.Accounts.Title" = "Ajimêrên ku belkî tu jê hez bikî"; @@ -301,12 +320,14 @@ girêdanê bitikne da ku ajimêra xwe bidî piştrastkirin."; "Scene.ServerPicker.Label.Category" = "BEŞ"; "Scene.ServerPicker.Label.Language" = "ZIMAN"; "Scene.ServerPicker.Label.Users" = "BIKARHÊNER"; +"Scene.ServerPicker.Subtitle" = "Li gorî berjewendî, herêm, an jî armancek gelemperî civakekê hilbijêre."; +"Scene.ServerPicker.SubtitleExtend" = "Li gorî berjewendî, herêm, an jî armancek gelemperî civakekê hilbijêre. Her civakek ji hêla rêxistinek an kesek bi tevahî serbixwe ve tê xebitandin."; "Scene.ServerPicker.Title" = "Rajekarekê hilbijêre, Her kîjan rajekar be."; "Scene.ServerRules.Button.Confirm" = "Ez dipejirînim"; "Scene.ServerRules.PrivacyPolicy" = "polîtikaya nihêniyê"; "Scene.ServerRules.Prompt" = "Bi domandinê, tu ji bo %@ di bin mercên bikaranînê û polîtîkaya nepenîtiyê dipejirînî."; -"Scene.ServerRules.Subtitle" = "Ev rêzik ji aliyê rêvebirên %@ ve tên sazkirin."; +"Scene.ServerRules.Subtitle" = "Ev rêzik ji aliyê çavdêrên %@ ve tên sazkirin."; "Scene.ServerRules.TermsOfService" = "mercên bikaranînê"; "Scene.ServerRules.Title" = "Hinek rêzikên bingehîn."; "Scene.Settings.Footer.MastodonDescription" = "Mastodon nermalava çavkaniya vekirî ye. Tu dikarî pirsgirêkan li ser GitHub-ê ragihînî di %@ (%@) de"; @@ -319,6 +340,11 @@ Her kîjan rajekar be."; "Scene.Settings.Section.BoringZone.Privacy" = "Polîtikaya nihêniyê"; "Scene.Settings.Section.BoringZone.Terms" = "Mercên bikaranînê"; "Scene.Settings.Section.BoringZone.Title" = "Devera acizker"; +"Scene.Settings.Section.LookAndFeel.Light" = "Ron"; +"Scene.Settings.Section.LookAndFeel.ReallyDark" = "Tarî"; +"Scene.Settings.Section.LookAndFeel.SortaDark" = "Hinekî tarî"; +"Scene.Settings.Section.LookAndFeel.Title" = "Xuyang"; +"Scene.Settings.Section.LookAndFeel.UseSystem" = "Pergalê bi kar bîne"; "Scene.Settings.Section.Notifications.Boosts" = "Şandiya min ji nû ve nivîsand"; "Scene.Settings.Section.Notifications.Favorites" = "Şandiyên min hez kir"; "Scene.Settings.Section.Notifications.Follows" = "Min dişopîne"; @@ -342,6 +368,8 @@ Her kîjan rajekar be."; "Scene.SuggestionAccount.Title" = "Kesên bo ku bişopînî bibîne"; "Scene.Thread.BackTitle" = "Şandî"; "Scene.Thread.Title" = "Şandî ji %@"; +"Scene.Welcome.GetStarted" = "Dest pê bike"; +"Scene.Welcome.LogIn" = "Têkeve"; "Scene.Welcome.Slogan" = "Torên civakî di destên te de."; "Scene.Wizard.AccessibilityHint" = "Du caran bitikîne da ku çarçoveyahilpekok ji holê rakî"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/ku.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/ku.lproj/Localizable.strings new file mode 100644 index 00000000..02c8be66 --- /dev/null +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/ku.lproj/Localizable.strings @@ -0,0 +1,377 @@ +"Common.Alerts.BlockDomain.BlockEntireDomain" = "Navperê asteng bike"; +"Common.Alerts.BlockDomain.Title" = "Tu ji xwe bawerî, bi rastî tu dixwazî hemû %@ 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."; +"Common.Alerts.CleanCache.Message" = "Pêşbîra %@ biserketî hate pakkirin."; +"Common.Alerts.CleanCache.Title" = "Pêşbîrê pak bike"; +"Common.Alerts.Common.PleaseTryAgain" = "Ji kerema xwe dîsa biceribîne."; +"Common.Alerts.Common.PleaseTryAgainLater" = "Ji kerema xwe paşê dîsa biceribîne."; +"Common.Alerts.DeletePost.Message" = "Ma tu dixwazî vê şandiyê jê bibî?"; +"Common.Alerts.DeletePost.Title" = "Şandiyê jê bibe"; +"Common.Alerts.DiscardPostContent.Message" = "Bipejrîne ku naveroka şandiyê ya hatiye nivîsandin paşguh bikî."; +"Common.Alerts.DiscardPostContent.Title" = "Reşnivîsê paşguh bike"; +"Common.Alerts.EditProfileFailure.Message" = "Nikare profîlê serrast bike. Jkx dîsa biceribîne."; +"Common.Alerts.EditProfileFailure.Title" = "Di serrastkirina profîlê çewtî"; +"Common.Alerts.PublishPostFailure.AttachmentsMessage.MoreThanOneVideo" = "Nikare ji bêtirî yek vîdyoyekê tevlî şandiyê bike."; +"Common.Alerts.PublishPostFailure.AttachmentsMessage.VideoAttachWithPhoto" = "Nikare vîdyoyekê tevlî şandiyê ku berê wêne tê de heye bike."; +"Common.Alerts.PublishPostFailure.Message" = "Weşandina şandiyê têkçû. +Jkx girêdana înternetê xwe kontrol bike."; +"Common.Alerts.PublishPostFailure.Title" = "Weşandin têkçû"; +"Common.Alerts.SavePhotoFailure.Message" = "Ji kerema xwe mafê bide gihîştina wênegehê çalak bike da ku wêne werin tomarkirin."; +"Common.Alerts.SavePhotoFailure.Title" = "Tomarkirina wêneyê têkçû"; +"Common.Alerts.ServerError.Title" = "Çewtiya rajekar"; +"Common.Alerts.SignOut.Confirm" = "Derkeve"; +"Common.Alerts.SignOut.Message" = "Ma tu dixwazî ku derkevî?"; +"Common.Alerts.SignOut.Title" = "Derkeve"; +"Common.Alerts.SignUpFailure.Title" = "Tomarkirin têkçû"; +"Common.Alerts.VoteFailure.PollEnded" = "Rapirsîya qediya"; +"Common.Alerts.VoteFailure.Title" = "Dengdayîn têkçû"; +"Common.Controls.Actions.Add" = "Tevlî bike"; +"Common.Controls.Actions.Back" = "Vegere"; +"Common.Controls.Actions.BlockDomain" = "%@ asteng bike"; +"Common.Controls.Actions.Cancel" = "Dev jê berde"; +"Common.Controls.Actions.Compose" = "Binivîsîne"; +"Common.Controls.Actions.Confirm" = "Bipejirîne"; +"Common.Controls.Actions.Continue" = "Bidomîne"; +"Common.Controls.Actions.CopyPhoto" = "Wêneyê jê bigire"; +"Common.Controls.Actions.Delete" = "Jê bibe"; +"Common.Controls.Actions.Discard" = "Biavêje"; +"Common.Controls.Actions.Done" = "Qediya"; +"Common.Controls.Actions.Edit" = "Serrast bike"; +"Common.Controls.Actions.FindPeople" = "Mirovan bo şopandinê bibîne"; +"Common.Controls.Actions.ManuallySearch" = "Ji devlê bi destan lêgerînê bike"; +"Common.Controls.Actions.Next" = "Pêş"; +"Common.Controls.Actions.Ok" = "BAŞ E"; +"Common.Controls.Actions.Open" = "Veke"; +"Common.Controls.Actions.OpenInBrowser" = "Di gerokê de veke"; +"Common.Controls.Actions.OpenInSafari" = "Di Safariyê de veke"; +"Common.Controls.Actions.Preview" = "Pêşdîtin"; +"Common.Controls.Actions.Previous" = "Paş"; +"Common.Controls.Actions.Remove" = "Rake"; +"Common.Controls.Actions.Reply" = "Bersivê bide"; +"Common.Controls.Actions.ReportUser" = "%@ ragihîne"; +"Common.Controls.Actions.Save" = "Tomar bike"; +"Common.Controls.Actions.SavePhoto" = "Wêneyê tomar bike"; +"Common.Controls.Actions.SeeMore" = "Bêtir bibîne"; +"Common.Controls.Actions.Settings" = "Sazkarî"; +"Common.Controls.Actions.Share" = "Parve bike"; +"Common.Controls.Actions.SharePost" = "Şandiyê parve bike"; +"Common.Controls.Actions.ShareUser" = "%@ parve bike"; +"Common.Controls.Actions.SignIn" = "Têkeve"; +"Common.Controls.Actions.SignUp" = "Tomar bibe"; +"Common.Controls.Actions.Skip" = "Derbas bike"; +"Common.Controls.Actions.TakePhoto" = "Wêne bikişîne"; +"Common.Controls.Actions.TryAgain" = "Dîsa biceribîne"; +"Common.Controls.Actions.UnblockDomain" = "%@ asteng neke"; +"Common.Controls.Friendship.Block" = "Asteng bike"; +"Common.Controls.Friendship.BlockDomain" = "%@ asteng bike"; +"Common.Controls.Friendship.BlockUser" = "%@ asteng bike"; +"Common.Controls.Friendship.Blocked" = "Astengkirî"; +"Common.Controls.Friendship.EditInfo" = "Zanyariyan serrast bike"; +"Common.Controls.Friendship.Follow" = "Bişopîne"; +"Common.Controls.Friendship.Following" = "Dişopîne"; +"Common.Controls.Friendship.Mute" = "Bêdeng bike"; +"Common.Controls.Friendship.MuteUser" = "%@ bêdeng bike"; +"Common.Controls.Friendship.Muted" = "Bêdengkirî"; +"Common.Controls.Friendship.Pending" = "Tê nirxandin"; +"Common.Controls.Friendship.Request" = "Daxwaz bike"; +"Common.Controls.Friendship.Unblock" = "Astengiyê rake"; +"Common.Controls.Friendship.UnblockUser" = "%@ asteng neke"; +"Common.Controls.Friendship.Unmute" = "Bêdeng neke"; +"Common.Controls.Friendship.UnmuteUser" = "%@ bêdeng neke"; +"Common.Controls.Keyboard.Common.ComposeNewPost" = "Şandiyeke nû binivsîne"; +"Common.Controls.Keyboard.Common.OpenSettings" = "Sazkariyan Veke"; +"Common.Controls.Keyboard.Common.ShowFavorites" = "Bijarteyan nîşan bide"; +"Common.Controls.Keyboard.Common.SwitchToTab" = "Biguherîne bo %@"; +"Common.Controls.Keyboard.SegmentedControl.NextSection" = "Beşa pêş"; +"Common.Controls.Keyboard.SegmentedControl.PreviousSection" = "Beşa paş"; +"Common.Controls.Keyboard.Timeline.NextStatus" = "Şandiya pêş"; +"Common.Controls.Keyboard.Timeline.OpenAuthorProfile" = "Profîla nivîskaran veke"; +"Common.Controls.Keyboard.Timeline.OpenRebloggerProfile" = "Profîla nivîskaran veke"; +"Common.Controls.Keyboard.Timeline.OpenStatus" = "Şandiyê veke"; +"Common.Controls.Keyboard.Timeline.PreviewImage" = "Pêşdîtina wêneyê"; +"Common.Controls.Keyboard.Timeline.PreviousStatus" = "Şandeya paş"; +"Common.Controls.Keyboard.Timeline.ReplyStatus" = "Bersivê bide şandiyê"; +"Common.Controls.Keyboard.Timeline.ToggleContentWarning" = "Hişyariya naverokê biguherîne"; +"Common.Controls.Keyboard.Timeline.ToggleFavorite" = "Li ser şandiyê bijarte biguherîne"; +"Common.Controls.Keyboard.Timeline.ToggleReblog" = "Ji nû ve nivîsandin di şandiyê de biguherîne"; +"Common.Controls.Status.Actions.Favorite" = "Bijarte"; +"Common.Controls.Status.Actions.Hide" = "Veşêre"; +"Common.Controls.Status.Actions.Menu" = "Kulîn"; +"Common.Controls.Status.Actions.Reblog" = "Ji nû ve nivîsandin"; +"Common.Controls.Status.Actions.Reply" = "Bersivê bide"; +"Common.Controls.Status.Actions.Unfavorite" = "Nebijarte"; +"Common.Controls.Status.Actions.Unreblog" = "Ji nû ve nivîsandinê vegere"; +"Common.Controls.Status.ContentWarning" = "Hişyariya naverokê"; +"Common.Controls.Status.MediaContentWarning" = "Ji bo eşkerekirinê li derekî bitikîne"; +"Common.Controls.Status.Poll.Closed" = "Girtî"; +"Common.Controls.Status.Poll.Vote" = "Deng bide"; +"Common.Controls.Status.ShowPost" = "Şandiyê nîşan bide"; +"Common.Controls.Status.ShowUserProfile" = "Profîla bikarhêner nîşan bide"; +"Common.Controls.Status.Tag.Email" = "E-name"; +"Common.Controls.Status.Tag.Emoji" = "Emojî"; +"Common.Controls.Status.Tag.Hashtag" = "Hashtag"; +"Common.Controls.Status.Tag.Link" = "Girêdan"; +"Common.Controls.Status.Tag.Mention" = "Qalkirin"; +"Common.Controls.Status.Tag.Url" = "URL"; +"Common.Controls.Status.UserReblogged" = "%@ ji nû ve nivîsand"; +"Common.Controls.Status.UserRepliedTo" = "Bersiv da %@"; +"Common.Controls.Status.Visibility.Direct" = "Tenê bikarhênerê qalkirî dikare vê şandiyê bibîne."; +"Common.Controls.Status.Visibility.Private" = "Tenê şopînerên wan dikarin vê şandiyê bibînin."; +"Common.Controls.Status.Visibility.PrivateFromMe" = "Tenê şopînerên min dikarin vê şandiyê bibînin."; +"Common.Controls.Status.Visibility.Unlisted" = "Her kes dikare vê şandiyê bibîne lê nayê nîşandan di demnameya gelemperî de."; +"Common.Controls.Tabs.Home" = "Serrûpel"; +"Common.Controls.Tabs.Notification" = "Agahdarî"; +"Common.Controls.Tabs.Profile" = "Profîl"; +"Common.Controls.Tabs.Search" = "Bigere"; +"Common.Controls.Timeline.Filtered" = "Parzûnkirî"; +"Common.Controls.Timeline.Header.BlockedWarning" = "Tu nikarî profîla vî/ê bikarhênerî bibînî +heya ku ew astengiyê li ser te rakin."; +"Common.Controls.Timeline.Header.BlockingWarning" = "Tu nikarî profîla vî/ê bikarhênerî bibînî +Heya ku tu astengiyê li ser wî/ê ranekî. +Profîla te ji wan ra wiha xuya dike."; +"Common.Controls.Timeline.Header.NoStatusFound" = "Tu şandî nehate dîtin"; +"Common.Controls.Timeline.Header.SuspendedWarning" = "Ev bikarhêner hatiye rawestandin."; +"Common.Controls.Timeline.Header.UserBlockedWarning" = "Tu nikarî profîla %@ bibînî +Heta ku astengîya te rakin."; +"Common.Controls.Timeline.Header.UserBlockingWarning" = "Tu nikarî profîla %@ bibînî +Heya ku tu astengiyê li ser wî/ê ranekî. +Profîla te ji wan ra wiha xuya dike."; +"Common.Controls.Timeline.Header.UserSuspendedWarning" = "Ajimêra %@ hatiye rawestandin."; +"Common.Controls.Timeline.Loader.LoadMissingPosts" = "Şandiyên wendayî bar bike"; +"Common.Controls.Timeline.Loader.LoadingMissingPosts" = "Şandiyên wendayî tên barkirin..."; +"Common.Controls.Timeline.Loader.ShowMoreReplies" = "Bêtir bersivan nîşan bide"; +"Common.Controls.Timeline.Timestamp.Now" = "Niha"; +"Scene.AccountList.AddAccount" = "Ajimêr tevlî bike"; +"Scene.AccountList.DismissAccountSwitcher" = "Guherkera ajimêrê paş guh bike"; +"Scene.AccountList.TabBarHint" = "Profîla hilbijartî ya niha: %@. Du caran bitikîne û paşê dest bide ser da ku guhêrbara ajimêr were nîşandan"; +"Scene.Compose.Accessibility.AppendAttachment" = "Pêvek tevlî bike"; +"Scene.Compose.Accessibility.AppendPoll" = "Rapirsî tevlî bike"; +"Scene.Compose.Accessibility.CustomEmojiPicker" = "Hilbijêrê emojî yên kesanekirî"; +"Scene.Compose.Accessibility.DisableContentWarning" = "Hişyariya naverokê neçalak bike"; +"Scene.Compose.Accessibility.EnableContentWarning" = "Hişyariya naverokê çalak bike"; +"Scene.Compose.Accessibility.PostVisibilityMenu" = "Kulîna xuyabûna şandiyê"; +"Scene.Compose.Accessibility.RemovePoll" = "Rapirsî rake"; +"Scene.Compose.Attachment.AttachmentBroken" = "Ev %@ naxebite û nayê barkirin + li ser Mastodon."; +"Scene.Compose.Attachment.DescriptionPhoto" = "Wêneyê ji bo kêmbînên dîtbar bide nasîn..."; +"Scene.Compose.Attachment.DescriptionVideo" = "Vîdyoyê ji bo kêmbînên dîtbar bide nasîn..."; +"Scene.Compose.Attachment.Photo" = "wêne"; +"Scene.Compose.Attachment.Video" = "vîdyo"; +"Scene.Compose.AutoComplete.SpaceToAdd" = "Bicîhkirinê tevlî bike"; +"Scene.Compose.ComposeAction" = "Biweşîne"; +"Scene.Compose.ContentInputPlaceholder" = "Tiştê ku di hişê te de ye binivîsin an jî pêve bike"; +"Scene.Compose.ContentWarning.Placeholder" = "Li vir hişyariyek hûrgilî binivîsine..."; +"Scene.Compose.Keyboard.AppendAttachmentEntry" = "Pêvek tevlî bike - %@"; +"Scene.Compose.Keyboard.DiscardPost" = "Şandî paşguh bike"; +"Scene.Compose.Keyboard.PublishPost" = "Şandiyê biweşîne"; +"Scene.Compose.Keyboard.SelectVisibilityEntry" = "Xuyabûnê hilbijêre - %@"; +"Scene.Compose.Keyboard.ToggleContentWarning" = "Hişyariya naverokê biguherîne"; +"Scene.Compose.Keyboard.TogglePoll" = "Rapirsiyê biguherîne"; +"Scene.Compose.MediaSelection.Browse" = "Bigere"; +"Scene.Compose.MediaSelection.Camera" = "Wêne bikişîne"; +"Scene.Compose.MediaSelection.PhotoLibrary" = "Wênegeh"; +"Scene.Compose.Poll.DurationTime" = "Dirêjî: %@"; +"Scene.Compose.Poll.OneDay" = "1 Roj"; +"Scene.Compose.Poll.OneHour" = "1 Demjimêr"; +"Scene.Compose.Poll.OptionNumber" = "Vebijêrk %ld"; +"Scene.Compose.Poll.SevenDays" = "7 Roj"; +"Scene.Compose.Poll.SixHours" = "6 Demjimêr"; +"Scene.Compose.Poll.ThirtyMinutes" = "30 xulek"; +"Scene.Compose.Poll.ThreeDays" = "3 Roj"; +"Scene.Compose.ReplyingToUser" = "bersiv bide %@"; +"Scene.Compose.Title.NewPost" = "Şandiya nû"; +"Scene.Compose.Title.NewReply" = "Bersiva nû"; +"Scene.Compose.Visibility.Direct" = "Tenê mirovên ku min qalkirî"; +"Scene.Compose.Visibility.Private" = "Tenê şopîneran"; +"Scene.Compose.Visibility.Public" = "Gelemperî"; +"Scene.Compose.Visibility.Unlisted" = "Nerêzokkirî"; +"Scene.ConfirmEmail.Button.OpenEmailApp" = "Sepana e-nameyê veke"; +"Scene.ConfirmEmail.Button.Resend" = "Ji nû ve bişîne"; +"Scene.ConfirmEmail.DontReceiveEmail.Description" = "Kontrol bike ka navnîşana e-nameya te rast e û her wiha peldanka xwe ya spam."; +"Scene.ConfirmEmail.DontReceiveEmail.ResendEmail" = "E-namyê yê dîsa bişîne"; +"Scene.ConfirmEmail.DontReceiveEmail.Title" = "E-nameyê xwe kontrol bike"; +"Scene.ConfirmEmail.OpenEmailApp.Description" = "Me tenê ji te re e-nameyek şand. Heke nehatiye peldanka xwe ya spamê kontrol bike."; +"Scene.ConfirmEmail.OpenEmailApp.Mail" = "E-name"; +"Scene.ConfirmEmail.OpenEmailApp.OpenEmailClient" = "Rajegirê e-nameyê veke"; +"Scene.ConfirmEmail.OpenEmailApp.Title" = "Nameyên xwe yên wergirtî kontrol bike."; +"Scene.ConfirmEmail.Subtitle" = "Me tenê e-nameyek ji %@ re şand, +girêdanê bitikne da ku ajimêra xwe bidî piştrastkirin."; +"Scene.ConfirmEmail.Title" = "Tiştekî dawî."; +"Scene.Favorite.Title" = "Bijarteyên te"; +"Scene.Follower.Footer" = "Şopîner ji rajekerên din nayê dîtin."; +"Scene.Following.Footer" = "Şopandin ji rajekerên din nayê dîtin."; +"Scene.HomeTimeline.NavigationBarState.NewPosts" = "Şandiyên nû bibîne"; +"Scene.HomeTimeline.NavigationBarState.Offline" = "Derhêl"; +"Scene.HomeTimeline.NavigationBarState.Published" = "Hate weşandin!"; +"Scene.HomeTimeline.NavigationBarState.Publishing" = "Şandî tê weşandin..."; +"Scene.HomeTimeline.Title" = "Serrûpel"; +"Scene.Notification.Keyobard.ShowEverything" = "Her tiştî nîşan bide"; +"Scene.Notification.Keyobard.ShowMentions" = "Qalkirinan nîşan bike"; +"Scene.Notification.NotificationDescription.FavoritedYourPost" = "şandiya te hez kir"; +"Scene.Notification.NotificationDescription.FollowedYou" = "te şopand"; +"Scene.Notification.NotificationDescription.MentionedYou" = "qale te kir"; +"Scene.Notification.NotificationDescription.PollHasEnded" = "rapirsî qediya"; +"Scene.Notification.NotificationDescription.RebloggedYourPost" = "şandiya te ji nû ve nivisand"; +"Scene.Notification.NotificationDescription.RequestToFollowYou" = "dixwazê te bişopîne"; +"Scene.Notification.Title.Everything" = "Her tişt"; +"Scene.Notification.Title.Mentions" = "Qalkirin"; +"Scene.Preview.Keyboard.ClosePreview" = "Pêşdîtin bigire"; +"Scene.Preview.Keyboard.ShowNext" = "A pêş nîşan bide"; +"Scene.Preview.Keyboard.ShowPrevious" = "A paş nîşan bide"; +"Scene.Profile.Dashboard.Followers" = "şopîner"; +"Scene.Profile.Dashboard.Following" = "dişopîne"; +"Scene.Profile.Dashboard.Posts" = "şandî"; +"Scene.Profile.Fields.AddRow" = "Rêzê tevlî bike"; +"Scene.Profile.Fields.Placeholder.Content" = "Naverok"; +"Scene.Profile.Fields.Placeholder.Label" = "Nîşan"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Message" = "Ji bo rakirina astengkirinê %@ bipejirîne"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title" = "Ajimêr asteng bike"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Message" = "Ji bo bêdengkirina %@ bipejirîne"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Title" = "Ajimêrê bêdeng bike"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Message" = "Ji bo rakirina astengkirinê %@ bipejirîne"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Title" = "Astengiyê li ser ajimêr rake"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Message" = "Ji bo vekirina bêdengkirinê %@ bipejirîne"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Title" = "Ajimêrê bêdeng neke"; +"Scene.Profile.SegmentedControl.About" = "Derbar"; +"Scene.Profile.SegmentedControl.Media" = "Medya"; +"Scene.Profile.SegmentedControl.Posts" = "Şandî"; +"Scene.Profile.SegmentedControl.PostsAndReplies" = "Şandî û bersiv"; +"Scene.Profile.SegmentedControl.Replies" = "Bersiv"; +"Scene.Register.Error.Item.Agreement" = "Peyman"; +"Scene.Register.Error.Item.Email" = "E-name"; +"Scene.Register.Error.Item.Locale" = "Zimanê navrûyê"; +"Scene.Register.Error.Item.Password" = "Pêborîn"; +"Scene.Register.Error.Item.Reason" = "Sedem"; +"Scene.Register.Error.Item.Username" = "Navê bikarhêner"; +"Scene.Register.Error.Reason.Accepted" = "%@ divê were pejirandin"; +"Scene.Register.Error.Reason.Blank" = "%@ pêwist e"; +"Scene.Register.Error.Reason.Blocked" = "%@ peydekerê e-peyamê yê qedexekirî dihewîne"; +"Scene.Register.Error.Reason.Inclusion" = "%@ ne nirxek piştgirî ye"; +"Scene.Register.Error.Reason.Invalid" = "%@ ne derbasdar e"; +"Scene.Register.Error.Reason.Reserved" = "%@ peyveke parastî ye"; +"Scene.Register.Error.Reason.Taken" = "%@ jixwe tê bikaranîn"; +"Scene.Register.Error.Reason.TooLong" = "%@ pir dirêj e"; +"Scene.Register.Error.Reason.TooShort" = "%@ pir kurt e"; +"Scene.Register.Error.Reason.Unreachable" = "%@ xuya ye ku tune ye"; +"Scene.Register.Error.Special.EmailInvalid" = "Ev navnîşaneke e-nameyê ne derbasdar e"; +"Scene.Register.Error.Special.PasswordTooShort" = "Pêborîn pir kurt e (divê herî kêm 8 tîp be)"; +"Scene.Register.Error.Special.UsernameInvalid" = "Navê bikarhêner divê tenê ji tîpên alfajimarî û binxêz pêk be"; +"Scene.Register.Error.Special.UsernameTooLong" = "Navê bikarhêner pir dirêj e (ji 30 tîpan dirêjtir nabe)"; +"Scene.Register.Input.Avatar.Delete" = "Jê bibe"; +"Scene.Register.Input.DisplayName.Placeholder" = "navê nîşanê"; +"Scene.Register.Input.Email.Placeholder" = "e-name"; +"Scene.Register.Input.Invite.RegistrationUserInviteRequest" = "Tu çima dixwazî beşdar bibî?"; +"Scene.Register.Input.Password.Accessibility.Checked" = "hate kontrolkirin"; +"Scene.Register.Input.Password.Accessibility.Unchecked" = "nehate kontrolkirin"; +"Scene.Register.Input.Password.CharacterLimit" = "8 tîp"; +"Scene.Register.Input.Password.Hint" = "Pêborîna te herî kêm divê ji 8 tîpan pêk bê"; +"Scene.Register.Input.Password.Placeholder" = "pêborîn"; +"Scene.Register.Input.Password.Require" = "Pêdiviya pêborîna te ya herî kêm:"; +"Scene.Register.Input.Username.DuplicatePrompt" = "Navê vê bikarhêner tê girtin."; +"Scene.Register.Input.Username.Placeholder" = "navê bikarhêner"; +"Scene.Register.Title" = "Ji me re hinekî qala xwe bike %@"; +"Scene.Report.Content1" = "Şandiyên din hene ku tu dixwazî tevlî ragihandinê bikî?"; +"Scene.Report.Content2" = "Derbarê vê ragihandinê de tiştek heye ku divê çavdêr bizanin?"; +"Scene.Report.ReportSentTitle" = "Spas ji bo ragihandina te, em ê binirxînin."; +"Scene.Report.Reported" = "HATE RAGIHANDIN"; +"Scene.Report.Send" = "Ragihandinê bişîne"; +"Scene.Report.SkipToSend" = "Bêyî şirove bişîne"; +"Scene.Report.Step1" = "Gav 1 ji 2"; +"Scene.Report.Step2" = "Gav 2 ji 2"; +"Scene.Report.TextPlaceholder" = "Şiroveyên daxwazkirê binivîsine an jî pê ve bike"; +"Scene.Report.Title" = "%@ ragihîne"; +"Scene.Report.TitleReport" = "Ragihandin"; +"Scene.Search.Recommend.Accounts.Description" = "Dibe ku tu bixwazî van ajimêran bişopînî"; +"Scene.Search.Recommend.Accounts.Follow" = "Bişopîne"; +"Scene.Search.Recommend.Accounts.Title" = "Ajimêrên ku belkî tu jê hez bikî"; +"Scene.Search.Recommend.ButtonText" = "Hemûyan bibîne"; +"Scene.Search.Recommend.HashTag.Description" = "Hashtag ên ku pir balê dikişînin"; +"Scene.Search.Recommend.HashTag.PeopleTalking" = "%@ kes diaxivin"; +"Scene.Search.Recommend.HashTag.Title" = "Rojev li ser Mastodon"; +"Scene.Search.SearchBar.Cancel" = "Dev jê berde"; +"Scene.Search.SearchBar.Placeholder" = "Li hashtag û bikarhêneran bigere"; +"Scene.Search.Searching.Clear" = "Pak bike"; +"Scene.Search.Searching.EmptyState.NoResults" = "Encam tune"; +"Scene.Search.Searching.RecentSearch" = "Lêgerînên dawî"; +"Scene.Search.Searching.Segment.All" = "Hemû"; +"Scene.Search.Searching.Segment.Hashtags" = "Hashtag"; +"Scene.Search.Searching.Segment.People" = "Mirov"; +"Scene.Search.Searching.Segment.Posts" = "Şandî"; +"Scene.Search.Title" = "Bigere"; +"Scene.ServerPicker.Button.Category.Academia" = "akademî"; +"Scene.ServerPicker.Button.Category.Activism" = "çalakî"; +"Scene.ServerPicker.Button.Category.All" = "Hemû"; +"Scene.ServerPicker.Button.Category.AllAccessiblityDescription" = "Beş: Hemû"; +"Scene.ServerPicker.Button.Category.Art" = "huner"; +"Scene.ServerPicker.Button.Category.Food" = "xwarin"; +"Scene.ServerPicker.Button.Category.Furry" = "furry"; +"Scene.ServerPicker.Button.Category.Games" = "lîsk"; +"Scene.ServerPicker.Button.Category.General" = "giştî"; +"Scene.ServerPicker.Button.Category.Journalism" = "rojnamevanî"; +"Scene.ServerPicker.Button.Category.Lgbt" = "lgbt"; +"Scene.ServerPicker.Button.Category.Music" = "muzîk"; +"Scene.ServerPicker.Button.Category.Regional" = "herêmî"; +"Scene.ServerPicker.Button.Category.Tech" = "teknolojî"; +"Scene.ServerPicker.Button.SeeLess" = "Kêmtir bibîne"; +"Scene.ServerPicker.Button.SeeMore" = "Bêtir bibîne"; +"Scene.ServerPicker.EmptyState.BadNetwork" = "Di dema barkirina daneyan da çewtî derket. Girêdana xwe ya înternetê kontrol bike."; +"Scene.ServerPicker.EmptyState.FindingServers" = "Peydakirina rajekarên berdest..."; +"Scene.ServerPicker.EmptyState.NoResults" = "Encam tune"; +"Scene.ServerPicker.Input.Placeholder" = "Rajekarekî bibîne an jî beşdarî ya xwe bibe..."; +"Scene.ServerPicker.Label.Category" = "BEŞ"; +"Scene.ServerPicker.Label.Language" = "ZIMAN"; +"Scene.ServerPicker.Label.Users" = "BIKARHÊNER"; +"Scene.ServerPicker.Subtitle" = "Li gorî berjewendî, herêm, an jî armancek gelemperî civakekê hilbijêre."; +"Scene.ServerPicker.SubtitleExtend" = "Li gorî berjewendî, herêm, an jî armancek gelemperî civakekê hilbijêre. Her civakek ji hêla rêxistinek an kesek bi tevahî serbixwe ve tê xebitandin."; +"Scene.ServerPicker.Title" = "Rajekarekê hilbijêre, +Her kîjan rajekar be."; +"Scene.ServerRules.Button.Confirm" = "Ez dipejirînim"; +"Scene.ServerRules.PrivacyPolicy" = "polîtikaya nihêniyê"; +"Scene.ServerRules.Prompt" = "Bi domandinê, tu ji bo %@ di bin mercên bikaranînê û polîtîkaya nepenîtiyê dipejirînî."; +"Scene.ServerRules.Subtitle" = "Ev rêzik ji aliyê çavdêrên %@ ve tên sazkirin."; +"Scene.ServerRules.TermsOfService" = "mercên bikaranînê"; +"Scene.ServerRules.Title" = "Hinek rêzikên bingehîn."; +"Scene.Settings.Footer.MastodonDescription" = "Mastodon nermalava çavkaniya vekirî ye. Tu dikarî pirsgirêkan li ser GitHub-ê ragihînî di %@ (%@) de"; +"Scene.Settings.Keyboard.CloseSettingsWindow" = "Sazkariyên çarçoveyê bigire"; +"Scene.Settings.Section.Appearance.Automatic" = "Xweber"; +"Scene.Settings.Section.Appearance.Dark" = "Her dem tarî"; +"Scene.Settings.Section.Appearance.Light" = "Her dem ronahî"; +"Scene.Settings.Section.Appearance.Title" = "Xuyang"; +"Scene.Settings.Section.BoringZone.AccountSettings" = "Sazkariyên ajimêr"; +"Scene.Settings.Section.BoringZone.Privacy" = "Polîtikaya nihêniyê"; +"Scene.Settings.Section.BoringZone.Terms" = "Mercên bikaranînê"; +"Scene.Settings.Section.BoringZone.Title" = "Devera acizker"; +"Scene.Settings.Section.LookAndFeel.Light" = "Ronahî"; +"Scene.Settings.Section.LookAndFeel.ReallyDark" = "Tarî"; +"Scene.Settings.Section.LookAndFeel.SortaDark" = "Hinekî tarî"; +"Scene.Settings.Section.LookAndFeel.Title" = "Xuyang"; +"Scene.Settings.Section.LookAndFeel.UseSystem" = "Pergalê bi kar bîne"; +"Scene.Settings.Section.Notifications.Boosts" = "Şandiya min ji nû ve nivîsand"; +"Scene.Settings.Section.Notifications.Favorites" = "Şandiyên min hez kir"; +"Scene.Settings.Section.Notifications.Follows" = "Min dişopîne"; +"Scene.Settings.Section.Notifications.Mentions" = "Qale min kir"; +"Scene.Settings.Section.Notifications.Title" = "Agahdarî"; +"Scene.Settings.Section.Notifications.Trigger.Anyone" = "her kes"; +"Scene.Settings.Section.Notifications.Trigger.Follow" = "her kesê ku dişopînim"; +"Scene.Settings.Section.Notifications.Trigger.Follower" = "şopînerek"; +"Scene.Settings.Section.Notifications.Trigger.Noone" = "ne yek"; +"Scene.Settings.Section.Notifications.Trigger.Title" = "Min agahdar bike gava"; +"Scene.Settings.Section.Preference.DisableAvatarAnimation" = "Avatarên anîmasyonî neçalak bike"; +"Scene.Settings.Section.Preference.DisableEmojiAnimation" = "Emojiyên anîmasyonî neçalak bike"; +"Scene.Settings.Section.Preference.Title" = "Sazkarî"; +"Scene.Settings.Section.Preference.TrueBlackDarkMode" = "Moda tarî ya reş a rastîn"; +"Scene.Settings.Section.Preference.UsingDefaultBrowser" = "Ji bo vekirina girêdanan geroka berdest bi kar bîne"; +"Scene.Settings.Section.SpicyZone.Clear" = "Pêşbîra medyayê pak bike"; +"Scene.Settings.Section.SpicyZone.Signout" = "Derkeve"; +"Scene.Settings.Section.SpicyZone.Title" = "Devera germ"; +"Scene.Settings.Title" = "Sazkarî"; +"Scene.SuggestionAccount.FollowExplain" = "Gava tu kesekî dişopînî, tu yê şandiyê wan di serrûpelê de bibîne."; +"Scene.SuggestionAccount.Title" = "Kesên bo ku bişopînî bibîne"; +"Scene.Thread.BackTitle" = "Şandî"; +"Scene.Thread.Title" = "Şandî ji %@"; +"Scene.Welcome.GetStarted" = "Dest pê bike"; +"Scene.Welcome.LogIn" = "Têkeve"; +"Scene.Welcome.Slogan" = "Torên civakî +di destên te de."; +"Scene.Wizard.AccessibilityHint" = "Du caran bitikîne da ku çarçoveyahilpekok ji holê rakî"; +"Scene.Wizard.MultipleAccountSwitchIntroDescription" = "Dest bide ser bişkoja profîlê da ku di navbera gelek ajimêrann de biguherînî."; +"Scene.Wizard.NewInMastodon" = "Nû di Mastodon de"; \ No newline at end of file diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/ku.lproj/Localizable.stringsdict b/MastodonSDK/Sources/MastodonLocalization/Resources/ku.lproj/Localizable.stringsdict new file mode 100644 index 00000000..8ae1b812 --- /dev/null +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/ku.lproj/Localizable.stringsdict @@ -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> diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/nl.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/nl.lproj/Localizable.strings index 9c84e138..f9e04622 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/nl.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/nl.lproj/Localizable.strings @@ -4,7 +4,7 @@ "Common.Alerts.CleanCache.Title" = "Cache-geheugen Wissen"; "Common.Alerts.Common.PleaseTryAgain" = "Probeer het opnieuw."; "Common.Alerts.Common.PleaseTryAgainLater" = "Probeer het later nog eens."; -"Common.Alerts.DeletePost.Delete" = "Verwijderen"; +"Common.Alerts.DeletePost.Message" = "Are you sure you want to delete this post?"; "Common.Alerts.DeletePost.Title" = "Weet u zeker dat u dit bericht wilt verwijderen?"; "Common.Alerts.DiscardPostContent.Message" = "Bevestig het verwijderen van het concept bericht."; "Common.Alerts.DiscardPostContent.Title" = "Concept Verwijderen"; @@ -40,6 +40,7 @@ "Common.Controls.Actions.Next" = "Volgende"; "Common.Controls.Actions.Ok" = "Oké"; "Common.Controls.Actions.Open" = "Open"; +"Common.Controls.Actions.OpenInBrowser" = "Open in Browser"; "Common.Controls.Actions.OpenInSafari" = "Open in Safari"; "Common.Controls.Actions.Preview" = "Voorvertoning"; "Common.Controls.Actions.Previous" = "Vorige"; @@ -92,6 +93,7 @@ "Common.Controls.Keyboard.Timeline.ToggleFavorite" = "Favoriet Omschakelen bij Bericht"; "Common.Controls.Keyboard.Timeline.ToggleReblog" = "Delen bij berichten omschakelen"; "Common.Controls.Status.Actions.Favorite" = "Toevoegen aan Favorieten"; +"Common.Controls.Status.Actions.Hide" = "Hide"; "Common.Controls.Status.Actions.Menu" = "Menu"; "Common.Controls.Status.Actions.Reblog" = "Delen"; "Common.Controls.Status.Actions.Reply" = "Reageren"; @@ -111,6 +113,10 @@ "Common.Controls.Status.Tag.Url" = "URL"; "Common.Controls.Status.UserReblogged" = "%@ gedeeld"; "Common.Controls.Status.UserRepliedTo" = "Reactie op %@"; +"Common.Controls.Status.Visibility.Direct" = "Only mentioned user can see this post."; +"Common.Controls.Status.Visibility.Private" = "Only their followers can see this post."; +"Common.Controls.Status.Visibility.PrivateFromMe" = "Only my followers can see this post."; +"Common.Controls.Status.Visibility.Unlisted" = "Everyone can see this post but not display in the public timeline."; "Common.Controls.Tabs.Home" = "Start"; "Common.Controls.Tabs.Notification" = "Melding"; "Common.Controls.Tabs.Profile" = "Profiel"; @@ -172,8 +178,8 @@ Uw profiel ziet er zo uit voor hen."; "Scene.Compose.Visibility.Private" = "Alleen volgers"; "Scene.Compose.Visibility.Public" = "Openbaar"; "Scene.Compose.Visibility.Unlisted" = "Niet-vermeld"; -"Scene.ConfirmEmail.Button.DontReceiveEmail" = "Ik heb geen email ontvangen"; "Scene.ConfirmEmail.Button.OpenEmailApp" = "Email Openen"; +"Scene.ConfirmEmail.Button.Resend" = "Resend"; "Scene.ConfirmEmail.DontReceiveEmail.Description" = "Controleer of uw emailadres correct is en of the email in de ongewenste email filter terecht is gekomen."; "Scene.ConfirmEmail.DontReceiveEmail.ResendEmail" = "Email Opnieuw Versturen"; "Scene.ConfirmEmail.DontReceiveEmail.Title" = "Controleer uw emailadres"; @@ -194,14 +200,14 @@ klik op de link om uw account te bevestigen."; "Scene.HomeTimeline.Title" = "Start"; "Scene.Notification.Keyobard.ShowEverything" = "Alles weergeven"; "Scene.Notification.Keyobard.ShowMentions" = "Vermeldingen weergeven"; +"Scene.Notification.NotificationDescription.FavoritedYourPost" = "favorited your post"; +"Scene.Notification.NotificationDescription.FollowedYou" = "followed you"; +"Scene.Notification.NotificationDescription.MentionedYou" = "mentioned you"; +"Scene.Notification.NotificationDescription.PollHasEnded" = "poll has ended"; +"Scene.Notification.NotificationDescription.RebloggedYourPost" = "reblogged your post"; +"Scene.Notification.NotificationDescription.RequestToFollowYou" = "request to follow you"; "Scene.Notification.Title.Everything" = "Alles"; "Scene.Notification.Title.Mentions" = "Vermeldingen"; -"Scene.Notification.UserFavorited Your Post" = "%@ favorited your post"; -"Scene.Notification.UserFollowedYou" = "%@ followed you"; -"Scene.Notification.UserMentionedYou" = "%@ mentioned you"; -"Scene.Notification.UserRebloggedYourPost" = "%@ reblogged your post"; -"Scene.Notification.UserRequestedToFollowYou" = "%@ requested to follow you"; -"Scene.Notification.UserYourPollHasEnded" = "%@ Your poll has ended"; "Scene.Preview.Keyboard.ClosePreview" = "Voorbeeldweergave Sluiten"; "Scene.Preview.Keyboard.ShowNext" = "Volgende"; "Scene.Preview.Keyboard.ShowPrevious" = "Vorige"; @@ -211,12 +217,18 @@ klik op de link om uw account te bevestigen."; "Scene.Profile.Fields.AddRow" = "Rij Toevoegen"; "Scene.Profile.Fields.Placeholder.Content" = "Inhoud"; "Scene.Profile.Fields.Placeholder.Label" = "Etiket"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Message" = "Bevestig om %@ te deblokkeren"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Title" = "Account niet langer negeren"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Message" = "Confirm to block %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title" = "Block Account"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Message" = "Confirm to mute %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Title" = "Mute Account"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Message" = "Confirm to unblock %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Title" = "Unblock Account"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Message" = "Bevestig om %@ te negeren"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Title" = "Account Negeren"; +"Scene.Profile.SegmentedControl.About" = "About"; "Scene.Profile.SegmentedControl.Media" = "Media"; "Scene.Profile.SegmentedControl.Posts" = "Berichten"; +"Scene.Profile.SegmentedControl.PostsAndReplies" = "Posts and Replies"; "Scene.Profile.SegmentedControl.Replies" = "Reacties"; "Scene.Register.Error.Item.Agreement" = "Overeenkomst"; "Scene.Register.Error.Item.Email" = "Email"; @@ -242,19 +254,26 @@ klik op de link om uw account te bevestigen."; "Scene.Register.Input.DisplayName.Placeholder" = "weergavenaam"; "Scene.Register.Input.Email.Placeholder" = "email"; "Scene.Register.Input.Invite.RegistrationUserInviteRequest" = "Waarom wil u zich hier registreren?"; +"Scene.Register.Input.Password.Accessibility.Checked" = "checked"; +"Scene.Register.Input.Password.Accessibility.Unchecked" = "unchecked"; +"Scene.Register.Input.Password.CharacterLimit" = "8 characters"; "Scene.Register.Input.Password.Hint" = "Uw wachtwoord moet ten minste acht tekens bevatten"; "Scene.Register.Input.Password.Placeholder" = "wachtwoord"; +"Scene.Register.Input.Password.Require" = "Your password needs at least:"; "Scene.Register.Input.Username.DuplicatePrompt" = "Deze gebruikersnaam is al in gebruik."; "Scene.Register.Input.Username.Placeholder" = "gebruikersnaam"; "Scene.Register.Title" = "Vertel ons over uzelf."; "Scene.Report.Content1" = "Zijn er nog meer berichten die u aan het rapport wilt toevoegen?"; "Scene.Report.Content2" = "Is er iets anders over dit rapport dat de moderators zouden moeten weten?"; +"Scene.Report.ReportSentTitle" = "Thanks for reporting, we’ll look into this."; +"Scene.Report.Reported" = "REPORTED"; "Scene.Report.Send" = "Stuur rapport"; "Scene.Report.SkipToSend" = "Verstuur zonder opmerkingen"; "Scene.Report.Step1" = "Stap 1 van 2"; "Scene.Report.Step2" = "Stap 2 van 2"; "Scene.Report.TextPlaceholder" = "Schrijf of plak aanvullende opmerkingen"; "Scene.Report.Title" = "Rapporteer %@"; +"Scene.Report.TitleReport" = "Report"; "Scene.Search.Recommend.Accounts.Description" = "Misschien dat u geïnteresseerd bent in deze accounts"; "Scene.Search.Recommend.Accounts.Follow" = "Volgen"; "Scene.Search.Recommend.Accounts.Title" = "Interessante accounts voor u"; @@ -295,6 +314,8 @@ klik op de link om uw account te bevestigen."; "Scene.ServerPicker.Label.Category" = "CATEGORIE"; "Scene.ServerPicker.Label.Language" = "TAAL"; "Scene.ServerPicker.Label.Users" = "GEBRUIKERS"; +"Scene.ServerPicker.Subtitle" = "Pick a community based on your interests, region, or a general purpose one."; +"Scene.ServerPicker.SubtitleExtend" = "Pick a community based on your interests, region, or a general purpose one. Each community is operated by an entirely independent organization or individual."; "Scene.ServerPicker.Title" = "Kies een server, welke dan ook."; "Scene.ServerRules.Button.Confirm" = "Ik Ga Akkoord"; "Scene.ServerRules.PrivacyPolicy" = "privacybeleid"; @@ -312,6 +333,11 @@ klik op de link om uw account te bevestigen."; "Scene.Settings.Section.BoringZone.Privacy" = "Privacybeleid"; "Scene.Settings.Section.BoringZone.Terms" = "Servicevoorwaarden"; "Scene.Settings.Section.BoringZone.Title" = "De Saaie Instellingen"; +"Scene.Settings.Section.LookAndFeel.Light" = "Light"; +"Scene.Settings.Section.LookAndFeel.ReallyDark" = "Really Dark"; +"Scene.Settings.Section.LookAndFeel.SortaDark" = "Sorta Dark"; +"Scene.Settings.Section.LookAndFeel.Title" = "Look and Feel"; +"Scene.Settings.Section.LookAndFeel.UseSystem" = "Use System"; "Scene.Settings.Section.Notifications.Boosts" = "Mijn bericht deelt"; "Scene.Settings.Section.Notifications.Favorites" = "Mijn bericht als favoriet toevoegt"; "Scene.Settings.Section.Notifications.Follows" = "Mij volgt"; @@ -335,6 +361,8 @@ klik op de link om uw account te bevestigen."; "Scene.SuggestionAccount.Title" = "Zoek Mensen om te Volgen"; "Scene.Thread.BackTitle" = "Bericht"; "Scene.Thread.Title" = "Bericht van %@"; +"Scene.Welcome.GetStarted" = "Get Started"; +"Scene.Welcome.LogIn" = "Log In"; "Scene.Welcome.Slogan" = "Sociale media terug in uw handen."; "Scene.Wizard.AccessibilityHint" = "Double tap to dismiss this wizard"; "Scene.Wizard.MultipleAccountSwitchIntroDescription" = "Switch between multiple accounts by holding the profile button."; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/ru.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/ru.lproj/Localizable.strings index 1a4f92fc..aa05910c 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/ru.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/ru.lproj/Localizable.strings @@ -4,7 +4,7 @@ "Common.Alerts.CleanCache.Title" = "Очистка кэша"; "Common.Alerts.Common.PleaseTryAgain" = "Пожалуйста, попробуйте ещё раз."; "Common.Alerts.Common.PleaseTryAgainLater" = "Пожалуйста, попробуйте позже."; -"Common.Alerts.DeletePost.Delete" = "Удалить"; +"Common.Alerts.DeletePost.Message" = "Are you sure you want to delete this post?"; "Common.Alerts.DeletePost.Title" = "Вы уверены, что хотите удалить этот пост?"; "Common.Alerts.DiscardPostContent.Message" = "Вы действительно хотите удалить набранное содержимое поста?"; "Common.Alerts.DiscardPostContent.Title" = "Удалить черновик"; @@ -28,7 +28,7 @@ "Common.Controls.Actions.Back" = "Назад"; "Common.Controls.Actions.BlockDomain" = "Заблокировать %@"; "Common.Controls.Actions.Cancel" = "Отмена"; -"Common.Controls.Actions.Compose" = "Compose"; +"Common.Controls.Actions.Compose" = "Написать"; "Common.Controls.Actions.Confirm" = "Подтвердить"; "Common.Controls.Actions.Continue" = "Продолжить"; "Common.Controls.Actions.CopyPhoto" = "Скопировать изображение"; @@ -41,6 +41,7 @@ "Common.Controls.Actions.Next" = "Далее"; "Common.Controls.Actions.Ok" = "ОК"; "Common.Controls.Actions.Open" = "Открыть"; +"Common.Controls.Actions.OpenInBrowser" = "Открыть в браузере"; "Common.Controls.Actions.OpenInSafari" = "Открыть в Safari"; "Common.Controls.Actions.Preview" = "Предпросмотр"; "Common.Controls.Actions.Previous" = "Прошлые"; @@ -93,6 +94,7 @@ "Common.Controls.Keyboard.Timeline.ToggleFavorite" = "Добавить или убрать из избранного"; "Common.Controls.Keyboard.Timeline.ToggleReblog" = "Продвинуть или убрать продвижение"; "Common.Controls.Status.Actions.Favorite" = "Добавить в избранное"; +"Common.Controls.Status.Actions.Hide" = "Hide"; "Common.Controls.Status.Actions.Menu" = "Меню"; "Common.Controls.Status.Actions.Reblog" = "Продвинуть"; "Common.Controls.Status.Actions.Reply" = "Ответить"; @@ -112,6 +114,10 @@ "Common.Controls.Status.Tag.Url" = "Ссылка"; "Common.Controls.Status.UserReblogged" = "%@ продвинул(а)"; "Common.Controls.Status.UserRepliedTo" = "Ответил(а) %@"; +"Common.Controls.Status.Visibility.Direct" = "Only mentioned user can see this post."; +"Common.Controls.Status.Visibility.Private" = "Only their followers can see this post."; +"Common.Controls.Status.Visibility.PrivateFromMe" = "Only my followers can see this post."; +"Common.Controls.Status.Visibility.Unlisted" = "Everyone can see this post but not display in the public timeline."; "Common.Controls.Tabs.Home" = "Главная"; "Common.Controls.Tabs.Notification" = "Уведомление"; "Common.Controls.Tabs.Profile" = "Профиль"; @@ -186,8 +192,8 @@ "Scene.Compose.Visibility.Private" = "Для подписчиков"; "Scene.Compose.Visibility.Public" = "Публичный"; "Scene.Compose.Visibility.Unlisted" = "Скрытый"; -"Scene.ConfirmEmail.Button.DontReceiveEmail" = "Я не получил письма"; "Scene.ConfirmEmail.Button.OpenEmailApp" = "Открыть приложение почты"; +"Scene.ConfirmEmail.Button.Resend" = "Resend"; "Scene.ConfirmEmail.DontReceiveEmail.Description" = "Проверьте, правильно ли указан ваш e-mail адрес, а также папку «спам», если ещё не сделали этого."; "Scene.ConfirmEmail.DontReceiveEmail.ResendEmail" = "Отправить ещё раз"; "Scene.ConfirmEmail.DontReceiveEmail.Title" = "Проверьте свой e-mail адрес"; @@ -210,14 +216,14 @@ "Scene.HomeTimeline.Title" = "Главная"; "Scene.Notification.Keyobard.ShowEverything" = "Показать все"; "Scene.Notification.Keyobard.ShowMentions" = "Показать упоминания"; +"Scene.Notification.NotificationDescription.FavoritedYourPost" = "favorited your post"; +"Scene.Notification.NotificationDescription.FollowedYou" = "followed you"; +"Scene.Notification.NotificationDescription.MentionedYou" = "mentioned you"; +"Scene.Notification.NotificationDescription.PollHasEnded" = "poll has ended"; +"Scene.Notification.NotificationDescription.RebloggedYourPost" = "reblogged your post"; +"Scene.Notification.NotificationDescription.RequestToFollowYou" = "request to follow you"; "Scene.Notification.Title.Everything" = "Все"; "Scene.Notification.Title.Mentions" = "Упоминания"; -"Scene.Notification.UserFavorited Your Post" = "%@ favorited your post"; -"Scene.Notification.UserFollowedYou" = "%@ подписался (-ась)"; -"Scene.Notification.UserMentionedYou" = "%@ упомянул вас"; -"Scene.Notification.UserRebloggedYourPost" = "%@ reblogged your post"; -"Scene.Notification.UserRequestedToFollowYou" = "%@ запрашивает подписку"; -"Scene.Notification.UserYourPollHasEnded" = "%@ Your poll has ended"; "Scene.Preview.Keyboard.ClosePreview" = "Закрыть предпросмотр"; "Scene.Preview.Keyboard.ShowNext" = "Следующее изображение"; "Scene.Preview.Keyboard.ShowPrevious" = "Предыдущее изображение"; @@ -227,12 +233,18 @@ "Scene.Profile.Fields.AddRow" = "Добавить строку"; "Scene.Profile.Fields.Placeholder.Content" = "Содержимое"; "Scene.Profile.Fields.Placeholder.Label" = "Ярлык"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Message" = "Убрать %@ из списка блокировки?"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Title" = "Разблокировать"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Message" = "Confirm to block %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title" = "Block Account"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Message" = "Confirm to mute %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Title" = "Mute Account"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Message" = "Confirm to unblock %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Title" = "Unblock Account"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Message" = "Убрать %@ из игнорируемых?"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Title" = "Убрать из игнорируемых"; +"Scene.Profile.SegmentedControl.About" = "About"; "Scene.Profile.SegmentedControl.Media" = "Медиа"; "Scene.Profile.SegmentedControl.Posts" = "Посты"; +"Scene.Profile.SegmentedControl.PostsAndReplies" = "Posts and Replies"; "Scene.Profile.SegmentedControl.Replies" = "Ответы"; "Scene.Register.Error.Item.Agreement" = "Соглашение"; "Scene.Register.Error.Item.Email" = "E-mail"; @@ -258,19 +270,26 @@ "Scene.Register.Input.DisplayName.Placeholder" = "отображаемое имя"; "Scene.Register.Input.Email.Placeholder" = "e-mail"; "Scene.Register.Input.Invite.RegistrationUserInviteRequest" = "Почему вы хотите присоединиться?"; +"Scene.Register.Input.Password.Accessibility.Checked" = "checked"; +"Scene.Register.Input.Password.Accessibility.Unchecked" = "unchecked"; +"Scene.Register.Input.Password.CharacterLimit" = "8 characters"; "Scene.Register.Input.Password.Hint" = "Пароль должен содержать не менее восьми символов"; "Scene.Register.Input.Password.Placeholder" = "пароль"; +"Scene.Register.Input.Password.Require" = "Your password needs at least:"; "Scene.Register.Input.Username.DuplicatePrompt" = "Это имя пользователя занято."; "Scene.Register.Input.Username.Placeholder" = "имя пользователя"; "Scene.Register.Title" = "Расскажите нам о себе."; "Scene.Report.Content1" = "Есть ли другие сообщения, которые вы хотите добавить в отчёт?"; "Scene.Report.Content2" = "Есть ли что-то, что модераторы должны знать об этом сообщении?"; +"Scene.Report.ReportSentTitle" = "Thanks for reporting, we’ll look into this."; +"Scene.Report.Reported" = "REPORTED"; "Scene.Report.Send" = "Пожаловаться"; "Scene.Report.SkipToSend" = "Отправить без комментария"; "Scene.Report.Step1" = "Шаг 1 из 2"; "Scene.Report.Step2" = "Шаг 2 из 2"; "Scene.Report.TextPlaceholder" = "Дополнительные комментарии"; "Scene.Report.Title" = "Пожаловаться на %@"; +"Scene.Report.TitleReport" = "Report"; "Scene.Search.Recommend.Accounts.Description" = "Возможно, вы захотите подписаться на эти профили"; "Scene.Search.Recommend.Accounts.Follow" = "Подписаться"; "Scene.Search.Recommend.Accounts.Title" = "Вам может понравится"; @@ -311,6 +330,8 @@ "Scene.ServerPicker.Label.Category" = "КАТЕГОРИЯ"; "Scene.ServerPicker.Label.Language" = "ЯЗЫК"; "Scene.ServerPicker.Label.Users" = "ПОЛЬЗОВАТЕЛИ"; +"Scene.ServerPicker.Subtitle" = "Выберите сообщество на основе своих интересов, региона или общей тематики."; +"Scene.ServerPicker.SubtitleExtend" = "Pick a community based on your interests, region, or a general purpose one. Each community is operated by an entirely independent organization or individual."; "Scene.ServerPicker.Title" = "Выберите сервер, любой сервер."; "Scene.ServerRules.Button.Confirm" = "Принимаю"; @@ -329,6 +350,11 @@ "Scene.Settings.Section.BoringZone.Privacy" = "Политика конфиденциальности"; "Scene.Settings.Section.BoringZone.Terms" = "Условия использования"; "Scene.Settings.Section.BoringZone.Title" = "Зона скукотищи"; +"Scene.Settings.Section.LookAndFeel.Light" = "Light"; +"Scene.Settings.Section.LookAndFeel.ReallyDark" = "Really Dark"; +"Scene.Settings.Section.LookAndFeel.SortaDark" = "Sorta Dark"; +"Scene.Settings.Section.LookAndFeel.Title" = "Look and Feel"; +"Scene.Settings.Section.LookAndFeel.UseSystem" = "Use System"; "Scene.Settings.Section.Notifications.Boosts" = "Продвигает мой пост"; "Scene.Settings.Section.Notifications.Favorites" = "Добавляет мой пост в избранное"; "Scene.Settings.Section.Notifications.Follows" = "Подписался на меня"; @@ -352,6 +378,8 @@ "Scene.SuggestionAccount.Title" = "Подпишитесь на людей"; "Scene.Thread.BackTitle" = "Пост"; "Scene.Thread.Title" = "Пост %@"; +"Scene.Welcome.GetStarted" = "Get Started"; +"Scene.Welcome.LogIn" = "Вход"; "Scene.Welcome.Slogan" = "Социальная сеть под вашим контролем."; "Scene.Wizard.AccessibilityHint" = "Double tap to dismiss this wizard"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/sv_FI.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/sv_FI.lproj/Localizable.strings index bf57c040..738a9ac0 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/sv_FI.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/sv_FI.lproj/Localizable.strings @@ -1,349 +1,376 @@ -"Common.Alerts.BlockDomain.BlockEntireDomain" = "Block Domain"; +"Common.Alerts.BlockDomain.BlockEntireDomain" = "Estä verkkotunnus"; "Common.Alerts.BlockDomain.Title" = "Are you really, really sure you want to block the entire %@? 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."; -"Common.Alerts.CleanCache.Message" = "Successfully cleaned %@ cache."; -"Common.Alerts.CleanCache.Title" = "Clean Cache"; -"Common.Alerts.Common.PleaseTryAgain" = "Var god försök igen."; -"Common.Alerts.Common.PleaseTryAgainLater" = "Var god försök igen senare."; -"Common.Alerts.DeletePost.Delete" = "Radera"; -"Common.Alerts.DeletePost.Title" = "Are you sure you want to delete this post?"; +"Common.Alerts.CleanCache.Message" = "%@ välimuisti tyhjennetty onnistuneesti."; +"Common.Alerts.CleanCache.Title" = "Puhdista välimuisti"; +"Common.Alerts.Common.PleaseTryAgain" = "Yritä uudelleen."; +"Common.Alerts.Common.PleaseTryAgainLater" = "Yritä uudelleen myöhemmin."; +"Common.Alerts.DeletePost.Message" = "Are you sure you want to delete this post?"; +"Common.Alerts.DeletePost.Title" = "Haluatko varmasti poistaa tämän julkaisun?"; "Common.Alerts.DiscardPostContent.Message" = "Confirm to discard composed post content."; -"Common.Alerts.DiscardPostContent.Title" = "Discard Draft"; -"Common.Alerts.EditProfileFailure.Message" = "Cannot edit profile. Please try again."; -"Common.Alerts.EditProfileFailure.Title" = "Edit Profile Error"; -"Common.Alerts.PublishPostFailure.AttachmentsMessage.MoreThanOneVideo" = "Cannot attach more than one video."; +"Common.Alerts.DiscardPostContent.Title" = "Hylkää luonnos"; +"Common.Alerts.EditProfileFailure.Message" = "Profiilia ei voida muoka. Yritä uudelleen."; +"Common.Alerts.EditProfileFailure.Title" = "Virhe profiilin muokkauksessa"; +"Common.Alerts.PublishPostFailure.AttachmentsMessage.MoreThanOneVideo" = "Ei voi liittä yhtä videota enempää."; "Common.Alerts.PublishPostFailure.AttachmentsMessage.VideoAttachWithPhoto" = "Cannot attach a video to a post that already contains images."; -"Common.Alerts.PublishPostFailure.Message" = "Failed to publish the post. -Please check your internet connection."; -"Common.Alerts.PublishPostFailure.Title" = "Publish Failure"; +"Common.Alerts.PublishPostFailure.Message" = "Julkaisun julkaiseminen epäonnistui. +Tarkista internet-yhteytesi."; +"Common.Alerts.PublishPostFailure.Title" = "Julkaiseminen epäonnistui"; "Common.Alerts.SavePhotoFailure.Message" = "Please enable the photo library access permission to save the photo."; -"Common.Alerts.SavePhotoFailure.Title" = "Save Photo Failure"; -"Common.Alerts.ServerError.Title" = "Serverfel"; -"Common.Alerts.SignOut.Confirm" = "Sign Out"; -"Common.Alerts.SignOut.Message" = "Är du säker på att du vill logga ut?"; -"Common.Alerts.SignOut.Title" = "Sign Out"; -"Common.Alerts.SignUpFailure.Title" = "Sign Up Failure"; -"Common.Alerts.VoteFailure.PollEnded" = "Omröstningen har avslutats"; +"Common.Alerts.SavePhotoFailure.Title" = "Kuvan tallentaminen epäonnistui"; +"Common.Alerts.ServerError.Title" = "Palvelinvirhe"; +"Common.Alerts.SignOut.Confirm" = "Kirjaudu ulos"; +"Common.Alerts.SignOut.Message" = "Haluatko varmasti kirjautua ulos?"; +"Common.Alerts.SignOut.Title" = "Kirjaudu ulos"; +"Common.Alerts.SignUpFailure.Title" = "Rekisteröinti epäonnistui"; +"Common.Alerts.VoteFailure.PollEnded" = "Kysely on päättynyt"; "Common.Alerts.VoteFailure.Title" = "Vote Failure"; -"Common.Controls.Actions.Add" = "Add"; -"Common.Controls.Actions.Back" = "Back"; -"Common.Controls.Actions.BlockDomain" = "Block %@"; -"Common.Controls.Actions.Cancel" = "Avbryt"; -"Common.Controls.Actions.Compose" = "Compose"; -"Common.Controls.Actions.Confirm" = "Confirm"; -"Common.Controls.Actions.Continue" = "Fortsätt"; -"Common.Controls.Actions.CopyPhoto" = "Copy Photo"; -"Common.Controls.Actions.Delete" = "Radera"; -"Common.Controls.Actions.Discard" = "Discard"; -"Common.Controls.Actions.Done" = "Done"; -"Common.Controls.Actions.Edit" = "Redigera"; -"Common.Controls.Actions.FindPeople" = "Find people to follow"; +"Common.Controls.Actions.Add" = "Lisää"; +"Common.Controls.Actions.Back" = "Takaisin"; +"Common.Controls.Actions.BlockDomain" = "Estä %@"; +"Common.Controls.Actions.Cancel" = "Kumoa"; +"Common.Controls.Actions.Compose" = "Koosta"; +"Common.Controls.Actions.Confirm" = "Vahvista"; +"Common.Controls.Actions.Continue" = "Jatka"; +"Common.Controls.Actions.CopyPhoto" = "Kopioi kuva"; +"Common.Controls.Actions.Delete" = "Poista"; +"Common.Controls.Actions.Discard" = "Hylkää"; +"Common.Controls.Actions.Done" = "Valmis"; +"Common.Controls.Actions.Edit" = "Muokkaa"; +"Common.Controls.Actions.FindPeople" = "Löydä tilejä seurattavaksi"; "Common.Controls.Actions.ManuallySearch" = "Manually search instead"; -"Common.Controls.Actions.Next" = "Next"; +"Common.Controls.Actions.Next" = "Seuraava"; "Common.Controls.Actions.Ok" = "OK"; -"Common.Controls.Actions.Open" = "Open"; -"Common.Controls.Actions.OpenInSafari" = "Öppna i Safari"; -"Common.Controls.Actions.Preview" = "Preview"; -"Common.Controls.Actions.Previous" = "Previous"; -"Common.Controls.Actions.Remove" = "Remove"; -"Common.Controls.Actions.Reply" = "Reply"; -"Common.Controls.Actions.ReportUser" = "Rapportera %@"; -"Common.Controls.Actions.Save" = "Spara"; -"Common.Controls.Actions.SavePhoto" = "Save Photo"; -"Common.Controls.Actions.SeeMore" = "See More"; -"Common.Controls.Actions.Settings" = "Inställningar"; -"Common.Controls.Actions.Share" = "Dela"; -"Common.Controls.Actions.SharePost" = "Share Post"; -"Common.Controls.Actions.ShareUser" = "Dela %@"; -"Common.Controls.Actions.SignIn" = "Sign In"; -"Common.Controls.Actions.SignUp" = "Sign Up"; -"Common.Controls.Actions.Skip" = "Skip"; -"Common.Controls.Actions.TakePhoto" = "Take Photo"; -"Common.Controls.Actions.TryAgain" = "Försök igen"; -"Common.Controls.Actions.UnblockDomain" = "Unblock %@"; -"Common.Controls.Friendship.Block" = "Block"; -"Common.Controls.Friendship.BlockDomain" = "Block %@"; -"Common.Controls.Friendship.BlockUser" = "Block %@"; -"Common.Controls.Friendship.Blocked" = "Blocked"; -"Common.Controls.Friendship.EditInfo" = "Edit Info"; -"Common.Controls.Friendship.Follow" = "Följ"; -"Common.Controls.Friendship.Following" = "Följer"; -"Common.Controls.Friendship.Mute" = "Mute"; -"Common.Controls.Friendship.MuteUser" = "Mute %@"; -"Common.Controls.Friendship.Muted" = "Muted"; -"Common.Controls.Friendship.Pending" = "Pending"; -"Common.Controls.Friendship.Request" = "Request"; -"Common.Controls.Friendship.Unblock" = "Unblock"; +"Common.Controls.Actions.Open" = "Avaa"; +"Common.Controls.Actions.OpenInBrowser" = "Open in Browser"; +"Common.Controls.Actions.OpenInSafari" = "Avaa Safarissa"; +"Common.Controls.Actions.Preview" = "Esikatselu"; +"Common.Controls.Actions.Previous" = "Edellinen"; +"Common.Controls.Actions.Remove" = "Poista"; +"Common.Controls.Actions.Reply" = "Vastaa"; +"Common.Controls.Actions.ReportUser" = "Ilmianna %@"; +"Common.Controls.Actions.Save" = "Tallenna"; +"Common.Controls.Actions.SavePhoto" = "Tallenna kuva"; +"Common.Controls.Actions.SeeMore" = "Näytä lisää"; +"Common.Controls.Actions.Settings" = "Asetukset"; +"Common.Controls.Actions.Share" = "Jaa"; +"Common.Controls.Actions.SharePost" = "Jaa julkaisu"; +"Common.Controls.Actions.ShareUser" = "Jaa %@"; +"Common.Controls.Actions.SignIn" = "Kirjaudu sisään"; +"Common.Controls.Actions.SignUp" = "Rekisteröidy"; +"Common.Controls.Actions.Skip" = "Ohita"; +"Common.Controls.Actions.TakePhoto" = "Ota kuva"; +"Common.Controls.Actions.TryAgain" = "Yritä uudelleen"; +"Common.Controls.Actions.UnblockDomain" = "Poista esto %@"; +"Common.Controls.Friendship.Block" = "Estä"; +"Common.Controls.Friendship.BlockDomain" = "Estä %@"; +"Common.Controls.Friendship.BlockUser" = "Estä %@"; +"Common.Controls.Friendship.Blocked" = "Estetty"; +"Common.Controls.Friendship.EditInfo" = "Muokkaa profiilia"; +"Common.Controls.Friendship.Follow" = "Seuraa"; +"Common.Controls.Friendship.Following" = "Seurataan"; +"Common.Controls.Friendship.Mute" = "Mykistä"; +"Common.Controls.Friendship.MuteUser" = "Mykistä %@"; +"Common.Controls.Friendship.Muted" = "Mykistetty"; +"Common.Controls.Friendship.Pending" = "Pyydetty"; +"Common.Controls.Friendship.Request" = "Pyydä"; +"Common.Controls.Friendship.Unblock" = "Poista esto"; "Common.Controls.Friendship.UnblockUser" = "Unblock %@"; -"Common.Controls.Friendship.Unmute" = "Unmute"; -"Common.Controls.Friendship.UnmuteUser" = "Unmute %@"; -"Common.Controls.Keyboard.Common.ComposeNewPost" = "Compose New Post"; -"Common.Controls.Keyboard.Common.OpenSettings" = "Open Settings"; -"Common.Controls.Keyboard.Common.ShowFavorites" = "Show Favorites"; -"Common.Controls.Keyboard.Common.SwitchToTab" = "Switch to %@"; -"Common.Controls.Keyboard.SegmentedControl.NextSection" = "Next Section"; +"Common.Controls.Friendship.Unmute" = "Poista mykistys"; +"Common.Controls.Friendship.UnmuteUser" = "Poista mykistys tililtä %@"; +"Common.Controls.Keyboard.Common.ComposeNewPost" = "Koosta uusi julkaisu"; +"Common.Controls.Keyboard.Common.OpenSettings" = "Avaa asetukset"; +"Common.Controls.Keyboard.Common.ShowFavorites" = "Näytä suosikit"; +"Common.Controls.Keyboard.Common.SwitchToTab" = "Vaihda %@"; +"Common.Controls.Keyboard.SegmentedControl.NextSection" = "Seuraava lohko"; "Common.Controls.Keyboard.SegmentedControl.PreviousSection" = "Previous Section"; -"Common.Controls.Keyboard.Timeline.NextStatus" = "Next Post"; -"Common.Controls.Keyboard.Timeline.OpenAuthorProfile" = "Open Author's Profile"; -"Common.Controls.Keyboard.Timeline.OpenRebloggerProfile" = "Open Reblogger's Profile"; -"Common.Controls.Keyboard.Timeline.OpenStatus" = "Open Post"; +"Common.Controls.Keyboard.Timeline.NextStatus" = "Seuraava julkaisu"; +"Common.Controls.Keyboard.Timeline.OpenAuthorProfile" = "Avaa tekijän profiili"; +"Common.Controls.Keyboard.Timeline.OpenRebloggerProfile" = "Avaa edelleen jakajan profiili"; +"Common.Controls.Keyboard.Timeline.OpenStatus" = "Avaa julkaisu"; "Common.Controls.Keyboard.Timeline.PreviewImage" = "Preview Image"; -"Common.Controls.Keyboard.Timeline.PreviousStatus" = "Previous Post"; -"Common.Controls.Keyboard.Timeline.ReplyStatus" = "Reply to Post"; -"Common.Controls.Keyboard.Timeline.ToggleContentWarning" = "Toggle Content Warning"; +"Common.Controls.Keyboard.Timeline.PreviousStatus" = "Edellinen julkaisu"; +"Common.Controls.Keyboard.Timeline.ReplyStatus" = "Vastaa julkaisuun"; +"Common.Controls.Keyboard.Timeline.ToggleContentWarning" = "Vaihda sisältövaroitus"; "Common.Controls.Keyboard.Timeline.ToggleFavorite" = "Toggle Favorite on Post"; "Common.Controls.Keyboard.Timeline.ToggleReblog" = "Toggle Reblog on Post"; "Common.Controls.Status.Actions.Favorite" = "Favorite"; -"Common.Controls.Status.Actions.Menu" = "Meny"; -"Common.Controls.Status.Actions.Reblog" = "Reblog"; -"Common.Controls.Status.Actions.Reply" = "Reply"; +"Common.Controls.Status.Actions.Hide" = "Dölj"; +"Common.Controls.Status.Actions.Menu" = "Valikko"; +"Common.Controls.Status.Actions.Reblog" = "Jaa edelleen"; +"Common.Controls.Status.Actions.Reply" = "Vastaa"; "Common.Controls.Status.Actions.Unfavorite" = "Unfavorite"; -"Common.Controls.Status.Actions.Unreblog" = "Undo reblog"; -"Common.Controls.Status.ContentWarning" = "Content Warning"; -"Common.Controls.Status.MediaContentWarning" = "Tap anywhere to reveal"; -"Common.Controls.Status.Poll.Closed" = "Closed"; +"Common.Controls.Status.Actions.Unreblog" = "Peru edelleen jako"; +"Common.Controls.Status.ContentWarning" = "Sisältövaroitus"; +"Common.Controls.Status.MediaContentWarning" = "Napauta mistä tahansa paljastaaksesi"; +"Common.Controls.Status.Poll.Closed" = "Suljettu"; "Common.Controls.Status.Poll.Vote" = "Vote"; -"Common.Controls.Status.ShowPost" = "Show Post"; -"Common.Controls.Status.ShowUserProfile" = "Show user profile"; -"Common.Controls.Status.Tag.Email" = "Email"; +"Common.Controls.Status.ShowPost" = "Näytä julkaisu"; +"Common.Controls.Status.ShowUserProfile" = "Näytä tili"; +"Common.Controls.Status.Tag.Email" = "Sähköposti"; "Common.Controls.Status.Tag.Emoji" = "Emoji"; -"Common.Controls.Status.Tag.Hashtag" = "Hashtag"; -"Common.Controls.Status.Tag.Link" = "Link"; +"Common.Controls.Status.Tag.Hashtag" = "Hashtagi"; +"Common.Controls.Status.Tag.Link" = "Linkki"; "Common.Controls.Status.Tag.Mention" = "Mention"; "Common.Controls.Status.Tag.Url" = "URL"; -"Common.Controls.Status.UserReblogged" = "%@ reblogged"; -"Common.Controls.Status.UserRepliedTo" = "Replied to %@"; -"Common.Controls.Tabs.Home" = "Home"; -"Common.Controls.Tabs.Notification" = "Notification"; -"Common.Controls.Tabs.Profile" = "Profil"; -"Common.Controls.Tabs.Search" = "Search"; -"Common.Controls.Timeline.Filtered" = "Filtered"; -"Common.Controls.Timeline.Header.BlockedWarning" = "You can’t view this user’s profile -until they unblock you."; -"Common.Controls.Timeline.Header.BlockingWarning" = "You can’t view this user's profile -until you unblock them. -Your profile looks like this to them."; -"Common.Controls.Timeline.Header.NoStatusFound" = "No Post Found"; -"Common.Controls.Timeline.Header.SuspendedWarning" = "This user has been suspended."; -"Common.Controls.Timeline.Header.UserBlockedWarning" = "You can’t view %@’s profile -until they unblock you."; -"Common.Controls.Timeline.Header.UserBlockingWarning" = "You can’t view %@’s profile -until you unblock them. -Your profile looks like this to them."; -"Common.Controls.Timeline.Header.UserSuspendedWarning" = "%@’s account has been suspended."; -"Common.Controls.Timeline.Loader.LoadMissingPosts" = "Load missing posts"; -"Common.Controls.Timeline.Loader.LoadingMissingPosts" = "Loading missing posts..."; -"Common.Controls.Timeline.Loader.ShowMoreReplies" = "Visa fler svar"; -"Common.Controls.Timeline.Timestamp.Now" = "Now"; -"Scene.AccountList.AddAccount" = "Lägg till konto"; -"Scene.AccountList.DismissAccountSwitcher" = "Dismiss Account Switcher"; -"Scene.AccountList.TabBarHint" = "Current selected profile: %@. Double tap then hold to show account switcher"; -"Scene.Compose.Accessibility.AppendAttachment" = "Add Attachment"; -"Scene.Compose.Accessibility.AppendPoll" = "Add Poll"; -"Scene.Compose.Accessibility.CustomEmojiPicker" = "Custom Emoji Picker"; -"Scene.Compose.Accessibility.DisableContentWarning" = "Disable Content Warning"; -"Scene.Compose.Accessibility.EnableContentWarning" = "Enable Content Warning"; -"Scene.Compose.Accessibility.PostVisibilityMenu" = "Post Visibility Menu"; -"Scene.Compose.Accessibility.RemovePoll" = "Remove Poll"; +"Common.Controls.Status.UserReblogged" = "%@ jakoi edelleen"; +"Common.Controls.Status.UserRepliedTo" = "Vastasi %@:lle"; +"Common.Controls.Status.Visibility.Direct" = "Only mentioned user can see this post."; +"Common.Controls.Status.Visibility.Private" = "Only their followers can see this post."; +"Common.Controls.Status.Visibility.PrivateFromMe" = "Only my followers can see this post."; +"Common.Controls.Status.Visibility.Unlisted" = "Everyone can see this post but not display in the public timeline."; +"Common.Controls.Tabs.Home" = "Koti"; +"Common.Controls.Tabs.Notification" = "Ilmoitus"; +"Common.Controls.Tabs.Profile" = "Profiili"; +"Common.Controls.Tabs.Search" = "Haku"; +"Common.Controls.Timeline.Filtered" = "Suodatettu"; +"Common.Controls.Timeline.Header.BlockedWarning" = "Et voi tarkastella tämän tilin profiilia +ennen kuin hän poistaa eston."; +"Common.Controls.Timeline.Header.BlockingWarning" = "Et voi tarkastella tämän tilin profiilia +ennen kuin poistat sen esto. +Profiilisi näyttää tältä hänelle."; +"Common.Controls.Timeline.Header.NoStatusFound" = "Julkaisua ei löytynyt"; +"Common.Controls.Timeline.Header.SuspendedWarning" = "Tämä tili on lakkautettu."; +"Common.Controls.Timeline.Header.UserBlockedWarning" = "Et voi tarkastella tilin %@ profiilia +ennen kuin hän poistaa eston."; +"Common.Controls.Timeline.Header.UserBlockingWarning" = "Et voi tarkastella tilin %@ profiilia +ennen kuin poistat sen esto. +Profiilisi näyttää tältä hänelle."; +"Common.Controls.Timeline.Header.UserSuspendedWarning" = "Tili %@ on lakkautettu."; +"Common.Controls.Timeline.Loader.LoadMissingPosts" = "Lataa puuttuvat julkaisut"; +"Common.Controls.Timeline.Loader.LoadingMissingPosts" = "Ladataan puuttuvia julkaisuja..."; +"Common.Controls.Timeline.Loader.ShowMoreReplies" = "Näytä lisää vastauksia"; +"Common.Controls.Timeline.Timestamp.Now" = "Nyt"; +"Scene.AccountList.AddAccount" = "Lisää tili"; +"Scene.AccountList.DismissAccountSwitcher" = "Sulje tilin vaihtaja"; +"Scene.AccountList.TabBarHint" = "Nykyinen valittu profiili: %@. Kaksoisnapauta ja pidä sitten painettuna näytääksesi tilin vaihtajan"; +"Scene.Compose.Accessibility.AppendAttachment" = "Lisää liite"; +"Scene.Compose.Accessibility.AppendPoll" = "Lisää kysely"; +"Scene.Compose.Accessibility.CustomEmojiPicker" = "Mukautettu emojivalitsin"; +"Scene.Compose.Accessibility.DisableContentWarning" = "Poista sisältövaroitus käytöstä"; +"Scene.Compose.Accessibility.EnableContentWarning" = "Ota sisältövaroitus käyttöön"; +"Scene.Compose.Accessibility.PostVisibilityMenu" = "Julkaisun näkyvyysvalikko"; +"Scene.Compose.Accessibility.RemovePoll" = "Poista kysely"; "Scene.Compose.Attachment.AttachmentBroken" = "This %@ is broken and can’t be uploaded to Mastodon."; -"Scene.Compose.Attachment.DescriptionPhoto" = "Describe the photo for the visually-impaired..."; -"Scene.Compose.Attachment.DescriptionVideo" = "Describe the video for the visually-impaired..."; -"Scene.Compose.Attachment.Photo" = "photo"; +"Scene.Compose.Attachment.DescriptionPhoto" = "Kuvaile kuva näkövammaisille..."; +"Scene.Compose.Attachment.DescriptionVideo" = "Kuvaile video näkövammaisille..."; +"Scene.Compose.Attachment.Photo" = "kuva"; "Scene.Compose.Attachment.Video" = "video"; "Scene.Compose.AutoComplete.SpaceToAdd" = "Space to add"; -"Scene.Compose.ComposeAction" = "Publicera"; -"Scene.Compose.ContentInputPlaceholder" = "Type or paste what’s on your mind"; -"Scene.Compose.ContentWarning.Placeholder" = "Write an accurate warning here..."; -"Scene.Compose.Keyboard.AppendAttachmentEntry" = "Add Attachment - %@"; -"Scene.Compose.Keyboard.DiscardPost" = "Discard Post"; -"Scene.Compose.Keyboard.PublishPost" = "Publish Post"; -"Scene.Compose.Keyboard.SelectVisibilityEntry" = "Select Visibility - %@"; -"Scene.Compose.Keyboard.ToggleContentWarning" = "Toggle Content Warning"; -"Scene.Compose.Keyboard.TogglePoll" = "Toggle Poll"; -"Scene.Compose.MediaSelection.Browse" = "Bläddra"; -"Scene.Compose.MediaSelection.Camera" = "Take Photo"; -"Scene.Compose.MediaSelection.PhotoLibrary" = "Photo Library"; -"Scene.Compose.Poll.DurationTime" = "Varaktighet: %@"; -"Scene.Compose.Poll.OneDay" = "1 Day"; -"Scene.Compose.Poll.OneHour" = "1 Hour"; -"Scene.Compose.Poll.OptionNumber" = "Option %ld"; -"Scene.Compose.Poll.SevenDays" = "7 Days"; -"Scene.Compose.Poll.SixHours" = "6 Hours"; -"Scene.Compose.Poll.ThirtyMinutes" = "30 minuter"; -"Scene.Compose.Poll.ThreeDays" = "3 Days"; -"Scene.Compose.ReplyingToUser" = "replying to %@"; -"Scene.Compose.Title.NewPost" = "New Post"; -"Scene.Compose.Title.NewReply" = "New Reply"; -"Scene.Compose.Visibility.Direct" = "Only people I mention"; -"Scene.Compose.Visibility.Private" = "Followers only"; -"Scene.Compose.Visibility.Public" = "Public"; -"Scene.Compose.Visibility.Unlisted" = "Unlisted"; -"Scene.ConfirmEmail.Button.DontReceiveEmail" = "I never got an email"; -"Scene.ConfirmEmail.Button.OpenEmailApp" = "Open Email App"; -"Scene.ConfirmEmail.DontReceiveEmail.Description" = "Check if your email address is correct as well as your junk folder if you haven’t."; -"Scene.ConfirmEmail.DontReceiveEmail.ResendEmail" = "Resend Email"; -"Scene.ConfirmEmail.DontReceiveEmail.Title" = "Check your email"; -"Scene.ConfirmEmail.OpenEmailApp.Description" = "We just sent you an email. Check your junk folder if you haven’t."; -"Scene.ConfirmEmail.OpenEmailApp.Mail" = "Mail"; -"Scene.ConfirmEmail.OpenEmailApp.OpenEmailClient" = "Open Email Client"; -"Scene.ConfirmEmail.OpenEmailApp.Title" = "Check your inbox."; -"Scene.ConfirmEmail.Subtitle" = "We just sent an email to %@, -tap the link to confirm your account."; -"Scene.ConfirmEmail.Title" = "One last thing."; -"Scene.Favorite.Title" = "Your Favorites"; -"Scene.Follower.Footer" = "Followers from other servers are not displayed."; -"Scene.Following.Footer" = "Follows from other servers are not displayed."; -"Scene.HomeTimeline.NavigationBarState.NewPosts" = "See new posts"; -"Scene.HomeTimeline.NavigationBarState.Offline" = "Offline"; -"Scene.HomeTimeline.NavigationBarState.Published" = "Published!"; -"Scene.HomeTimeline.NavigationBarState.Publishing" = "Publishing post..."; -"Scene.HomeTimeline.Title" = "Home"; -"Scene.Notification.Keyobard.ShowEverything" = "Show Everything"; -"Scene.Notification.Keyobard.ShowMentions" = "Show Mentions"; -"Scene.Notification.Title.Everything" = "Everything"; -"Scene.Notification.Title.Mentions" = "Mentions"; -"Scene.Notification.UserFavorited Your Post" = "%@ favorited your post"; -"Scene.Notification.UserFollowedYou" = "%@ följde dig"; -"Scene.Notification.UserMentionedYou" = "%@ nämnde dig"; -"Scene.Notification.UserRebloggedYourPost" = "%@ reblogged your post"; -"Scene.Notification.UserRequestedToFollowYou" = "%@ har begärt att följa dig"; -"Scene.Notification.UserYourPollHasEnded" = "%@ Omröstningen har avslutats"; -"Scene.Preview.Keyboard.ClosePreview" = "Close Preview"; -"Scene.Preview.Keyboard.ShowNext" = "Show Next"; -"Scene.Preview.Keyboard.ShowPrevious" = "Show Previous"; -"Scene.Profile.Dashboard.Followers" = "followers"; -"Scene.Profile.Dashboard.Following" = "following"; -"Scene.Profile.Dashboard.Posts" = "posts"; -"Scene.Profile.Fields.AddRow" = "Add Row"; -"Scene.Profile.Fields.Placeholder.Content" = "Content"; -"Scene.Profile.Fields.Placeholder.Label" = "Label"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Message" = "Confirm to unblock %@"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Title" = "Unblock Account"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Message" = "Confirm to unmute %@"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Title" = "Unmute Account"; +"Scene.Compose.ComposeAction" = "Julkaise"; +"Scene.Compose.ContentInputPlaceholder" = "Kirjoita tai liitä, siitä mitä ajattelet"; +"Scene.Compose.ContentWarning.Placeholder" = "Kirjoita tarkka varoitus tähän..."; +"Scene.Compose.Keyboard.AppendAttachmentEntry" = "Lisää liite - %@"; +"Scene.Compose.Keyboard.DiscardPost" = "Hylkää julkaisu"; +"Scene.Compose.Keyboard.PublishPost" = "Julkaise julkaisu"; +"Scene.Compose.Keyboard.SelectVisibilityEntry" = "Valitse näkyvyys - %@"; +"Scene.Compose.Keyboard.ToggleContentWarning" = "Vaihda sisältövaroitus"; +"Scene.Compose.Keyboard.TogglePoll" = "Vaihda kysely"; +"Scene.Compose.MediaSelection.Browse" = "Selaa"; +"Scene.Compose.MediaSelection.Camera" = "Ota kuva"; +"Scene.Compose.MediaSelection.PhotoLibrary" = "Kuvakirjasto"; +"Scene.Compose.Poll.DurationTime" = "Kesto: %@"; +"Scene.Compose.Poll.OneDay" = "1 päivä"; +"Scene.Compose.Poll.OneHour" = "1 tunti"; +"Scene.Compose.Poll.OptionNumber" = "Vaihtoehto %ld"; +"Scene.Compose.Poll.SevenDays" = "7 päivää"; +"Scene.Compose.Poll.SixHours" = "6 tuntia"; +"Scene.Compose.Poll.ThirtyMinutes" = "30 minuuttia"; +"Scene.Compose.Poll.ThreeDays" = "3 päivää"; +"Scene.Compose.ReplyingToUser" = "vastaamassa tilille %@"; +"Scene.Compose.Title.NewPost" = "Uusi julkaisu"; +"Scene.Compose.Title.NewReply" = "Uusi vastaus"; +"Scene.Compose.Visibility.Direct" = "Vain mainitsemani tilit"; +"Scene.Compose.Visibility.Private" = "Vain seuraajat"; +"Scene.Compose.Visibility.Public" = "Julkinen"; +"Scene.Compose.Visibility.Unlisted" = "Listaamaton"; +"Scene.ConfirmEmail.Button.OpenEmailApp" = "Avaa sähköpostisovellus"; +"Scene.ConfirmEmail.Button.Resend" = "Resend"; +"Scene.ConfirmEmail.DontReceiveEmail.Description" = "Tarkista, että sähköpostiosoitteesi on oikea, sekä roskapostikansiosi, jos et vielä ole."; +"Scene.ConfirmEmail.DontReceiveEmail.ResendEmail" = "Lähetä sähköposti uudelleen"; +"Scene.ConfirmEmail.DontReceiveEmail.Title" = "Tarkista sähköpostisi"; +"Scene.ConfirmEmail.OpenEmailApp.Description" = "Lähetimme sinulle juuri sähköpostin. Tarkista myös roskapostikansiosi, jos et vielä ole."; +"Scene.ConfirmEmail.OpenEmailApp.Mail" = "Sähköposti"; +"Scene.ConfirmEmail.OpenEmailApp.OpenEmailClient" = "Avaa sähköpostisovellus"; +"Scene.ConfirmEmail.OpenEmailApp.Title" = "Tarkasta postilaatikkosi."; +"Scene.ConfirmEmail.Subtitle" = "Lähetimme juuri sähköpostin osoitteeseen %@, napauta siinä olevaa linkkiä vahvistaaksesi tilisi."; +"Scene.ConfirmEmail.Title" = "Viimeinen asia."; +"Scene.Favorite.Title" = "Omat suosikit"; +"Scene.Follower.Footer" = "Seuraajia muilta palvelimilta ei näytetä."; +"Scene.Following.Footer" = "Seurauksia muilta palvelimilta ei näytetä."; +"Scene.HomeTimeline.NavigationBarState.NewPosts" = "Uusia julkaisuja"; +"Scene.HomeTimeline.NavigationBarState.Offline" = "Yhteydetön"; +"Scene.HomeTimeline.NavigationBarState.Published" = "Julkaistu!"; +"Scene.HomeTimeline.NavigationBarState.Publishing" = "Julkaistaan julkaisua..."; +"Scene.HomeTimeline.Title" = "Koti"; +"Scene.Notification.Keyobard.ShowEverything" = "Näytä kaikki"; +"Scene.Notification.Keyobard.ShowMentions" = "Näytä maininnat"; +"Scene.Notification.NotificationDescription.FavoritedYourPost" = "favorited your post"; +"Scene.Notification.NotificationDescription.FollowedYou" = "followed you"; +"Scene.Notification.NotificationDescription.MentionedYou" = "nämnde dig"; +"Scene.Notification.NotificationDescription.PollHasEnded" = "poll has ended"; +"Scene.Notification.NotificationDescription.RebloggedYourPost" = "reblogged your post"; +"Scene.Notification.NotificationDescription.RequestToFollowYou" = "request to follow you"; +"Scene.Notification.Title.Everything" = "Kaikki"; +"Scene.Notification.Title.Mentions" = "Maininnat"; +"Scene.Preview.Keyboard.ClosePreview" = "Sulje esikatselu"; +"Scene.Preview.Keyboard.ShowNext" = "Näytä seuraava"; +"Scene.Preview.Keyboard.ShowPrevious" = "Näytä edellinen"; +"Scene.Profile.Dashboard.Followers" = "seuraajat"; +"Scene.Profile.Dashboard.Following" = "seurataan"; +"Scene.Profile.Dashboard.Posts" = "julkaisut"; +"Scene.Profile.Fields.AddRow" = "Lisää rivi"; +"Scene.Profile.Fields.Placeholder.Content" = "Sisältö"; +"Scene.Profile.Fields.Placeholder.Label" = "Nimi"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Message" = "Confirm to block %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title" = "Block Account"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Message" = "Confirm to mute %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Title" = "Mute Account"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Message" = "Confirm to unblock %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Title" = "Unblock Account"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Message" = "Vahvista, että haluat poistaa mykistyksen tililtä %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Title" = "Poista tilin mykistys"; +"Scene.Profile.SegmentedControl.About" = "Om"; "Scene.Profile.SegmentedControl.Media" = "Media"; -"Scene.Profile.SegmentedControl.Posts" = "Posts"; -"Scene.Profile.SegmentedControl.Replies" = "Replies"; -"Scene.Register.Error.Item.Agreement" = "Agreement"; -"Scene.Register.Error.Item.Email" = "Email"; +"Scene.Profile.SegmentedControl.Posts" = "Julkaisut"; +"Scene.Profile.SegmentedControl.PostsAndReplies" = "Posts and Replies"; +"Scene.Profile.SegmentedControl.Replies" = "Vastaukset"; +"Scene.Register.Error.Item.Agreement" = "Hyväksy"; +"Scene.Register.Error.Item.Email" = "Sähköposti"; "Scene.Register.Error.Item.Locale" = "Locale"; -"Scene.Register.Error.Item.Password" = "Password"; -"Scene.Register.Error.Item.Reason" = "Reason"; -"Scene.Register.Error.Item.Username" = "Användarnamn"; -"Scene.Register.Error.Reason.Accepted" = "%@ must be accepted"; -"Scene.Register.Error.Reason.Blank" = "%@ is required"; -"Scene.Register.Error.Reason.Blocked" = "%@ contains a disallowed email provider"; -"Scene.Register.Error.Reason.Inclusion" = "%@ is not a supported value"; -"Scene.Register.Error.Reason.Invalid" = "%@ is invalid"; +"Scene.Register.Error.Item.Password" = "Salasana"; +"Scene.Register.Error.Item.Reason" = "Syy"; +"Scene.Register.Error.Item.Username" = "Käyttäjänimi"; +"Scene.Register.Error.Reason.Accepted" = "%@ täytyy hyväksyä"; +"Scene.Register.Error.Reason.Blank" = "%@ vaaditaan"; +"Scene.Register.Error.Reason.Blocked" = "%@ sisältää estetyn sähköpostipalveluntarjoajan"; +"Scene.Register.Error.Reason.Inclusion" = "%@ ei ole tuettu arvo"; +"Scene.Register.Error.Reason.Invalid" = "%@ on virheellinen"; "Scene.Register.Error.Reason.Reserved" = "%@ is a reserved keyword"; -"Scene.Register.Error.Reason.Taken" = "%@ is already in use"; -"Scene.Register.Error.Reason.TooLong" = "%@ is too long"; -"Scene.Register.Error.Reason.TooShort" = "%@ is too short"; -"Scene.Register.Error.Reason.Unreachable" = "%@ does not seem to exist"; -"Scene.Register.Error.Special.EmailInvalid" = "This is not a valid email address"; -"Scene.Register.Error.Special.PasswordTooShort" = "Password is too short (must be at least 8 characters)"; -"Scene.Register.Error.Special.UsernameInvalid" = "Username must only contain alphanumeric characters and underscores"; -"Scene.Register.Error.Special.UsernameTooLong" = "Username is too long (can’t be longer than 30 characters)"; -"Scene.Register.Input.Avatar.Delete" = "Radera"; -"Scene.Register.Input.DisplayName.Placeholder" = "display name"; -"Scene.Register.Input.Email.Placeholder" = "email"; -"Scene.Register.Input.Invite.RegistrationUserInviteRequest" = "Why do you want to join?"; -"Scene.Register.Input.Password.Hint" = "Your password needs at least eight characters"; -"Scene.Register.Input.Password.Placeholder" = "password"; -"Scene.Register.Input.Username.DuplicatePrompt" = "This username is taken."; -"Scene.Register.Input.Username.Placeholder" = "username"; -"Scene.Register.Title" = "Tell us about you."; -"Scene.Report.Content1" = "Are there any other posts you’d like to add to the report?"; -"Scene.Report.Content2" = "Is there anything the moderators should know about this report?"; -"Scene.Report.Send" = "Send Report"; -"Scene.Report.SkipToSend" = "Send without comment"; -"Scene.Report.Step1" = "Steg 1 av 2"; -"Scene.Report.Step2" = "Steg 2 av 2"; -"Scene.Report.TextPlaceholder" = "Type or paste additional comments"; -"Scene.Report.Title" = "Rapportera %@"; -"Scene.Search.Recommend.Accounts.Description" = "You may like to follow these accounts"; -"Scene.Search.Recommend.Accounts.Follow" = "Följ"; -"Scene.Search.Recommend.Accounts.Title" = "Accounts you might like"; -"Scene.Search.Recommend.ButtonText" = "See All"; -"Scene.Search.Recommend.HashTag.Description" = "Hashtags that are getting quite a bit of attention"; -"Scene.Search.Recommend.HashTag.PeopleTalking" = "%@ people are talking"; -"Scene.Search.Recommend.HashTag.Title" = "Trending on Mastodon"; -"Scene.Search.SearchBar.Cancel" = "Avbryt"; -"Scene.Search.SearchBar.Placeholder" = "Search hashtags and users"; -"Scene.Search.Searching.Clear" = "Clear"; -"Scene.Search.Searching.EmptyState.NoResults" = "Inga resultat"; -"Scene.Search.Searching.RecentSearch" = "Recent searches"; -"Scene.Search.Searching.Segment.All" = "All"; -"Scene.Search.Searching.Segment.Hashtags" = "Hashtags"; -"Scene.Search.Searching.Segment.People" = "People"; -"Scene.Search.Searching.Segment.Posts" = "Posts"; -"Scene.Search.Title" = "Search"; -"Scene.ServerPicker.Button.Category.Academia" = "academia"; -"Scene.ServerPicker.Button.Category.Activism" = "activism"; -"Scene.ServerPicker.Button.Category.All" = "All"; -"Scene.ServerPicker.Button.Category.AllAccessiblityDescription" = "Kategori: Alla"; -"Scene.ServerPicker.Button.Category.Art" = "art"; -"Scene.ServerPicker.Button.Category.Food" = "food"; -"Scene.ServerPicker.Button.Category.Furry" = "furry"; -"Scene.ServerPicker.Button.Category.Games" = "games"; -"Scene.ServerPicker.Button.Category.General" = "general"; -"Scene.ServerPicker.Button.Category.Journalism" = "journalism"; -"Scene.ServerPicker.Button.Category.Lgbt" = "lgbt"; -"Scene.ServerPicker.Button.Category.Music" = "music"; -"Scene.ServerPicker.Button.Category.Regional" = "regional"; -"Scene.ServerPicker.Button.Category.Tech" = "tech"; -"Scene.ServerPicker.Button.SeeLess" = "See Less"; -"Scene.ServerPicker.Button.SeeMore" = "See More"; -"Scene.ServerPicker.EmptyState.BadNetwork" = "Something went wrong while loading the data. Check your internet connection."; -"Scene.ServerPicker.EmptyState.FindingServers" = "Finding available servers..."; -"Scene.ServerPicker.EmptyState.NoResults" = "Inga resultat"; -"Scene.ServerPicker.Input.Placeholder" = "Find a server or join your own..."; -"Scene.ServerPicker.Label.Category" = "KATEGORI"; -"Scene.ServerPicker.Label.Language" = "SPRÅK"; -"Scene.ServerPicker.Label.Users" = "ANVÄNDARE"; -"Scene.ServerPicker.Title" = "Pick a server, -any server."; -"Scene.ServerRules.Button.Confirm" = "I Agree"; -"Scene.ServerRules.PrivacyPolicy" = "integritetspolicy"; -"Scene.ServerRules.Prompt" = "By continuing, you’re subject to the terms of service and privacy policy for %@."; -"Scene.ServerRules.Subtitle" = "These rules are set by the admins of %@."; -"Scene.ServerRules.TermsOfService" = "terms of service"; -"Scene.ServerRules.Title" = "Some ground rules."; -"Scene.Settings.Footer.MastodonDescription" = "Mastodon is open source software. You can report issues on GitHub at %@ (%@)"; -"Scene.Settings.Keyboard.CloseSettingsWindow" = "Close Settings Window"; -"Scene.Settings.Section.Appearance.Automatic" = "Automatic"; -"Scene.Settings.Section.Appearance.Dark" = "Always Dark"; -"Scene.Settings.Section.Appearance.Light" = "Always Light"; -"Scene.Settings.Section.Appearance.Title" = "Appearance"; -"Scene.Settings.Section.BoringZone.AccountSettings" = "Account Settings"; -"Scene.Settings.Section.BoringZone.Privacy" = "Integritetspolicy"; -"Scene.Settings.Section.BoringZone.Terms" = "Terms of Service"; -"Scene.Settings.Section.BoringZone.Title" = "The Boring Zone"; -"Scene.Settings.Section.Notifications.Boosts" = "Reblogs my post"; +"Scene.Register.Error.Reason.Taken" = "%@ on jo käytössä"; +"Scene.Register.Error.Reason.TooLong" = "%@ on liian pitkä"; +"Scene.Register.Error.Reason.TooShort" = "%@ on liian lyhyt"; +"Scene.Register.Error.Reason.Unreachable" = "%@ ei näytä olevan olemassa"; +"Scene.Register.Error.Special.EmailInvalid" = "Tämä ei ole kelvollinen sähköpostiosoite"; +"Scene.Register.Error.Special.PasswordTooShort" = "Salasana on liian lyhyt (täytyy olla vähintään 8 merkkiä)"; +"Scene.Register.Error.Special.UsernameInvalid" = "Käyttäjänimi voi sisältää ainoastaan aakkosnumerrisia merkkejä ja alaviivoja"; +"Scene.Register.Error.Special.UsernameTooLong" = "Käyttäjänimi on liian pitkä (ei voi olla pidempi kuin 30 merkkiä)"; +"Scene.Register.Input.Avatar.Delete" = "Poista"; +"Scene.Register.Input.DisplayName.Placeholder" = "näyttönimi"; +"Scene.Register.Input.Email.Placeholder" = "sähköposti"; +"Scene.Register.Input.Invite.RegistrationUserInviteRequest" = "Miksi haluat liittyä?"; +"Scene.Register.Input.Password.Accessibility.Checked" = "checked"; +"Scene.Register.Input.Password.Accessibility.Unchecked" = "unchecked"; +"Scene.Register.Input.Password.CharacterLimit" = "8 characters"; +"Scene.Register.Input.Password.Hint" = "Salasanassasi on oltava vähintään kahdeksan merkkiä"; +"Scene.Register.Input.Password.Placeholder" = "salasana"; +"Scene.Register.Input.Password.Require" = "Your password needs at least:"; +"Scene.Register.Input.Username.DuplicatePrompt" = "Tämä käyttäjänimi on varattu."; +"Scene.Register.Input.Username.Placeholder" = "käyttäjänimi"; +"Scene.Register.Title" = "Kerro meille sinusta."; +"Scene.Report.Content1" = "Onko julkaisuja, joita haluaisit lisätä ilmiantoon?"; +"Scene.Report.Content2" = "Onko valvojien syytä tietää tästä ilmiannosta?"; +"Scene.Report.ReportSentTitle" = "Thanks for reporting, we’ll look into this."; +"Scene.Report.Reported" = "REPORTED"; +"Scene.Report.Send" = "Lähetä ilmianto"; +"Scene.Report.SkipToSend" = "Lähetä ilman kommentteja"; +"Scene.Report.Step1" = "Vaihe 1/2"; +"Scene.Report.Step2" = "Vaihe 2/2"; +"Scene.Report.TextPlaceholder" = "Kirjoita tai liitä lisäkommentteja"; +"Scene.Report.Title" = "Ilmianna %@"; +"Scene.Report.TitleReport" = "Report"; +"Scene.Search.Recommend.Accounts.Description" = "Haluta ehkä seurata näitä tilejä"; +"Scene.Search.Recommend.Accounts.Follow" = "Seuraa"; +"Scene.Search.Recommend.Accounts.Title" = "Saatat pitää näistä tileistä"; +"Scene.Search.Recommend.ButtonText" = "Katso kaikki"; +"Scene.Search.Recommend.HashTag.Description" = "Hashtagit, jotka saavat melkoisesti huomiota"; +"Scene.Search.Recommend.HashTag.PeopleTalking" = "%@ ihmistä puhuu"; +"Scene.Search.Recommend.HashTag.Title" = "Trendaavat Mastodonissa"; +"Scene.Search.SearchBar.Cancel" = "Kumoa"; +"Scene.Search.SearchBar.Placeholder" = "Haku"; +"Scene.Search.Searching.Clear" = "Tyhjennä"; +"Scene.Search.Searching.EmptyState.NoResults" = "Ei hakutuloksia"; +"Scene.Search.Searching.RecentSearch" = "Viimeaikaiset"; +"Scene.Search.Searching.Segment.All" = "Kaikki"; +"Scene.Search.Searching.Segment.Hashtags" = "Hashtagit"; +"Scene.Search.Searching.Segment.People" = "Tilit"; +"Scene.Search.Searching.Segment.Posts" = "Julkaisut"; +"Scene.Search.Title" = "Haku"; +"Scene.ServerPicker.Button.Category.Academia" = "akateeminen"; +"Scene.ServerPicker.Button.Category.Activism" = "aktivismi"; +"Scene.ServerPicker.Button.Category.All" = "Kaikki"; +"Scene.ServerPicker.Button.Category.AllAccessiblityDescription" = "Kategoria: Kaikki"; +"Scene.ServerPicker.Button.Category.Art" = "taide"; +"Scene.ServerPicker.Button.Category.Food" = "ruoka"; +"Scene.ServerPicker.Button.Category.Furry" = "turri"; +"Scene.ServerPicker.Button.Category.Games" = "pelit"; +"Scene.ServerPicker.Button.Category.General" = "yleinen"; +"Scene.ServerPicker.Button.Category.Journalism" = "journalismi"; +"Scene.ServerPicker.Button.Category.Lgbt" = "hlbt"; +"Scene.ServerPicker.Button.Category.Music" = "musiikki"; +"Scene.ServerPicker.Button.Category.Regional" = "alueellinen"; +"Scene.ServerPicker.Button.Category.Tech" = "tekniikka"; +"Scene.ServerPicker.Button.SeeLess" = "Näytä vähemmän"; +"Scene.ServerPicker.Button.SeeMore" = "Näytä lisää"; +"Scene.ServerPicker.EmptyState.BadNetwork" = "Jokin meni pieleen dataa ladatessa. Tarkista internet-yhteytesi."; +"Scene.ServerPicker.EmptyState.FindingServers" = "Etsistään saatavilla olevia palvelimia..."; +"Scene.ServerPicker.EmptyState.NoResults" = "Ei hakutuloksia"; +"Scene.ServerPicker.Input.Placeholder" = "Etsi palvelin tai liity omaan..."; +"Scene.ServerPicker.Label.Category" = "KATEGORIA"; +"Scene.ServerPicker.Label.Language" = "KIELI"; +"Scene.ServerPicker.Label.Users" = "TILIÄ"; +"Scene.ServerPicker.Subtitle" = "Pick a community based on your interests, region, or a general purpose one."; +"Scene.ServerPicker.SubtitleExtend" = "Pick a community based on your interests, region, or a general purpose one. Each community is operated by an entirely independent organization or individual."; +"Scene.ServerPicker.Title" = "Valitse palvelin, +mikä tahansa palvelin."; +"Scene.ServerRules.Button.Confirm" = "Hyväksyn"; +"Scene.ServerRules.PrivacyPolicy" = "tietosuojakäytäntö"; +"Scene.ServerRules.Prompt" = "Jatkamalla, hyväksyt palvelun %@ palveluehdot ja tietosuojakäytönnön."; +"Scene.ServerRules.Subtitle" = "Nämä säännöt ovat %@ -palvelun asettamia."; +"Scene.ServerRules.TermsOfService" = "käyttöehdot"; +"Scene.ServerRules.Title" = "Joitakin perussääntöjä."; +"Scene.Settings.Footer.MastodonDescription" = "Mastodon on avoimen lähdekoodin ohjelmisto. Voit raportoida ongelmasta GitHubissa osoitteessa %@ (%@)"; +"Scene.Settings.Keyboard.CloseSettingsWindow" = "Sulje asetukset"; +"Scene.Settings.Section.Appearance.Automatic" = "Seuraa järjestelmää"; +"Scene.Settings.Section.Appearance.Dark" = "Tumma"; +"Scene.Settings.Section.Appearance.Light" = "Vaalea"; +"Scene.Settings.Section.Appearance.Title" = "Ulkoasu"; +"Scene.Settings.Section.BoringZone.AccountSettings" = "Tiliasetukset"; +"Scene.Settings.Section.BoringZone.Privacy" = "Tietosuojakäytäntö"; +"Scene.Settings.Section.BoringZone.Terms" = "Palveluehdot"; +"Scene.Settings.Section.BoringZone.Title" = "Tylsä alue"; +"Scene.Settings.Section.LookAndFeel.Light" = "Ljust"; +"Scene.Settings.Section.LookAndFeel.ReallyDark" = "Really Dark"; +"Scene.Settings.Section.LookAndFeel.SortaDark" = "Sorta Dark"; +"Scene.Settings.Section.LookAndFeel.Title" = "Look and Feel"; +"Scene.Settings.Section.LookAndFeel.UseSystem" = "Use System"; +"Scene.Settings.Section.Notifications.Boosts" = "Omien julkaisujen edelleen jaot"; "Scene.Settings.Section.Notifications.Favorites" = "Favorites my post"; -"Scene.Settings.Section.Notifications.Follows" = "Follows me"; -"Scene.Settings.Section.Notifications.Mentions" = "Mentions me"; -"Scene.Settings.Section.Notifications.Title" = "Notifications"; -"Scene.Settings.Section.Notifications.Trigger.Anyone" = "anyone"; -"Scene.Settings.Section.Notifications.Trigger.Follow" = "anyone I follow"; -"Scene.Settings.Section.Notifications.Trigger.Follower" = "a follower"; -"Scene.Settings.Section.Notifications.Trigger.Noone" = "no one"; -"Scene.Settings.Section.Notifications.Trigger.Title" = "Notify me when"; -"Scene.Settings.Section.Preference.DisableAvatarAnimation" = "Disable animated avatars"; -"Scene.Settings.Section.Preference.DisableEmojiAnimation" = "Disable animated emojis"; -"Scene.Settings.Section.Preference.Title" = "Preferences"; -"Scene.Settings.Section.Preference.TrueBlackDarkMode" = "True black dark mode"; -"Scene.Settings.Section.Preference.UsingDefaultBrowser" = "Use default browser to open links"; -"Scene.Settings.Section.SpicyZone.Clear" = "Clear Media Cache"; -"Scene.Settings.Section.SpicyZone.Signout" = "Logga ut"; -"Scene.Settings.Section.SpicyZone.Title" = "The Spicy Zone"; -"Scene.Settings.Title" = "Inställningar"; -"Scene.SuggestionAccount.FollowExplain" = "When you follow someone, you’ll see their posts in your home feed."; -"Scene.SuggestionAccount.Title" = "Find People to Follow"; -"Scene.Thread.BackTitle" = "Post"; -"Scene.Thread.Title" = "Post from %@"; -"Scene.Welcome.Slogan" = "Social networking -back in your hands."; -"Scene.Wizard.AccessibilityHint" = "Double tap to dismiss this wizard"; -"Scene.Wizard.MultipleAccountSwitchIntroDescription" = "Switch between multiple accounts by holding the profile button."; -"Scene.Wizard.NewInMastodon" = "New in Mastodon"; \ No newline at end of file +"Scene.Settings.Section.Notifications.Follows" = "Seuraa minua"; +"Scene.Settings.Section.Notifications.Mentions" = "Mainitsee minut"; +"Scene.Settings.Section.Notifications.Title" = "Ilmoitukset"; +"Scene.Settings.Section.Notifications.Trigger.Anyone" = "kuka tahansa"; +"Scene.Settings.Section.Notifications.Trigger.Follow" = "kuka tahansa, jota seuraan"; +"Scene.Settings.Section.Notifications.Trigger.Follower" = "seuraaja"; +"Scene.Settings.Section.Notifications.Trigger.Noone" = "ei kukaan"; +"Scene.Settings.Section.Notifications.Trigger.Title" = "Ilmoita minulle, kun"; +"Scene.Settings.Section.Preference.DisableAvatarAnimation" = "Poista käytöstä animoidut avatarit"; +"Scene.Settings.Section.Preference.DisableEmojiAnimation" = "Poista käytöstä animoidut emojit"; +"Scene.Settings.Section.Preference.Title" = "Lisäasetukset"; +"Scene.Settings.Section.Preference.TrueBlackDarkMode" = "Todellinen mustan tumma tila"; +"Scene.Settings.Section.Preference.UsingDefaultBrowser" = "Käytä oletusselainta linkkien avaamiseen"; +"Scene.Settings.Section.SpicyZone.Clear" = "Tyhjennä median välimuisti"; +"Scene.Settings.Section.SpicyZone.Signout" = "Kirjaudu ulos"; +"Scene.Settings.Section.SpicyZone.Title" = "Varovainen alue"; +"Scene.Settings.Title" = "Asetukset"; +"Scene.SuggestionAccount.FollowExplain" = "Kun seuraat jotakuta, näet hänen julkaisunsa kotisyötteessäsi."; +"Scene.SuggestionAccount.Title" = "Löydä tilejä seurattavaksi"; +"Scene.Thread.BackTitle" = "Julkaisu"; +"Scene.Thread.Title" = "Julkaisu tililtä %@"; +"Scene.Welcome.GetStarted" = "Kom igång"; +"Scene.Welcome.LogIn" = "Logga in"; +"Scene.Welcome.Slogan" = "Sosiaalinen verkostoituminen +takaisin käsissäsi."; +"Scene.Wizard.AccessibilityHint" = "Hylkää tämä ohjattu toiminto kaksoisnapauttamalla"; +"Scene.Wizard.MultipleAccountSwitchIntroDescription" = "Vaihda useiden tilien välillä pitämällä profiilipainiketta painettuna."; +"Scene.Wizard.NewInMastodon" = "Uutta Mastodonissa"; \ No newline at end of file diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/sv_FI.lproj/Localizable.stringsdict b/MastodonSDK/Sources/MastodonLocalization/Resources/sv_FI.lproj/Localizable.stringsdict index 65316e3d..eec977a6 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/sv_FI.lproj/Localizable.stringsdict +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/sv_FI.lproj/Localizable.stringsdict @@ -13,15 +13,15 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 unread notification</string> + <string>1 lukematon ilmoitus</string> <key>other</key> - <string>%ld unread notification</string> + <string>%ld lukematonta ilmoitusta</string> </dict> </dict> <key>a11y.plural.count.input_limit_exceeds</key> <dict> <key>NSStringLocalizedFormatKey</key> - <string>Input limit exceeds %#@character_count@</string> + <string>Syöterajoitus ylittyy %#@character_count@</string> <key>character_count</key> <dict> <key>NSStringFormatSpecTypeKey</key> @@ -29,15 +29,15 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 character</string> + <string>1 merkki</string> <key>other</key> - <string>%ld characters</string> + <string>%ld merkkiä</string> </dict> </dict> <key>a11y.plural.count.input_limit_remains</key> <dict> <key>NSStringLocalizedFormatKey</key> - <string>Input limit remains %#@character_count@</string> + <string>Syöterajoitus ylittyy %#@character_count@ päästä</string> <key>character_count</key> <dict> <key>NSStringFormatSpecTypeKey</key> @@ -45,9 +45,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 character</string> + <string>1 merkki</string> <key>other</key> - <string>%ld characters</string> + <string>%ld merkkiä</string> </dict> </dict> <key>plural.count.metric_formatted.post</key> @@ -61,9 +61,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>post</string> + <string>julkaisu</string> <key>other</key> - <string>posts</string> + <string>julkaisut</string> </dict> </dict> <key>plural.count.post</key> @@ -77,9 +77,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 post</string> + <string>1 julkaisu</string> <key>other</key> - <string>%ld posts</string> + <string>%ld julkaisua</string> </dict> </dict> <key>plural.count.favorite</key> @@ -93,9 +93,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 favorite</string> + <string>1 suosikki</string> <key>other</key> - <string>%ld favorites</string> + <string>%ld suosikkia</string> </dict> </dict> <key>plural.count.reblog</key> @@ -109,9 +109,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 reblog</string> + <string>1 edelleen jako</string> <key>other</key> - <string>%ld reblogs</string> + <string>%ld edelleen jakoa</string> </dict> </dict> <key>plural.count.vote</key> @@ -125,9 +125,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 vote</string> + <string>1 ääni</string> <key>other</key> - <string>%ld votes</string> + <string>%ld ääntä</string> </dict> </dict> <key>plural.count.voter</key> @@ -141,9 +141,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 voter</string> + <string>1 vastaaja</string> <key>other</key> - <string>%ld voters</string> + <string>%ld vastaajaa</string> </dict> </dict> <key>plural.people_talking</key> @@ -157,9 +157,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 people talking</string> + <string>1 ihminen puhuu</string> <key>other</key> - <string>%ld people talking</string> + <string>%ld ihmistä puhuu</string> </dict> </dict> <key>plural.count.following</key> @@ -173,9 +173,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 following</string> + <string>1 seurataan</string> <key>other</key> - <string>%ld following</string> + <string>%ld seurataan</string> </dict> </dict> <key>plural.count.follower</key> @@ -189,9 +189,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 följare</string> + <string>1 seuraaja</string> <key>other</key> - <string>%ld följare</string> + <string>%ld seuraajaa</string> </dict> </dict> <key>date.year.left</key> @@ -205,9 +205,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 year left</string> + <string>1 vuosi jäljellä</string> <key>other</key> - <string>%ld years left</string> + <string>%ld vuotta jäljellä</string> </dict> </dict> <key>date.month.left</key> @@ -221,9 +221,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 months left</string> + <string>1 kuukausi jäljellä</string> <key>other</key> - <string>%ld months left</string> + <string>%ld kuukautta jäljellä</string> </dict> </dict> <key>date.day.left</key> @@ -237,9 +237,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 day left</string> + <string>1 päivä jäljellä</string> <key>other</key> - <string>%ld days left</string> + <string>%ld päivää jäljellä</string> </dict> </dict> <key>date.hour.left</key> @@ -253,9 +253,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 hour left</string> + <string>1 tunti jäljellä</string> <key>other</key> - <string>%ld hours left</string> + <string>%ld tuntia jäljellä</string> </dict> </dict> <key>date.minute.left</key> @@ -269,9 +269,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 minute left</string> + <string>1 minuutti jäljellä</string> <key>other</key> - <string>%ld minutes left</string> + <string>%ld minuuttia jäljellä</string> </dict> </dict> <key>date.second.left</key> @@ -285,9 +285,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1 second left</string> + <string>1 sekuntti</string> <key>other</key> - <string>%ld seconds left</string> + <string>%ld sekunttia jäljellä</string> </dict> </dict> <key>date.year.ago.abbr</key> @@ -301,9 +301,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1y ago</string> + <string>1v sitten</string> <key>other</key> - <string>%ldy ago</string> + <string>%ldv sitten</string> </dict> </dict> <key>date.month.ago.abbr</key> @@ -317,9 +317,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1M ago</string> + <string>1kk sitten</string> <key>other</key> - <string>%ldM ago</string> + <string>%ldkk sitten</string> </dict> </dict> <key>date.day.ago.abbr</key> @@ -333,9 +333,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1d ago</string> + <string>1pv sitten</string> <key>other</key> - <string>%ldd ago</string> + <string>%ldpv sitten</string> </dict> </dict> <key>date.hour.ago.abbr</key> @@ -349,9 +349,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1h ago</string> + <string>1t sitten</string> <key>other</key> - <string>%ldh ago</string> + <string>%ldt sitten</string> </dict> </dict> <key>date.minute.ago.abbr</key> @@ -365,9 +365,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1m ago</string> + <string>1min sitten</string> <key>other</key> - <string>%ldm ago</string> + <string>%ldmin sitten</string> </dict> </dict> <key>date.second.ago.abbr</key> @@ -381,9 +381,9 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>1s ago</string> + <string>1s sitten</string> <key>other</key> - <string>%lds ago</string> + <string>%lds sitten</string> </dict> </dict> </dict> diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/th.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/th.lproj/Localizable.strings index 1bd954fe..c79bb681 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/th.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/th.lproj/Localizable.strings @@ -4,8 +4,8 @@ "Common.Alerts.CleanCache.Title" = "ล้างแคช"; "Common.Alerts.Common.PleaseTryAgain" = "โปรดลองอีกครั้ง"; "Common.Alerts.Common.PleaseTryAgainLater" = "โปรดลองอีกครั้งในภายหลัง"; -"Common.Alerts.DeletePost.Delete" = "ลบ"; -"Common.Alerts.DeletePost.Title" = "คุณแน่ใจหรือไม่ว่าต้องการลบโพสต์นี้?"; +"Common.Alerts.DeletePost.Message" = "คุณแน่ใจหรือไม่ว่าต้องการลบโพสต์นี้?"; +"Common.Alerts.DeletePost.Title" = "ลบโพสต์"; "Common.Alerts.DiscardPostContent.Message" = "ยืนยันที่จะละทิ้งเนื้อหาโพสต์ที่เขียน"; "Common.Alerts.DiscardPostContent.Title" = "ละทิ้งแบบร่าง"; "Common.Alerts.EditProfileFailure.Message" = "ไม่สามารถแก้ไขโปรไฟล์ โปรดลองอีกครั้ง"; @@ -41,6 +41,7 @@ "Common.Controls.Actions.Next" = "ถัดไป"; "Common.Controls.Actions.Ok" = "ตกลง"; "Common.Controls.Actions.Open" = "เปิด"; +"Common.Controls.Actions.OpenInBrowser" = "เปิดในเบราว์เซอร์"; "Common.Controls.Actions.OpenInSafari" = "เปิดใน Safari"; "Common.Controls.Actions.Preview" = "แสดงตัวอย่าง"; "Common.Controls.Actions.Previous" = "ก่อนหน้า"; @@ -93,6 +94,7 @@ "Common.Controls.Keyboard.Timeline.ToggleFavorite" = "เปิด/ปิดรายการโปรดในโพสต์"; "Common.Controls.Keyboard.Timeline.ToggleReblog" = "เปิด/ปิดการดันในโพสต์"; "Common.Controls.Status.Actions.Favorite" = "ชื่นชอบ"; +"Common.Controls.Status.Actions.Hide" = "ซ่อน"; "Common.Controls.Status.Actions.Menu" = "เมนู"; "Common.Controls.Status.Actions.Reblog" = "ดัน"; "Common.Controls.Status.Actions.Reply" = "ตอบกลับ"; @@ -112,23 +114,27 @@ "Common.Controls.Status.Tag.Url" = "URL"; "Common.Controls.Status.UserReblogged" = "%@ ได้ดัน"; "Common.Controls.Status.UserRepliedTo" = "ตอบกลับ %@"; +"Common.Controls.Status.Visibility.Direct" = "เฉพาะผู้ใช้ที่กล่าวถึงเท่านั้นที่สามารถเห็นโพสต์นี้"; +"Common.Controls.Status.Visibility.Private" = "เฉพาะผู้ติดตามของเขาเท่านั้นที่สามารถเห็นโพสต์นี้"; +"Common.Controls.Status.Visibility.PrivateFromMe" = "เฉพาะผู้ติดตามของฉันเท่านั้นที่สามารถเห็นโพสต์นี้"; +"Common.Controls.Status.Visibility.Unlisted" = "ทุกคนสามารถเห็นโพสต์นี้แต่ไม่แสดงในเส้นเวลาสาธารณะ"; "Common.Controls.Tabs.Home" = "หน้าแรก"; "Common.Controls.Tabs.Notification" = "การแจ้งเตือน"; "Common.Controls.Tabs.Profile" = "โปรไฟล์"; "Common.Controls.Tabs.Search" = "ค้นหา"; "Common.Controls.Timeline.Filtered" = "กรองอยู่"; "Common.Controls.Timeline.Header.BlockedWarning" = "คุณไม่สามารถดูโปรไฟล์ของผู้ใช้นี้ -จนกว่าผู้ใช้นี้จะเลิกปิดกั้นคุณ"; +จนกว่าเขาจะเลิกปิดกั้นคุณ"; "Common.Controls.Timeline.Header.BlockingWarning" = "คุณไม่สามารถดูโปรไฟล์ของผู้ใช้นี้ -จนกว่าคุณจะเลิกปิดกั้นผู้ใช้นี้ -ผู้ใช้นี้เห็นโปรไฟล์ของคุณเหมือนกับที่คุณเห็น"; +จนกว่าคุณจะเลิกปิดกั้นเขา +โปรไฟล์ของคุณมีลักษณะเช่นนี้สำหรับเขา"; "Common.Controls.Timeline.Header.NoStatusFound" = "ไม่พบโพสต์"; "Common.Controls.Timeline.Header.SuspendedWarning" = "ผู้ใช้นี้ถูกระงับการใช้งาน"; "Common.Controls.Timeline.Header.UserBlockedWarning" = "คุณไม่สามารถดูโปรไฟล์ของ %@ -จนกว่าผู้ใช้นี้จะเลิกปิดกั้นคุณ"; +จนกว่าเขาจะเลิกปิดกั้นคุณ"; "Common.Controls.Timeline.Header.UserBlockingWarning" = "คุณไม่สามารถดูโปรไฟล์ของ %@ -จนกว่าคุณจะเลิกปิดกั้นผู้ใช้นี้ -ผู้ใช้นี้เห็นโปรไฟล์ของคุณเหมือนกับที่คุณเห็น"; +จนกว่าคุณจะเลิกปิดกั้นเขา +โปรไฟล์ของคุณมีลักษณะเช่นนี้สำหรับเขา"; "Common.Controls.Timeline.Header.UserSuspendedWarning" = "บัญชีของ %@ ถูกระงับการใช้งาน"; "Common.Controls.Timeline.Loader.LoadMissingPosts" = "โหลดโพสต์ที่ขาดหายไป"; "Common.Controls.Timeline.Loader.LoadingMissingPosts" = "กำลังโหลดโพสต์ที่ขาดหายไป..."; @@ -178,8 +184,8 @@ "Scene.Compose.Visibility.Private" = "ผู้ติดตามเท่านั้น"; "Scene.Compose.Visibility.Public" = "สาธารณะ"; "Scene.Compose.Visibility.Unlisted" = "ไม่อยู่ในรายการ"; -"Scene.ConfirmEmail.Button.DontReceiveEmail" = "ฉันไม่เคยได้รับอีเมล"; "Scene.ConfirmEmail.Button.OpenEmailApp" = "เปิดแอปอีเมล"; +"Scene.ConfirmEmail.Button.Resend" = "ส่งใหม่"; "Scene.ConfirmEmail.DontReceiveEmail.Description" = "หากคุณยังไม่ได้รับอีเมล ตรวจสอบว่าที่อยู่อีเมลของคุณถูกต้อง รวมถึงโฟลเดอร์อีเมลขยะของคุณ"; "Scene.ConfirmEmail.DontReceiveEmail.ResendEmail" = "ส่งอีเมลใหม่"; "Scene.ConfirmEmail.DontReceiveEmail.Title" = "ตรวจสอบอีเมลของคุณ"; @@ -187,8 +193,7 @@ "Scene.ConfirmEmail.OpenEmailApp.Mail" = "จดหมาย"; "Scene.ConfirmEmail.OpenEmailApp.OpenEmailClient" = "เปิดไคลเอ็นต์อีเมล"; "Scene.ConfirmEmail.OpenEmailApp.Title" = "ตรวจสอบกล่องขาเข้าของคุณ"; -"Scene.ConfirmEmail.Subtitle" = "เราเพิ่งส่งอีเมลไปยัง %@ -แตะที่ลิงก์เพื่อยืนยันบัญชีของคุณ"; +"Scene.ConfirmEmail.Subtitle" = "แตะลิงก์ที่เราส่งอีเมลถึงคุณเพื่อยืนยันบัญชีของคุณ"; "Scene.ConfirmEmail.Title" = "หนึ่งสิ่งสุดท้าย"; "Scene.Favorite.Title" = "รายการโปรดของคุณ"; "Scene.Follower.Footer" = "ไม่ได้แสดงผู้ติดตามจากเซิร์ฟเวอร์อื่น ๆ"; @@ -200,14 +205,14 @@ "Scene.HomeTimeline.Title" = "หน้าแรก"; "Scene.Notification.Keyobard.ShowEverything" = "แสดงทุกอย่าง"; "Scene.Notification.Keyobard.ShowMentions" = "แสดงการกล่าวถึง"; +"Scene.Notification.NotificationDescription.FavoritedYourPost" = "ได้ชื่นชอบโพสต์ของคุณ"; +"Scene.Notification.NotificationDescription.FollowedYou" = "ได้ติดตามคุณ"; +"Scene.Notification.NotificationDescription.MentionedYou" = "ได้กล่าวถึงคุณ"; +"Scene.Notification.NotificationDescription.PollHasEnded" = "การสำรวจความคิดเห็นได้สิ้นสุดแล้ว"; +"Scene.Notification.NotificationDescription.RebloggedYourPost" = "ได้ดันโพสต์ของคุณ"; +"Scene.Notification.NotificationDescription.RequestToFollowYou" = "ขอติดตามคุณ"; "Scene.Notification.Title.Everything" = "ทุกอย่าง"; "Scene.Notification.Title.Mentions" = "การกล่าวถึง"; -"Scene.Notification.UserFavorited Your Post" = "%@ ได้ชื่นชอบโพสต์ของคุณ"; -"Scene.Notification.UserFollowedYou" = "%@ ได้ติดตามคุณ"; -"Scene.Notification.UserMentionedYou" = "%@ ได้กล่าวถึงคุณ"; -"Scene.Notification.UserRebloggedYourPost" = "%@ ได้ดันโพสต์ของคุณ"; -"Scene.Notification.UserRequestedToFollowYou" = "%@ ได้ขอติดตามคุณ"; -"Scene.Notification.UserYourPollHasEnded" = "%@ โพลของคุณได้สิ้นสุดแล้ว"; "Scene.Preview.Keyboard.ClosePreview" = "ปิดตัวอย่าง"; "Scene.Preview.Keyboard.ShowNext" = "แสดงถัดไป"; "Scene.Preview.Keyboard.ShowPrevious" = "แสดงก่อนหน้า"; @@ -217,12 +222,18 @@ "Scene.Profile.Fields.AddRow" = "เพิ่มแถว"; "Scene.Profile.Fields.Placeholder.Content" = "เนื้อหา"; "Scene.Profile.Fields.Placeholder.Label" = "ป้ายชื่อ"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Message" = "ยืนยันเพื่อเลิกปิดกั้น %@"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Title" = "เลิกปิดกั้นบัญชี"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Message" = "ยืนยันเพื่อปิดกั้น %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title" = "ปิดกั้นบัญชี"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Message" = "ยืนยันเพื่อซ่อน %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Title" = "ซ่อนบัญชี"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Message" = "ยืนยันเพื่อเลิกปิดกั้น %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Title" = "เลิกปิดกั้นบัญชี"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Message" = "ยืนยันเพื่อเลิกซ่อน %@"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Title" = "เลิกซ่อนบัญชี"; +"Scene.Profile.SegmentedControl.About" = "เกี่ยวกับ"; "Scene.Profile.SegmentedControl.Media" = "สื่อ"; "Scene.Profile.SegmentedControl.Posts" = "โพสต์"; +"Scene.Profile.SegmentedControl.PostsAndReplies" = "โพสต์และการตอบกลับ"; "Scene.Profile.SegmentedControl.Replies" = "การตอบกลับ"; "Scene.Register.Error.Item.Agreement" = "ข้อตกลง"; "Scene.Register.Error.Item.Email" = "อีเมล"; @@ -248,19 +259,26 @@ "Scene.Register.Input.DisplayName.Placeholder" = "ชื่อที่แสดง"; "Scene.Register.Input.Email.Placeholder" = "อีเมล"; "Scene.Register.Input.Invite.RegistrationUserInviteRequest" = "ทำไมคุณจึงต้องการเข้าร่วม?"; +"Scene.Register.Input.Password.Accessibility.Checked" = "กาเครื่องหมายแล้ว"; +"Scene.Register.Input.Password.Accessibility.Unchecked" = "ไม่ได้กาเครื่องหมาย"; +"Scene.Register.Input.Password.CharacterLimit" = "8 ตัวอักษร"; "Scene.Register.Input.Password.Hint" = "รหัสผ่านของคุณต้องมีอย่างน้อยแปดตัวอักษร"; "Scene.Register.Input.Password.Placeholder" = "รหัสผ่าน"; +"Scene.Register.Input.Password.Require" = "รหัสผ่านของคุณต้องมีอย่างน้อย:"; "Scene.Register.Input.Username.DuplicatePrompt" = "ชื่อผู้ใช้นี้ถูกใช้ไปแล้ว"; "Scene.Register.Input.Username.Placeholder" = "ชื่อผู้ใช้"; -"Scene.Register.Title" = "บอกเราเกี่ยวกับคุณ"; +"Scene.Register.Title" = "มาตั้งค่าของคุณใน %@ กันเลย"; "Scene.Report.Content1" = "มีโพสต์อื่นใดที่คุณต้องการเพิ่มไปยังรายงานหรือไม่?"; "Scene.Report.Content2" = "มีสิ่งใดที่ผู้ควบคุมควรทราบเกี่ยวกับรายงานนี้หรือไม่?"; +"Scene.Report.ReportSentTitle" = "ขอบคุณสำหรับการรายงาน เราจะตรวจสอบสิ่งนี้"; +"Scene.Report.Reported" = "รายงานแล้ว"; "Scene.Report.Send" = "ส่งรายงาน"; "Scene.Report.SkipToSend" = "ส่งโดยไม่มีความคิดเห็น"; "Scene.Report.Step1" = "ขั้นตอนที่ 1 จาก 2"; "Scene.Report.Step2" = "ขั้นตอนที่ 2 จาก 2"; "Scene.Report.TextPlaceholder" = "พิมพ์หรือวางความคิดเห็นเพิ่มเติม"; "Scene.Report.Title" = "รายงาน %@"; +"Scene.Report.TitleReport" = "รายงาน"; "Scene.Search.Recommend.Accounts.Description" = "คุณอาจต้องการติดตามบัญชีเหล่านี้"; "Scene.Search.Recommend.Accounts.Follow" = "ติดตาม"; "Scene.Search.Recommend.Accounts.Title" = "บัญชีที่คุณอาจชอบ"; @@ -297,16 +315,17 @@ "Scene.ServerPicker.EmptyState.BadNetwork" = "มีบางอย่างผิดพลาดขณะโหลดข้อมูล ตรวจสอบการเชื่อมต่ออินเทอร์เน็ตของคุณ"; "Scene.ServerPicker.EmptyState.FindingServers" = "กำลังค้นหาเซิร์ฟเวอร์ที่พร้อมใช้งาน..."; "Scene.ServerPicker.EmptyState.NoResults" = "ไม่มีผลลัพธ์"; -"Scene.ServerPicker.Input.Placeholder" = "ค้นหาเซิร์ฟเวอร์หรือเข้าร่วมของคุณเอง..."; +"Scene.ServerPicker.Input.Placeholder" = "ค้นหาชุมชน"; "Scene.ServerPicker.Label.Category" = "หมวดหมู่"; "Scene.ServerPicker.Label.Language" = "ภาษา"; "Scene.ServerPicker.Label.Users" = "ผู้ใช้"; -"Scene.ServerPicker.Title" = "เลือกเซิร์ฟเวอร์ -อันไหนก็ได้"; +"Scene.ServerPicker.Subtitle" = "เลือกชุมชนตามความสนใจ, ภูมิภาค หรือวัตถุประสงค์ทั่วไปของคุณ"; +"Scene.ServerPicker.SubtitleExtend" = "เลือกชุมชนตามความสนใจ, ภูมิภาค หรือวัตถุประสงค์ทั่วไปของคุณ แต่ละชุมชนดำเนินการโดยองค์กรหรือบุคคลที่เป็นอิสระโดยสิ้นเชิง"; +"Scene.ServerPicker.Title" = "Mastodon ประกอบด้วยผู้ใช้ในชุมชนต่าง ๆ"; "Scene.ServerRules.Button.Confirm" = "ฉันเห็นด้วย"; "Scene.ServerRules.PrivacyPolicy" = "นโยบายความเป็นส่วนตัว"; "Scene.ServerRules.Prompt" = "เมื่อคุณดำเนินการต่อ คุณอยู่ภายใต้เงื่อนไขการให้บริการและนโยบายความเป็นส่วนตัวสำหรับ %@"; -"Scene.ServerRules.Subtitle" = "กฎเหล่านี้ถูกตั้งโดยผู้ดูแลของ %@"; +"Scene.ServerRules.Subtitle" = "มีการตั้งและบังคับใช้กฎเหล่านี้โดยผู้ควบคุมของ %@"; "Scene.ServerRules.TermsOfService" = "เงื่อนไขการให้บริการ"; "Scene.ServerRules.Title" = "กฎพื้นฐานบางประการ"; "Scene.Settings.Footer.MastodonDescription" = "Mastodon เป็นซอฟต์แวร์โอเพนซอร์ส คุณสามารถรายงานปัญหาได้ใน GitHub ที่ %@ (%@)"; @@ -319,6 +338,11 @@ "Scene.Settings.Section.BoringZone.Privacy" = "นโยบายความเป็นส่วนตัว"; "Scene.Settings.Section.BoringZone.Terms" = "เงื่อนไขการให้บริการ"; "Scene.Settings.Section.BoringZone.Title" = "โซนน่าเบื่อ"; +"Scene.Settings.Section.LookAndFeel.Light" = "สว่าง"; +"Scene.Settings.Section.LookAndFeel.ReallyDark" = "มืดมาก"; +"Scene.Settings.Section.LookAndFeel.SortaDark" = "ค่อนข้างมืด"; +"Scene.Settings.Section.LookAndFeel.Title" = "ลักษณะที่แสดง"; +"Scene.Settings.Section.LookAndFeel.UseSystem" = "ใช้ของระบบ"; "Scene.Settings.Section.Notifications.Boosts" = "ดันโพสต์ของฉัน"; "Scene.Settings.Section.Notifications.Favorites" = "ชื่นชอบโพสต์ของฉัน"; "Scene.Settings.Section.Notifications.Follows" = "ติดตามฉัน"; @@ -342,6 +366,8 @@ "Scene.SuggestionAccount.Title" = "ค้นหาผู้คนที่จะติดตาม"; "Scene.Thread.BackTitle" = "โพสต์"; "Scene.Thread.Title" = "โพสต์จาก %@"; +"Scene.Welcome.GetStarted" = "เริ่มต้นใช้งาน"; +"Scene.Welcome.LogIn" = "เข้าสู่ระบบ"; "Scene.Welcome.Slogan" = "ให้เครือข่ายสังคม กลับมาอยู่ในมือของคุณ"; "Scene.Wizard.AccessibilityHint" = "แตะสองครั้งเพื่อปิดตัวช่วยสร้างนี้"; diff --git a/MastodonSDK/Sources/MastodonLocalization/Resources/zh-Hans.lproj/Localizable.strings b/MastodonSDK/Sources/MastodonLocalization/Resources/zh-Hans.lproj/Localizable.strings index 7a6b0203..7ad984f1 100644 --- a/MastodonSDK/Sources/MastodonLocalization/Resources/zh-Hans.lproj/Localizable.strings +++ b/MastodonSDK/Sources/MastodonLocalization/Resources/zh-Hans.lproj/Localizable.strings @@ -4,7 +4,7 @@ "Common.Alerts.CleanCache.Title" = "清除缓存"; "Common.Alerts.Common.PleaseTryAgain" = "请重试。"; "Common.Alerts.Common.PleaseTryAgainLater" = "请稍后重试。"; -"Common.Alerts.DeletePost.Delete" = "删除"; +"Common.Alerts.DeletePost.Message" = "确定要删除这个帖子吗?"; "Common.Alerts.DeletePost.Title" = "确定要删除这条消息吗?"; "Common.Alerts.DiscardPostContent.Message" = "确认要丢弃正在编辑的内容"; "Common.Alerts.DiscardPostContent.Title" = "丢弃草案"; @@ -41,6 +41,7 @@ "Common.Controls.Actions.Next" = "下一个"; "Common.Controls.Actions.Ok" = "好的"; "Common.Controls.Actions.Open" = "打开"; +"Common.Controls.Actions.OpenInBrowser" = "在浏览器中打开"; "Common.Controls.Actions.OpenInSafari" = "在 Safari 中打开"; "Common.Controls.Actions.Preview" = "预览"; "Common.Controls.Actions.Previous" = "上一个"; @@ -93,6 +94,7 @@ "Common.Controls.Keyboard.Timeline.ToggleFavorite" = "喜欢此帖子"; "Common.Controls.Keyboard.Timeline.ToggleReblog" = "转发此帖子"; "Common.Controls.Status.Actions.Favorite" = "喜欢"; +"Common.Controls.Status.Actions.Hide" = "隐藏"; "Common.Controls.Status.Actions.Menu" = "菜单"; "Common.Controls.Status.Actions.Reblog" = "转发"; "Common.Controls.Status.Actions.Reply" = "回复"; @@ -112,6 +114,10 @@ "Common.Controls.Status.Tag.Url" = "URL"; "Common.Controls.Status.UserReblogged" = "%@ 转发"; "Common.Controls.Status.UserRepliedTo" = "回复给 %@"; +"Common.Controls.Status.Visibility.Direct" = "只有提到的用户才能看到此帖子。"; +"Common.Controls.Status.Visibility.Private" = "只有作者的关注者才能看到此帖子。"; +"Common.Controls.Status.Visibility.PrivateFromMe" = "只有我的关注者才能看到此帖子。"; +"Common.Controls.Status.Visibility.Unlisted" = "任何人都可以看到这个帖子,但不会在公开的时间线中显示。"; "Common.Controls.Tabs.Home" = "主页"; "Common.Controls.Tabs.Notification" = "通知"; "Common.Controls.Tabs.Profile" = "个人资料"; @@ -178,8 +184,8 @@ "Scene.Compose.Visibility.Private" = "仅关注者"; "Scene.Compose.Visibility.Public" = "公开"; "Scene.Compose.Visibility.Unlisted" = "不公开"; -"Scene.ConfirmEmail.Button.DontReceiveEmail" = "我还没有收到电子邮件"; "Scene.ConfirmEmail.Button.OpenEmailApp" = "打开电子邮件应用"; +"Scene.ConfirmEmail.Button.Resend" = "重新发送"; "Scene.ConfirmEmail.DontReceiveEmail.Description" = "检查您的电子邮件地址是否正确,同时请检查你的垃圾箱。"; "Scene.ConfirmEmail.DontReceiveEmail.ResendEmail" = "重新发送邮件"; "Scene.ConfirmEmail.DontReceiveEmail.Title" = "请检查你的邮箱。"; @@ -200,14 +206,14 @@ "Scene.HomeTimeline.Title" = "主页"; "Scene.Notification.Keyobard.ShowEverything" = "显示全部"; "Scene.Notification.Keyobard.ShowMentions" = "显示提及"; +"Scene.Notification.NotificationDescription.FavoritedYourPost" = "喜欢了你的帖子"; +"Scene.Notification.NotificationDescription.FollowedYou" = "关注了你"; +"Scene.Notification.NotificationDescription.MentionedYou" = "提及了你"; +"Scene.Notification.NotificationDescription.PollHasEnded" = "投票已结束"; +"Scene.Notification.NotificationDescription.RebloggedYourPost" = "转发了你的帖子"; +"Scene.Notification.NotificationDescription.RequestToFollowYou" = "关注请求"; "Scene.Notification.Title.Everything" = "全部"; "Scene.Notification.Title.Mentions" = "提及"; -"Scene.Notification.UserFavorited Your Post" = "%@ 喜欢了你的帖子"; -"Scene.Notification.UserFollowedYou" = "%@ 关注了你"; -"Scene.Notification.UserMentionedYou" = "%@ 提及了你"; -"Scene.Notification.UserRebloggedYourPost" = "%@ 转发了你的帖子"; -"Scene.Notification.UserRequestedToFollowYou" = "%@ 向你发送了关注请求"; -"Scene.Notification.UserYourPollHasEnded" = "%@ 你的投票已经结束"; "Scene.Preview.Keyboard.ClosePreview" = "关闭预览"; "Scene.Preview.Keyboard.ShowNext" = "显示下一个"; "Scene.Preview.Keyboard.ShowPrevious" = "显示前一个"; @@ -217,12 +223,18 @@ "Scene.Profile.Fields.AddRow" = "添加"; "Scene.Profile.Fields.Placeholder.Content" = "内容"; "Scene.Profile.Fields.Placeholder.Label" = "标签"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Message" = "确认取消屏蔽 %@"; -"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUsre.Title" = "解除屏蔽帐户"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Message" = "确认屏蔽 %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmBlockUser.Title" = "屏蔽帐户"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Message" = "确认静音 %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmMuteUser.Title" = "静音账户"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Message" = "确认取消屏蔽 %@"; +"Scene.Profile.RelationshipActionAlert.ConfirmUnblockUser.Title" = "解除屏蔽帐户"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Message" = "确认取消静音 %@"; "Scene.Profile.RelationshipActionAlert.ConfirmUnmuteUser.Title" = "取消静音账户"; +"Scene.Profile.SegmentedControl.About" = "关于"; "Scene.Profile.SegmentedControl.Media" = "媒体"; "Scene.Profile.SegmentedControl.Posts" = "帖子"; +"Scene.Profile.SegmentedControl.PostsAndReplies" = "帖子与回复"; "Scene.Profile.SegmentedControl.Replies" = "回复"; "Scene.Register.Error.Item.Agreement" = "协议"; "Scene.Register.Error.Item.Email" = "电子邮箱"; @@ -248,19 +260,26 @@ "Scene.Register.Input.DisplayName.Placeholder" = "昵称"; "Scene.Register.Input.Email.Placeholder" = "电子邮箱"; "Scene.Register.Input.Invite.RegistrationUserInviteRequest" = "加入的理由是?"; +"Scene.Register.Input.Password.Accessibility.Checked" = "已选中"; +"Scene.Register.Input.Password.Accessibility.Unchecked" = "未选中"; +"Scene.Register.Input.Password.CharacterLimit" = "8 个字符"; "Scene.Register.Input.Password.Hint" = "密码长度至少为 8 个字符"; "Scene.Register.Input.Password.Placeholder" = "密码"; +"Scene.Register.Input.Password.Require" = "您的密码至少需要:"; "Scene.Register.Input.Username.DuplicatePrompt" = "此用户名已被使用"; "Scene.Register.Input.Username.Placeholder" = "用户名"; "Scene.Register.Title" = "介绍一下你自己吧"; "Scene.Report.Content1" = "是否有帖子需要举报?"; "Scene.Report.Content2" = "是否有关于此举报的详细描述信息?"; +"Scene.Report.ReportSentTitle" = "感谢提交举报,我们将会进行处理。"; +"Scene.Report.Reported" = "已报告"; "Scene.Report.Send" = "发送举报"; "Scene.Report.SkipToSend" = "直接发送"; "Scene.Report.Step1" = "步骤 1 / 2"; "Scene.Report.Step2" = "步骤 2 / 2"; "Scene.Report.TextPlaceholder" = "输入或粘贴额外的注释"; "Scene.Report.Title" = "举报 %@"; +"Scene.Report.TitleReport" = "举报"; "Scene.Search.Recommend.Accounts.Description" = "你可能会喜欢关注这些用户"; "Scene.Search.Recommend.Accounts.Follow" = "关注"; "Scene.Search.Recommend.Accounts.Title" = "你可能感兴趣的用户"; @@ -301,6 +320,8 @@ "Scene.ServerPicker.Label.Category" = "类别"; "Scene.ServerPicker.Label.Language" = "语言"; "Scene.ServerPicker.Label.Users" = "用户"; +"Scene.ServerPicker.Subtitle" = "根据你的兴趣、区域或一般目的选择一个社区。"; +"Scene.ServerPicker.SubtitleExtend" = "根据你的兴趣、区域或一般目的选择一个社区。每个社区都由完全独立的组织或个人管理。"; "Scene.ServerPicker.Title" = "挑选一个服务器, 任意服务器。"; "Scene.ServerRules.Button.Confirm" = "我同意"; @@ -319,6 +340,11 @@ "Scene.Settings.Section.BoringZone.Privacy" = "隐私政策"; "Scene.Settings.Section.BoringZone.Terms" = "服务条款"; "Scene.Settings.Section.BoringZone.Title" = "The Boring Zone"; +"Scene.Settings.Section.LookAndFeel.Light" = "浅色"; +"Scene.Settings.Section.LookAndFeel.ReallyDark" = "暗色"; +"Scene.Settings.Section.LookAndFeel.SortaDark" = "深色"; +"Scene.Settings.Section.LookAndFeel.Title" = "外观和风格"; +"Scene.Settings.Section.LookAndFeel.UseSystem" = "跟随系统"; "Scene.Settings.Section.Notifications.Boosts" = "转发我的帖子"; "Scene.Settings.Section.Notifications.Favorites" = "喜欢我的帖子"; "Scene.Settings.Section.Notifications.Follows" = "关注我"; @@ -342,6 +368,8 @@ "Scene.SuggestionAccount.Title" = "查看推荐关注的用户"; "Scene.Thread.BackTitle" = "帖子"; "Scene.Thread.Title" = "来自 %@ 的帖子"; +"Scene.Welcome.GetStarted" = "开始使用"; +"Scene.Welcome.LogIn" = "登录"; "Scene.Welcome.Slogan" = "社交网络 回到你的手中。"; "Scene.Wizard.AccessibilityHint" = "双击关闭此向导"; diff --git a/MastodonSDK/Sources/MastodonSDK/API/Mastodon+API.swift b/MastodonSDK/Sources/MastodonSDK/API/Mastodon+API.swift index f72fd3af..66c822b3 100644 --- a/MastodonSDK/Sources/MastodonSDK/API/Mastodon+API.swift +++ b/MastodonSDK/Sources/MastodonSDK/API/Mastodon+API.swift @@ -74,27 +74,27 @@ extension Mastodon.API { }() static func oauthEndpointURL(domain: String) -> URL { - return URL(string: "https://" + domain + "/oauth/")! + return URL(string: "\(URL.httpScheme(domain: domain))://" + domain + "/oauth/")! } static func endpointURL(domain: String) -> URL { - return URL(string: "https://" + domain + "/api/v1/")! + return URL(string: "\(URL.httpScheme(domain: domain))://" + domain + "/api/v1/")! } static func endpointV2URL(domain: String) -> URL { - return URL(string: "https://" + domain + "/api/v2/")! + return URL(string: "\(URL.httpScheme(domain: domain))://" + domain + "/api/v2/")! } static let joinMastodonEndpointURL = URL(string: "https://api.joinmastodon.org/")! public static func resendEmailURL(domain: String) -> URL { - return URL(string: "https://" + domain + "/auth/confirmation/new")! + return URL(string: "\(URL.httpScheme(domain: domain))://" + domain + "/auth/confirmation/new")! } public static func serverRulesURL(domain: String) -> URL { - return URL(string: "https://" + domain + "/about/more")! + return URL(string: "\(URL.httpScheme(domain: domain))://" + domain + "/about/more")! } public static func privacyURL(domain: String) -> URL { - return URL(string: "https://" + domain + "/terms")! + return URL(string: "\(URL.httpScheme(domain: domain))://" + domain + "/terms")! } } diff --git a/MastodonSDK/Sources/MastodonSDK/Entity/Mastodon+Entity+Filter.swift b/MastodonSDK/Sources/MastodonSDK/Entity/Mastodon+Entity+Filter.swift index e52dd36b..00a06ccf 100644 --- a/MastodonSDK/Sources/MastodonSDK/Entity/Mastodon+Entity+Filter.swift +++ b/MastodonSDK/Sources/MastodonSDK/Entity/Mastodon+Entity+Filter.swift @@ -22,7 +22,7 @@ extension Mastodon.Entity { public let id: ID public let phrase: String public let context: [Context] - public let expiresAt: Date + public let expiresAt: Date? public let irreversible: Bool public let wholeWord: Bool @@ -38,7 +38,7 @@ extension Mastodon.Entity { } extension Mastodon.Entity.Filter { - public enum Context: RawRepresentable, Codable { + public enum Context: RawRepresentable, Codable, Hashable { case home case notifications case `public` diff --git a/MastodonSDK/Sources/MastodonSDK/Extension/URL.swift b/MastodonSDK/Sources/MastodonSDK/Extension/URL.swift new file mode 100644 index 00000000..a9345c7b --- /dev/null +++ b/MastodonSDK/Sources/MastodonSDK/Extension/URL.swift @@ -0,0 +1,14 @@ +// +// URL.swift +// +// +// Created by MainasuK on 2022-3-16. +// + +import Foundation + +extension URL { + public static func httpScheme(domain: String) -> String { + return domain.hasSuffix(".onion") ? "http" : "https" + } +} diff --git a/MastodonSDK/Sources/MastodonUI/Protocol/AdaptiveMarginStatusTableViewCell.swift b/MastodonSDK/Sources/MastodonUI/Protocol/AdaptiveMarginStatusTableViewCell.swift new file mode 100644 index 00000000..0ac9342a --- /dev/null +++ b/MastodonSDK/Sources/MastodonUI/Protocol/AdaptiveMarginStatusTableViewCell.swift @@ -0,0 +1,56 @@ +// +// AdaptiveMarginStatusTableViewCell.swift +// +// +// Created by MainasuK on 2022-2-18. +// + +import UIKit + +public protocol AdaptiveContainerView: UIView { + func updateContainerViewComponentsLayoutMarginsRelativeArrangementBehavior(isEnabled: Bool) +} + +public protocol AdaptiveContainerMarginTableViewCell: UITableViewCell { + associatedtype ContainerView: AdaptiveContainerView + static var containerViewMarginForRegularHorizontalSizeClass: CGFloat { get } + var containerView: ContainerView { get } + var containerViewLeadingLayoutConstraint: NSLayoutConstraint! { get set } + var containerViewTrailingLayoutConstraint: NSLayoutConstraint! { get set } +} + +extension AdaptiveContainerMarginTableViewCell { + + public static var containerViewMarginForRegularHorizontalSizeClass: CGFloat { 64 } + + public func setupContainerViewMarginConstraints() { + containerViewLeadingLayoutConstraint = containerView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor) + containerViewTrailingLayoutConstraint = contentView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor) + } + + public func updateContainerViewMarginConstraints() { + func setupContainerForPhone() { + containerView.updateContainerViewComponentsLayoutMarginsRelativeArrangementBehavior(isEnabled: true) // add inner margin for phone + containerViewLeadingLayoutConstraint.constant = 0 // remove outer margin for phone + containerViewTrailingLayoutConstraint.constant = 0 + } + + switch traitCollection.userInterfaceIdiom { + case .phone: + setupContainerForPhone() + default: + guard traitCollection.horizontalSizeClass == .regular else { + setupContainerForPhone() + return + } + containerView.updateContainerViewComponentsLayoutMarginsRelativeArrangementBehavior(isEnabled: false) // remove margin for iPad + containerViewLeadingLayoutConstraint.constant = Self.containerViewMarginForRegularHorizontalSizeClass // add outer margin for iPad + containerViewTrailingLayoutConstraint.constant = Self.containerViewMarginForRegularHorizontalSizeClass + } + } + + public var containerViewHorizontalMargin: CGFloat { + containerViewLeadingLayoutConstraint.constant + containerViewTrailingLayoutConstraint.constant + } + +} diff --git a/MastodonSDK/Sources/MastodonUI/Vendor/ItemProviderLoader.swift b/MastodonSDK/Sources/MastodonUI/Vendor/ItemProviderLoader.swift index 6662f90e..ef0c36f1 100644 --- a/MastodonSDK/Sources/MastodonUI/Vendor/ItemProviderLoader.swift +++ b/MastodonSDK/Sources/MastodonUI/Vendor/ItemProviderLoader.swift @@ -55,6 +55,24 @@ extension ItemProviderLoader { ] as CFDictionary guard let cgImage = CGImageSourceCreateThumbnailAtIndex(source, 0, downsampleOptions) else { + // fallback to loadItem when create thumbnail failure + itemProvider.loadItem(forTypeIdentifier: UTType.image.identifier, options: nil) { image, error in + if let error = error { + promise(.failure(error)) + } + + guard let image = image as? UIImage, + let data = image.jpegData(compressionQuality: 0.75) + else { + promise(.success(nil)) + assertionFailure() + return + } + + let file = Mastodon.Query.MediaAttachment.jpeg(data) + promise(.success(file)) + + } // end itemProvider.loadItem return } diff --git a/MastodonSDK/Sources/MastodonUI/View/Button/AvatarButton.swift b/MastodonSDK/Sources/MastodonUI/View/Button/AvatarButton.swift index 3854c470..57257fd8 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Button/AvatarButton.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Button/AvatarButton.swift @@ -7,6 +7,7 @@ import os.log import UIKit +import MastodonLocalization open class AvatarButton: UIControl { @@ -37,6 +38,9 @@ open class AvatarButton: UIControl { avatarImageView.trailingAnchor.constraint(equalTo: trailingAnchor), avatarImageView.bottomAnchor.constraint(equalTo: bottomAnchor), ]) + + isAccessibilityElement = true + accessibilityLabel = L10n.Common.Controls.Status.showUserProfile } public override func layoutSubviews() { diff --git a/MastodonSDK/Sources/MastodonUI/View/Container/AdaptiveMarginContainerView.swift b/MastodonSDK/Sources/MastodonUI/View/Container/AdaptiveMarginContainerView.swift new file mode 100644 index 00000000..3bc6c781 --- /dev/null +++ b/MastodonSDK/Sources/MastodonUI/View/Container/AdaptiveMarginContainerView.swift @@ -0,0 +1,61 @@ +// +// AdaptiveMarginContainerView.swift +// +// +// Created by MainasuK on 2022-2-18. +// + +import UIKit + +public final class AdaptiveMarginContainerView: UIView { + + public var margin: CGFloat = 0 { + didSet { updateConstraints() } + } + + public var contentView: UIView? { + didSet { + guard let contentView = contentView else { return } + guard contentView.superview == nil else { return } + + contentView.translatesAutoresizingMaskIntoConstraints = false + addSubview(contentView) + + let _topLayoutConstraint = contentView.topAnchor.constraint(equalTo: topAnchor) + let _leadingLayoutConstraint = contentView.leadingAnchor.constraint(equalTo: leadingAnchor) + let _trailingLayoutConstraint = trailingAnchor.constraint(equalTo: contentView.trailingAnchor) + let _bottomLayoutConstraint = bottomAnchor.constraint(equalTo: contentView.bottomAnchor) + + NSLayoutConstraint.activate([ + _topLayoutConstraint, + _leadingLayoutConstraint, + _trailingLayoutConstraint, + _bottomLayoutConstraint + ]) + + topLayoutConstraint = _topLayoutConstraint + leadingLayoutConstraint = _leadingLayoutConstraint + trailingLayoutConstraint = _trailingLayoutConstraint + bottomLayoutConstraint = _bottomLayoutConstraint + + updateConstraints() + } + } + + private(set) var topLayoutConstraint: NSLayoutConstraint? + private(set) var leadingLayoutConstraint: NSLayoutConstraint? + private(set) var trailingLayoutConstraint: NSLayoutConstraint? + private(set) var bottomLayoutConstraint: NSLayoutConstraint? + +} + +extension AdaptiveMarginContainerView { + + public override func updateConstraints() { + super.updateConstraints() + + leadingLayoutConstraint?.constant = margin + trailingLayoutConstraint?.constant = margin + } + +} diff --git a/MastodonSDK/Sources/MastodonUI/View/Container/MediaGridContainerView.swift b/MastodonSDK/Sources/MastodonUI/View/Container/MediaGridContainerView.swift index 41d97c0f..cb9c53f3 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Container/MediaGridContainerView.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Container/MediaGridContainerView.swift @@ -74,6 +74,13 @@ public final class MediaGridContainerView: UIView { super.init(coder: coder) _init() } + + public override var accessibilityElements: [Any]? { + get { + mediaViews + } + set { } + } } diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/MediaView.swift b/MastodonSDK/Sources/MastodonUI/View/Content/MediaView.swift index 68847e74..f4cee092 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/MediaView.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/MediaView.swift @@ -22,6 +22,7 @@ public final class MediaView: UIView { formatter.allowedUnits = [.minute, .second] return formatter }() + public static let placeholderImage = UIImage.placeholder(color: .systemGray6) public let container = TouchBlockingView() @@ -104,6 +105,8 @@ extension MediaView { extension MediaView { private func _init() { // lazy load content later + + isAccessibilityElement = true } public func setup(configuration: Configuration) { @@ -115,13 +118,18 @@ extension MediaView { case .image(let info): layoutImage() bindImage(configuration: configuration, info: info) + accessibilityLabel = "Show image" // TODO: i18n case .gif(let info): layoutGIF() bindGIF(configuration: configuration, info: info) + accessibilityLabel = "Show GIF" // TODO: i18n case .video(let info): layoutVideo() bindVideo(configuration: configuration, info: info) + accessibilityLabel = "Show video player" // TODO: i18n } + + accessibilityHint = "Tap then hold to show menu" // TODO: i18n layoutBlurhash() bindBlurhash(configuration: configuration) @@ -147,7 +155,10 @@ extension MediaView { .receive(on: DispatchQueue.main) .sink { [weak self] isReveal, previewImage, blurhashImage in guard let self = self else { return } - let image = isReveal ? previewImage : blurhashImage + + let image = isReveal ? + (previewImage ?? blurhashImage ?? MediaView.placeholderImage) : + (blurhashImage ?? MediaView.placeholderImage) self.imageView.image = image } .store(in: &configuration.disposeBag) @@ -197,30 +208,6 @@ extension MediaView { assetURL: info.previewURL ) bindImage(configuration: configuration, info: imageInfo) - -// indicatorBlurEffectView.translatesAutoresizingMaskIntoConstraints = false -// imageView.addSubview(indicatorBlurEffectView) -// NSLayoutConstraint.activate([ -// imageView.trailingAnchor.constraint(equalTo: indicatorBlurEffectView.trailingAnchor, constant: 11), -// imageView.bottomAnchor.constraint(equalTo: indicatorBlurEffectView.bottomAnchor, constant: 8), -// ]) -// setupIndicatorViewHierarchy() - -// playerIndicatorLabel.attributedText = { -// let imageAttachment = NSTextAttachment(image: UIImage(systemName: "play.fill")!) -// let imageAttributedString = AttributedString(NSAttributedString(attachment: imageAttachment)) -// let duration: String = { -// guard let durationMS = info.durationMS else { return "" } -// let timeInterval = TimeInterval(durationMS / 1000) -// guard timeInterval > 0 else { return "" } -// guard let text = MediaView.durationFormatter.string(from: timeInterval) else { return "" } -// return " \(text)" -// }() -// let textAttributedString = AttributedString("\(duration)") -// var attributedString = imageAttributedString + textAttributedString -// attributedString.foregroundColor = .secondaryLabel -// return NSAttributedString(attributedString) -// }() } private func layoutBlurhash() { @@ -277,6 +264,8 @@ extension MediaView { playerViewController.player = nil playerLooper = nil + playbackImageView.removeFromSuperview() + // blurhash blurhashImageView.removeFromSuperview() blurhashImageView.removeConstraints(blurhashImageView.constraints) diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/NotificationView.swift b/MastodonSDK/Sources/MastodonUI/View/Content/NotificationView.swift index 78ebdbcd..8827eada 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/NotificationView.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/NotificationView.swift @@ -19,14 +19,14 @@ public protocol NotificationViewDelegate: AnyObject { func notificationView(_ notificationView: NotificationView, statusView: StatusView, metaText: MetaText, didSelectMeta meta: Meta) func notificationView(_ notificationView: NotificationView, statusView: StatusView, spoilerOverlayViewDidPressed overlayView: SpoilerOverlayView) -// func notificationView(_ notificationView: NotificationView, statusView: StatusView, spoilerBannerViewDidPressed bannerView: SpoilerBannerView) + func notificationView(_ notificationView: NotificationView, statusView: StatusView, mediaGridContainerView: MediaGridContainerView, mediaView: MediaView, didSelectMediaViewAt index: Int) func notificationView(_ notificationView: NotificationView, statusView: StatusView, actionToolbarContainer: ActionToolbarContainer, buttonDidPressed button: UIButton, action: ActionToolbarContainer.Action) func notificationView(_ notificationView: NotificationView, quoteStatusView: StatusView, authorAvatarButtonDidPressed button: AvatarButton) func notificationView(_ notificationView: NotificationView, quoteStatusView: StatusView, metaText: MetaText, didSelectMeta meta: Meta) func notificationView(_ notificationView: NotificationView, quoteStatusView: StatusView, spoilerOverlayViewDidPressed overlayView: SpoilerOverlayView) - // func notificationView(_ notificationView: NotificationView, quoteStatusView: StatusView, spoilerBannerViewDidPressed bannerView: SpoilerBannerView) + func notificationView(_ notificationView: NotificationView, quoteStatusView: StatusView, mediaGridContainerView: MediaGridContainerView, mediaView: MediaView, didSelectMediaViewAt index: Int) // a11y func notificationView(_ notificationView: NotificationView, accessibilityActivate: Void) @@ -57,6 +57,7 @@ public final class NotificationView: UIView { }() // author + let authorAdaptiveMarginContainerView = AdaptiveMarginContainerView() let authorContainerView: UIStackView = { let stackView = UIStackView() stackView.axis = .horizontal @@ -103,6 +104,7 @@ public final class NotificationView: UIView { public let statusView = StatusView() public let quoteStatusViewContainerView = UIView() + public let quoteBackgroundView = UIView() public let quoteStatusView = StatusView() public func prepareForReuse() { @@ -135,7 +137,7 @@ public final class NotificationView: UIView { extension NotificationView { private func _init() { // container: V - [ author container | (authorContainerViewBottomPaddingView) | statusView | quoteStatusView ] - containerStackView.layoutMargins = StatusView.containerLayoutMargin + // containerStackView.layoutMargins = StatusView.containerLayoutMargin containerStackView.translatesAutoresizingMaskIntoConstraints = false addSubview(containerStackView) @@ -147,9 +149,10 @@ extension NotificationView { ]) // author container: H - [ avatarButton | author meta container ] - authorContainerView.preservesSuperviewLayoutMargins = true - authorContainerView.isLayoutMarginsRelativeArrangement = true - containerStackView.addArrangedSubview(authorContainerView) + authorAdaptiveMarginContainerView.contentView = authorContainerView + authorAdaptiveMarginContainerView.margin = StatusView.containerLayoutMargin + containerStackView.addArrangedSubview(authorAdaptiveMarginContainerView) + UIContentSizeCategory.publisher .sink { [weak self] category in guard let self = self else { return } @@ -225,16 +228,9 @@ extension NotificationView { // quoteStatusView containerStackView.addArrangedSubview(quoteStatusViewContainerView) - quoteStatusViewContainerView.layoutMargins = UIEdgeInsets( - top: 0, - left: StatusView.containerLayoutMargin.left, - bottom: 16, - right: StatusView.containerLayoutMargin.right - ) + quoteStatusViewContainerView.layoutMargins = UIEdgeInsets(top: 0, left: 0, bottom: 16, right: 0) - let quoteBackgroundView = UIView() quoteBackgroundView.layoutMargins = UIEdgeInsets(top: 16, left: 0, bottom: 0, right: 0) - quoteBackgroundView.translatesAutoresizingMaskIntoConstraints = false quoteStatusViewContainerView.addSubview(quoteBackgroundView) NSLayoutConstraint.activate([ @@ -297,6 +293,19 @@ extension NotificationView { } +// MARK: - AdaptiveContainerView +extension NotificationView: AdaptiveContainerView { + public func updateContainerViewComponentsLayoutMarginsRelativeArrangementBehavior(isEnabled: Bool) { + let margin = isEnabled ? StatusView.containerLayoutMargin : .zero + authorAdaptiveMarginContainerView.margin = margin + quoteStatusViewContainerView.layoutMargins.left = margin + quoteStatusViewContainerView.layoutMargins.right = margin + + statusView.updateContainerViewComponentsLayoutMarginsRelativeArrangementBehavior(isEnabled: isEnabled) + quoteStatusView.updateContainerViewComponentsLayoutMarginsRelativeArrangementBehavior(isEnabled: true) // always set margins + } +} + extension NotificationView { public typealias AuthorMenuContext = StatusView.AuthorMenuContext @@ -366,7 +375,14 @@ extension NotificationView: StatusViewDelegate { } public func statusView(_ statusView: StatusView, mediaGridContainerView: MediaGridContainerView, mediaView: MediaView, didSelectMediaViewAt index: Int) { - assertionFailure() + switch statusView { + case self.statusView: + delegate?.notificationView(self, statusView: statusView, mediaGridContainerView: mediaGridContainerView, mediaView: mediaView, didSelectMediaViewAt: index) + case quoteStatusView: + delegate?.notificationView(self, quoteStatusView: statusView, mediaGridContainerView: mediaGridContainerView, mediaView: mediaView, didSelectMediaViewAt: index) + default: + assertionFailure() + } } public func statusView(_ statusView: StatusView, pollTableView tableView: UITableView, didSelectRowAt indexPath: IndexPath) { diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/PollOptionView+ViewModel.swift b/MastodonSDK/Sources/MastodonUI/View/Content/PollOptionView+ViewModel.swift index ff458e7a..e25e5d0a 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/PollOptionView+ViewModel.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/PollOptionView+ViewModel.swift @@ -50,6 +50,8 @@ extension PollOptionView { @Published public var primaryStripProgressViewTintColor: UIColor = Asset.Colors.brandBlue.color @Published public var secondaryStripProgressViewTintColor: UIColor = Asset.Colors.brandBlue.color.withAlphaComponent(0.5) + @Published public var groupedAccessibilityLabel = "" + init() { // selectState Publishers.CombineLatest3( @@ -136,9 +138,11 @@ extension PollOptionView.ViewModel { .sink { metaContent in guard let metaContent = metaContent else { view.optionTextField.text = "" + view.optionTextField.accessibilityLabel = "" return } view.optionTextField.text = metaContent.string + view.optionTextField.accessibilityLabel = metaContent.string } .store(in: &disposeBag) // selectState @@ -175,6 +179,21 @@ extension PollOptionView.ViewModel { } } .store(in: &disposeBag) + + bindAccessibility(view: view) + } + + private func bindAccessibility(view: PollOptionView) { + $selectState + .sink { selectState in + switch selectState { + case .on: + view.accessibilityTraits.insert(.selected) + default: + view.accessibilityTraits.remove(.selected) + } + } + .store(in: &disposeBag) } } diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/PollOptionView.swift b/MastodonSDK/Sources/MastodonUI/View/Content/PollOptionView.swift index d56ac06e..df000233 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/PollOptionView.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/PollOptionView.swift @@ -177,6 +177,26 @@ extension PollOptionView { plusCircleImageView.isHidden = true updateCornerRadius() + + isAccessibilityElement = true + } + + public override var accessibilityLabel: String? { + get { + switch viewModel.voteState { + case .reveal: + return [ + optionTextField, + optionPercentageLabel + ] + .compactMap { $0.accessibilityLabel } + .joined(separator: ", ") + + case .hidden: + return optionTextField.accessibilityLabel + } + } + set { } } public override func layoutSubviews() { diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/StatusMetricView.swift b/MastodonSDK/Sources/MastodonUI/View/Content/StatusMetricView.swift index 7b356fc6..2a770f30 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/StatusMetricView.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/StatusMetricView.swift @@ -71,8 +71,8 @@ extension StatusMetricView { addSubview(containerStackView) NSLayoutConstraint.activate([ containerStackView.topAnchor.constraint(equalTo: topAnchor, constant: 8), - containerStackView.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor), - containerStackView.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor), + containerStackView.leadingAnchor.constraint(equalTo: leadingAnchor), + containerStackView.trailingAnchor.constraint(equalTo: trailingAnchor), bottomAnchor.constraint(equalTo: containerStackView.bottomAnchor, constant: 12), ]) diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/StatusView+ViewModel.swift b/MastodonSDK/Sources/MastodonUI/View/Content/StatusView+ViewModel.swift index da529ea1..f848b37e 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/StatusView+ViewModel.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/StatusView+ViewModel.swift @@ -50,6 +50,7 @@ extension StatusView { // Status @Published public var content: MetaContent? + @Published public var language: String? // Media @Published public var mediaViewConfigurations: [MediaView.Configuration] = [] @@ -88,6 +89,11 @@ extension StatusView { @Published public var replyCount: Int = 0 @Published public var reblogCount: Int = 0 @Published public var favoriteCount: Int = 0 + + // Filter + @Published public var activeFilters: [Mastodon.Entity.Filter] = [] + @Published public var filterContext: Mastodon.Entity.Filter.Context? + @Published public var isFiltered = false @Published public var groupedAccessibilityLabel = "" @@ -127,9 +133,8 @@ extension StatusView { isMediaSensitive = false isMediaSensitiveToggled = false -// isSensitive = false -// isContentReveal = false -// isMediaReveal = false + activeFilters = [] + filterContext = nil } init() { @@ -191,6 +196,7 @@ extension StatusView.ViewModel { bindToolbar(statusView: statusView) bindMetric(statusView: statusView) bindMenu(statusView: statusView) + bindFilter(statusView: statusView) bindAccessibility(statusView: statusView) } @@ -273,12 +279,13 @@ extension StatusView.ViewModel { } private func bindContent(statusView: StatusView) { - Publishers.CombineLatest3( + Publishers.CombineLatest4( $spoilerContent, $content, + $language, $isContentReveal.removeDuplicates() ) - .sink { spoilerContent, content, isContentReveal in + .sink { spoilerContent, content, language, isContentReveal in if let spoilerContent = spoilerContent { statusView.spoilerOverlayView.spoilerMetaLabel.configure(content: spoilerContent) // statusView.spoilerBannerView.label.configure(content: spoilerContent) @@ -289,10 +296,18 @@ extension StatusView.ViewModel { // statusView.spoilerBannerView.label.reset() } + let paragraphStyle = statusView.contentMetaText.paragraphStyle + if let language = language { + let direction = Locale.characterDirection(forLanguage: language) + paragraphStyle.alignment = direction == .rightToLeft ? .right : .left + } else { + paragraphStyle.alignment = .natural + } + statusView.contentMetaText.paragraphStyle = paragraphStyle + if let content = content { statusView.contentMetaText.configure( - content: content, - isRedactedModeEnabled: !isContentReveal + content: content ) statusView.contentMetaText.textView.accessibilityLabel = content.string statusView.contentMetaText.textView.accessibilityTraits = [.staticText] @@ -302,6 +317,8 @@ extension StatusView.ViewModel { statusView.contentMetaText.textView.accessibilityLabel = "" } + statusView.contentMetaText.textView.alpha = isContentReveal ? 1 : 0 // keep the frame size and only display when revealing + statusView.setSpoilerOverlayViewHidden(isHidden: isContentReveal) let image = isContentReveal ? UIImage(systemName: "eye.slash.fill") : UIImage(systemName: "eye.fill") @@ -310,95 +327,33 @@ extension StatusView.ViewModel { self.logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): isContentReveal: \(isContentReveal)") } .store(in: &disposeBag) + $isSensitive .sink { isSensitive in guard isSensitive else { return } statusView.setContentSensitiveeToggleButtonDisplay() } .store(in: &disposeBag) - // visibility - Publishers.CombineLatest( - $visibility, - $isMyself - ) - .sink { visibility, isMyself in - switch visibility { - case .public: - break - case .unlisted: - statusView.statusVisibilityView.label.text = "Everyone can see this post but not display in the public timeline." - statusView.setVisibilityDisplay() - case .private: - statusView.statusVisibilityView.label.text = isMyself ? "Only my followers can see this post." : "Only their followers can see this post." - statusView.setVisibilityDisplay() - case .direct: - statusView.statusVisibilityView.label.text = "Only mentioned user can see this post." - statusView.setVisibilityDisplay() - case ._other: - break - } - } - .store(in: &disposeBag) -// $isSensitive -// .sink { isSensitive in -// if isSensitive { -// statusView.setStatusSpoilerBannerViewDisplay() -// } -// } -// .store(in: &disposeBag) -// $spoilerContent -// .sink { metaContent in -// guard let metaContent = metaContent else { -// statusView.spoilerContentTextView.reset() -// return -// } -// statusView.spoilerContentTextView.configure(content: metaContent) -// statusView.setSpoilerDisplay() -// } -// .store(in: &disposeBag) -// + +// // visibility // Publishers.CombineLatest( -// $isContentReveal, -// $spoilerContent +// $visibility, +// $isMyself // ) -// .receive(on: DispatchQueue.main) -// .sink { [weak self] isContentReveal, spoilerContent in -// guard let self = self else { return } -// guard spoilerContent != nil else { -// // ignore reveal state when no spoiler exists -// statusView.contentTextView.isHidden = false -// return -// } -// -// statusView.contentTextView.isHidden = !isContentReveal -// self.contentRevealChangePublisher.send() -// } -// .store(in: &disposeBag) -// $source -// .sink { source in -// statusView.metricsDashboardView.sourceLabel.text = source ?? "" -// } -// .store(in: &disposeBag) -// // dashboard -// Publishers.CombineLatest4( -// $replyCount, -// $reblogCount, -// $quoteCount, -// $favoriteCount -// ) -// .sink { replyCount, reblogCount, quoteCount, favoriteCount in -// switch statusView.style { -// case .plain: -// statusView.setMetricsDisplay() -// -// statusView.metricsDashboardView.setupReply(count: replyCount) -// statusView.metricsDashboardView.setupRepost(count: reblogCount) -// statusView.metricsDashboardView.setupQuote(count: quoteCount) -// statusView.metricsDashboardView.setupLike(count: favoriteCount) -// -// let needsDashboardDisplay = replyCount > 0 || reblogCount > 0 || quoteCount > 0 || favoriteCount > 0 -// statusView.metricsDashboardView.dashboardContainer.isHidden = !needsDashboardDisplay -// default: +// .sink { visibility, isMyself in +// switch visibility { +// case .public: +// break +// case .unlisted: +// statusView.statusVisibilityView.label.text = "Everyone can see this post but not display in the public timeline." +// statusView.setVisibilityDisplay() +// case .private: +// statusView.statusVisibilityView.label.text = isMyself ? "Only my followers can see this post." : "Only their followers can see this post." +// statusView.setVisibilityDisplay() +// case .direct: +// statusView.statusVisibilityView.label.text = "Only mentioned user can see this post." +// statusView.setVisibilityDisplay() +// case ._other: // break // } // } @@ -663,6 +618,17 @@ extension StatusView.ViewModel { .store(in: &disposeBag) } + private func bindFilter(statusView: StatusView) { + $isFiltered + .sink { isFiltered in + statusView.containerStackView.isHidden = isFiltered + if isFiltered { + statusView.setFilterHintLabelDisplay() + } + } + .store(in: &disposeBag) + } + private func bindAccessibility(statusView: StatusView) { let authorAccessibilityLabel = Publishers.CombineLatest3( $header, @@ -698,6 +664,9 @@ extension StatusView.ViewModel { if let spoilerContent = spoilerContent, !spoilerContent.string.isEmpty { strings.append(L10n.Common.Controls.Status.contentWarning) strings.append(spoilerContent.string) + + // TODO: replace with "Tap to reveal" + strings.append(L10n.Common.Controls.Status.mediaContentWarning) } if isContentReveal { @@ -707,6 +676,21 @@ extension StatusView.ViewModel { return strings.compactMap { $0 }.joined(separator: ", ") } + $isContentReveal + .map { isContentReveal in + isContentReveal ? L10n.Scene.Compose.Accessibility.enableContentWarning : L10n.Scene.Compose.Accessibility.disableContentWarning + } + .sink { label in + statusView.contentSensitiveeToggleButton.accessibilityLabel = label + } + .store(in: &disposeBag) + + contentAccessibilityLabel + .sink { contentAccessibilityLabel in + statusView.spoilerOverlayView.accessibilityLabel = contentAccessibilityLabel + } + .store(in: &disposeBag) + let meidaAccessibilityLabel = $mediaViewConfigurations .map { configurations -> String? in let count = configurations.count diff --git a/MastodonSDK/Sources/MastodonUI/View/Content/StatusView.swift b/MastodonSDK/Sources/MastodonUI/View/Content/StatusView.swift index d6b37656..b938f2b9 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Content/StatusView.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Content/StatusView.swift @@ -24,19 +24,15 @@ public protocol StatusViewDelegate: AnyObject { func statusView(_ statusView: StatusView, actionToolbarContainer: ActionToolbarContainer, buttonDidPressed button: UIButton, action: ActionToolbarContainer.Action) func statusView(_ statusView: StatusView, menuButton button: UIButton, didSelectAction action: MastodonMenu.Action) func statusView(_ statusView: StatusView, spoilerOverlayViewDidPressed overlayView: SpoilerOverlayView) - // func statusView(_ statusView: StatusView, spoilerBannerViewDidPressed bannerView: SpoilerBannerView) func statusView(_ statusView: StatusView, mediaGridContainerView: MediaGridContainerView, mediaSensitiveButtonDidPressed button: UIButton) // a11y func statusView(_ statusView: StatusView, accessibilityActivate: Void) - -// func statusView(_ statusView: StatusView, contentWarningOverlayViewDidPressed contentWarningOverlayView: ContentWarningOverlayView) -// func statusView(_ statusView: StatusView, playerContainerView: PlayerContainerView, contentWarningOverlayViewDidPressed contentWarningOverlayView: ContentWarningOverlayView) } public final class StatusView: UIView { - public static let containerLayoutMargin = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16) + public static let containerLayoutMargin: CGFloat = 16 let logger = Logger(subsystem: "StatusView", category: "View") @@ -61,7 +57,8 @@ public final class StatusView: UIView { }() // header - let headerContainerView = UIView() + let headerAdaptiveMarginContainerView = AdaptiveMarginContainerView() + public let headerContainerView = UIView() // header icon let headerIconImageView: UIImageView = { @@ -75,6 +72,7 @@ public final class StatusView: UIView { let headerInfoLabel = MetaLabel(style: .statusHeader) // author + let authorAdaptiveMarginContainerView = AdaptiveMarginContainerView() let authorContainerView: UIStackView = { let stackView = UIStackView() stackView.axis = .horizontal @@ -106,6 +104,7 @@ public final class StatusView: UIView { button.tintColor = Asset.Colors.Label.secondary.color let image = UIImage(systemName: "ellipsis", withConfiguration: UIImage.SymbolConfiguration(font: .systemFont(ofSize: 15))) button.setImage(image, for: .normal) + button.accessibilityLabel = L10n.Common.Controls.Status.Actions.menu return button }() @@ -121,6 +120,7 @@ public final class StatusView: UIView { }() // content + let contentAdaptiveMarginContainerView = AdaptiveMarginContainerView() let contentContainer = UIStackView() public let contentMetaText: MetaText = { let metaText = MetaText() @@ -152,14 +152,15 @@ public final class StatusView: UIView { }() // content warning - let spoilerOverlayView = SpoilerOverlayView() + public let spoilerOverlayView = SpoilerOverlayView() // media public let mediaContainerView = UIView() public let mediaGridContainerView = MediaGridContainerView() // poll - public let pollContainerView = UIStackView() + let pollAdaptiveMarginContainerView = AdaptiveMarginContainerView() + let pollContainerView = UIStackView() public let pollTableView: UITableView = { let tableView = UITableView(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) tableView.register(PollOptionTableViewCell.self, forCellReuseIdentifier: String(describing: PollOptionTableViewCell.self)) @@ -173,7 +174,7 @@ public final class StatusView: UIView { public var pollTableViewHeightLayoutConstraint: NSLayoutConstraint! public var pollTableViewDiffableDataSource: UITableViewDiffableDataSource<PollSection, PollItem>? - let pollStatusStackView = UIStackView() + public let pollStatusStackView = UIStackView() let pollVoteCountLabel: UILabel = { let label = UILabel() label.font = UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 12, weight: .regular)) @@ -186,6 +187,7 @@ public final class StatusView: UIView { label.font = UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 12, weight: .regular)) label.textColor = Asset.Colors.Label.secondary.color label.text = " · " + label.isAccessibilityElement = false return label }() let pollCountdownLabel: UILabel = { @@ -211,19 +213,24 @@ public final class StatusView: UIView { indicatorView.stopAnimating() return indicatorView }() - - // visibility - public let statusVisibilityView = StatusVisibilityView() - - // spoiler banner - // public let spoilerBannerView = SpoilerBannerView() - + // toolbar + let actionToolbarAdaptiveMarginContainerView = AdaptiveMarginContainerView() public let actionToolbarContainer = ActionToolbarContainer() // metric + let statusMetricViewAdaptiveMarginContainerView = AdaptiveMarginContainerView() public let statusMetricView = StatusMetricView() + // filter hint + public let filterHintLabel: UILabel = { + let label = UILabel() + label.textColor = Asset.Colors.Label.secondary.color + label.text = L10n.Common.Controls.Timeline.filtered + label.font = .systemFont(ofSize: 17, weight: .regular) + return label + }() + public func prepareForReuse() { disposeBag.removeAll() @@ -241,13 +248,12 @@ public final class StatusView: UIView { } } - headerContainerView.isHidden = true - contentSensitiveeToggleButton.isHidden = true + setHeaderDisplay(isDisplay: false) + setContentSensitiveeToggleButtonDisplay(isDisplay: false) setSpoilerOverlayViewHidden(isHidden: true) - mediaContainerView.isHidden = true - pollContainerView.isHidden = true - statusVisibilityView.isHidden = true - // setSpoilerBannerViewHidden(isHidden: true) + setMediaDisplay(isDisplay: false) + setPollDisplay(isDisplay: false) + setFilterHintLabelDisplay(isDisplay: false) } public override init(frame: CGRect) { @@ -312,12 +318,6 @@ extension StatusView { ]) pollTableView.delegate = self pollVoteButton.addTarget(self, action: #selector(StatusView.pollVoteButtonDidPressed(_:)), for: .touchUpInside) - - // statusSpoilerBannerView - // let spoilerBannerViewTapGestureRecognizer = UITapGestureRecognizer.singleTapGestureRecognizer - // spoilerBannerView.addGestureRecognizer(spoilerBannerViewTapGestureRecognizer) - // spoilerBannerViewTapGestureRecognizer.addTarget(self, action: #selector(StatusView.spoilerBannerViewTapGestureRecognizerHandler(_:))) - // toolbar actionToolbarContainer.delegate = self } @@ -351,11 +351,6 @@ extension StatusView { delegate?.statusView(self, spoilerOverlayViewDidPressed: spoilerOverlayView) } -// @objc private func spoilerBannerViewTapGestureRecognizerHandler(_ sender: UITapGestureRecognizer) { -// logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)") -// delegate?.statusView(self, spoilerBannerViewDidPressed: spoilerBannerView) -// } - } extension StatusView { @@ -397,22 +392,23 @@ extension StatusView.Style { private func base(statusView: StatusView) { // container: V - [ header container | author container | content container | media container | pollTableView | actionToolbarContainer ] - statusView.containerStackView.layoutMargins = StatusView.containerLayoutMargin // header container: H - [ icon | label ] - statusView.headerContainerView.preservesSuperviewLayoutMargins = true - statusView.containerStackView.addArrangedSubview(statusView.headerContainerView) + statusView.headerAdaptiveMarginContainerView.contentView = statusView.headerContainerView + statusView.headerAdaptiveMarginContainerView.margin = StatusView.containerLayoutMargin + statusView.containerStackView.addArrangedSubview(statusView.headerAdaptiveMarginContainerView) + statusView.headerIconImageView.translatesAutoresizingMaskIntoConstraints = false statusView.headerInfoLabel.translatesAutoresizingMaskIntoConstraints = false statusView.headerContainerView.addSubview(statusView.headerIconImageView) statusView.headerContainerView.addSubview(statusView.headerInfoLabel) NSLayoutConstraint.activate([ - statusView.headerIconImageView.leadingAnchor.constraint(equalTo: statusView.headerContainerView.layoutMarginsGuide.leadingAnchor), + statusView.headerIconImageView.leadingAnchor.constraint(equalTo: statusView.headerContainerView.leadingAnchor), statusView.headerIconImageView.heightAnchor.constraint(equalTo: statusView.headerInfoLabel.heightAnchor, multiplier: 1.0).priority(.required - 1), statusView.headerIconImageView.widthAnchor.constraint(equalTo: statusView.headerIconImageView.heightAnchor, multiplier: 1.0).priority(.required - 1), statusView.headerInfoLabel.topAnchor.constraint(equalTo: statusView.headerContainerView.topAnchor), statusView.headerInfoLabel.leadingAnchor.constraint(equalTo: statusView.headerIconImageView.trailingAnchor, constant: 6), - statusView.headerInfoLabel.trailingAnchor.constraint(equalTo: statusView.headerContainerView.layoutMarginsGuide.trailingAnchor), + statusView.headerInfoLabel.trailingAnchor.constraint(equalTo: statusView.headerContainerView.trailingAnchor), statusView.headerInfoLabel.bottomAnchor.constraint(equalTo: statusView.headerContainerView.bottomAnchor), statusView.headerInfoLabel.centerYAnchor.constraint(equalTo: statusView.headerIconImageView.centerYAnchor), ]) @@ -423,9 +419,10 @@ extension StatusView.Style { statusView.headerIconImageView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) // author container: H - [ avatarButton | author meta container | contentWarningToggleButton ] - statusView.authorContainerView.preservesSuperviewLayoutMargins = true - statusView.authorContainerView.isLayoutMarginsRelativeArrangement = true - statusView.containerStackView.addArrangedSubview(statusView.authorContainerView) + statusView.authorAdaptiveMarginContainerView.contentView = statusView.authorContainerView + statusView.authorAdaptiveMarginContainerView.margin = StatusView.containerLayoutMargin + statusView.containerStackView.addArrangedSubview(statusView.authorAdaptiveMarginContainerView) + UIContentSizeCategory.publisher .sink { category in statusView.authorContainerView.axis = category > .accessibilityLarge ? .vertical : .horizontal @@ -503,9 +500,9 @@ extension StatusView.Style { statusView.contentContainer.distribution = .fill statusView.contentContainer.alignment = .top - statusView.contentContainer.preservesSuperviewLayoutMargins = true - statusView.contentContainer.isLayoutMarginsRelativeArrangement = true - statusView.containerStackView.addArrangedSubview(statusView.contentContainer) + statusView.contentAdaptiveMarginContainerView.contentView = statusView.contentContainer + statusView.contentAdaptiveMarginContainerView.margin = StatusView.containerLayoutMargin + statusView.containerStackView.addArrangedSubview(statusView.contentAdaptiveMarginContainerView) statusView.contentContainer.setContentHuggingPriority(.required - 1, for: .vertical) statusView.contentContainer.setContentCompressionResistancePriority(.required - 1, for: .vertical) @@ -522,7 +519,12 @@ extension StatusView.Style { ]) // media container: V - [ mediaGridContainerView ] + statusView.mediaContainerView.translatesAutoresizingMaskIntoConstraints = false statusView.containerStackView.addArrangedSubview(statusView.mediaContainerView) + NSLayoutConstraint.activate([ + statusView.mediaContainerView.leadingAnchor.constraint(equalTo: statusView.containerStackView.leadingAnchor), + statusView.mediaContainerView.trailingAnchor.constraint(equalTo: statusView.containerStackView.trailingAnchor), + ]) statusView.mediaGridContainerView.translatesAutoresizingMaskIntoConstraints = false statusView.mediaContainerView.addSubview(statusView.mediaGridContainerView) @@ -534,15 +536,15 @@ extension StatusView.Style { ]) // pollContainerView: V - [ pollTableView | pollStatusStackView ] + statusView.pollAdaptiveMarginContainerView.contentView = statusView.pollContainerView + statusView.pollAdaptiveMarginContainerView.margin = StatusView.containerLayoutMargin statusView.pollContainerView.axis = .vertical - statusView.pollContainerView.preservesSuperviewLayoutMargins = true - statusView.pollContainerView.isLayoutMarginsRelativeArrangement = true - statusView.containerStackView.addArrangedSubview(statusView.pollContainerView) + statusView.containerStackView.addArrangedSubview(statusView.pollAdaptiveMarginContainerView) // pollTableView statusView.pollContainerView.addArrangedSubview(statusView.pollTableView) - // pollStatusStackView + // pollStatusStackView: H - [ pollVoteCountLabel | pollCountdownLabel | pollVoteButton ] statusView.pollStatusStackView.axis = .horizontal statusView.pollContainerView.addArrangedSubview(statusView.pollStatusStackView) @@ -556,24 +558,23 @@ extension StatusView.Style { statusView.pollCountdownLabel.setContentHuggingPriority(.defaultLow, for: .horizontal) statusView.pollVoteButton.setContentHuggingPriority(.defaultHigh + 3, for: .horizontal) - // statusVisibilityView - statusView.statusVisibilityView.preservesSuperviewLayoutMargins = true - statusView.containerStackView.addArrangedSubview(statusView.statusVisibilityView) - - // spoilerBannerView - // statusView.spoilerBannerView.preservesSuperviewLayoutMargins = true - // statusView.containerStackView.addArrangedSubview(statusView.spoilerBannerView) - // action toolbar + statusView.actionToolbarAdaptiveMarginContainerView.contentView = statusView.actionToolbarContainer + statusView.actionToolbarAdaptiveMarginContainerView.margin = StatusView.containerLayoutMargin statusView.actionToolbarContainer.configure(for: .inline) - statusView.actionToolbarContainer.preservesSuperviewLayoutMargins = true - statusView.containerStackView.addArrangedSubview(statusView.actionToolbarContainer) + statusView.containerStackView.addArrangedSubview(statusView.actionToolbarAdaptiveMarginContainerView) + + // filterHintLabel + statusView.filterHintLabel.translatesAutoresizingMaskIntoConstraints = false + statusView.addSubview(statusView.filterHintLabel) + NSLayoutConstraint.activate([ + statusView.filterHintLabel.centerXAnchor.constraint(equalTo: statusView.containerStackView.centerXAnchor), + statusView.filterHintLabel.centerYAnchor.constraint(equalTo: statusView.containerStackView.centerYAnchor), + ]) } func inline(statusView: StatusView) { base(statusView: statusView) - - statusView.statusVisibilityView.removeFromSuperview() } func plain(statusView: StatusView) { @@ -581,8 +582,10 @@ extension StatusView.Style { base(statusView: statusView) // override the base style // statusMetricView - statusView.statusMetricView.layoutMargins = StatusView.containerLayoutMargin - statusView.containerStackView.addArrangedSubview(statusView.statusMetricView) + statusView.statusMetricViewAdaptiveMarginContainerView.contentView = statusView.statusMetricView + statusView.statusMetricViewAdaptiveMarginContainerView.margin = StatusView.containerLayoutMargin + statusView.containerStackView.addArrangedSubview(statusView.statusMetricViewAdaptiveMarginContainerView) + UIContentSizeCategory.publisher .sink { category in statusView.statusMetricView.containerStackView.axis = category > .accessibilityLarge ? .vertical : .horizontal @@ -595,26 +598,24 @@ extension StatusView.Style { base(statusView: statusView) // override the base style statusView.menuButton.removeFromSuperview() - statusView.statusVisibilityView.removeFromSuperview() - statusView.actionToolbarContainer.removeFromSuperview() + statusView.actionToolbarAdaptiveMarginContainerView.removeFromSuperview() } func notification(statusView: StatusView) { base(statusView: statusView) // override the base style - statusView.headerContainerView.removeFromSuperview() - statusView.authorContainerView.removeFromSuperview() - statusView.statusVisibilityView.removeFromSuperview() + statusView.headerAdaptiveMarginContainerView.removeFromSuperview() + statusView.authorAdaptiveMarginContainerView.removeFromSuperview() } func notificationQuote(statusView: StatusView) { base(statusView: statusView) // override the base style - statusView.contentContainer.layoutMargins.bottom = 16 // fix contentText align to edge issue + statusView.contentAdaptiveMarginContainerView.bottomLayoutConstraint?.constant = 16 // fix bottom margin missing issue + statusView.pollAdaptiveMarginContainerView.bottomLayoutConstraint?.constant = 16 // fix bottom margin missing issue statusView.contentSensitiveeToggleButton.removeFromSuperview() statusView.menuButton.removeFromSuperview() - statusView.statusVisibilityView.removeFromSuperview() - statusView.actionToolbarContainer.removeFromSuperview() + statusView.actionToolbarAdaptiveMarginContainerView.removeFromSuperview() } func composeStatusReplica(statusView: StatusView) { @@ -622,9 +623,7 @@ extension StatusView.Style { statusView.avatarButton.isUserInteractionEnabled = false statusView.menuButton.removeFromSuperview() - statusView.statusVisibilityView.removeFromSuperview() - // statusView.spoilerBannerView.removeFromSuperview() - statusView.actionToolbarContainer.removeFromSuperview() + statusView.actionToolbarAdaptiveMarginContainerView.removeFromSuperview() } func composeStatusAuthor(statusView: StatusView) { @@ -634,24 +633,22 @@ extension StatusView.Style { statusView.menuButton.removeFromSuperview() statusView.usernameTrialingDotLabel.removeFromSuperview() statusView.dateLabel.removeFromSuperview() - statusView.contentContainer.removeFromSuperview() + statusView.contentAdaptiveMarginContainerView.removeFromSuperview() statusView.spoilerOverlayView.removeFromSuperview() statusView.mediaContainerView.removeFromSuperview() - statusView.pollContainerView.removeFromSuperview() - statusView.statusVisibilityView.removeFromSuperview() - // statusView.spoilerBannerView.removeFromSuperview() - statusView.actionToolbarContainer.removeFromSuperview() + statusView.pollAdaptiveMarginContainerView.removeFromSuperview() + statusView.actionToolbarAdaptiveMarginContainerView.removeFromSuperview() } } extension StatusView { - func setHeaderDisplay() { - headerContainerView.isHidden = false + func setHeaderDisplay(isDisplay: Bool = true) { + headerAdaptiveMarginContainerView.isHidden = !isDisplay } - func setContentSensitiveeToggleButtonDisplay() { - contentSensitiveeToggleButton.isHidden = false + func setContentSensitiveeToggleButtonDisplay(isDisplay: Bool = true) { + contentSensitiveeToggleButton.isHidden = !isDisplay } func setSpoilerOverlayViewHidden(isHidden: Bool) { @@ -659,31 +656,35 @@ extension StatusView { spoilerOverlayView.setComponentHidden(isHidden) } - func setMediaDisplay() { - mediaContainerView.isHidden = false + func setMediaDisplay(isDisplay: Bool = true) { + mediaContainerView.isHidden = !isDisplay } - func setPollDisplay() { - pollContainerView.isHidden = false + func setPollDisplay(isDisplay: Bool = true) { + pollAdaptiveMarginContainerView.isHidden = !isDisplay } - func setVisibilityDisplay() { - statusVisibilityView.isHidden = false + func setFilterHintLabelDisplay(isDisplay: Bool = true) { + filterHintLabel.isHidden = !isDisplay } - // func setSpoilerBannerViewHidden(isHidden: Bool) { - // spoilerBannerView.isHidden = isHidden - // } - - // content text Width + // container width public var contentMaxLayoutWidth: CGFloat { - let inset = contentLayoutInset - return frame.width - inset.left - inset.right + return frame.width } - - public var contentLayoutInset: UIEdgeInsets { - // TODO: adaptive iPad regular horizontal size class - return .zero + +} + +// MARK: - AdaptiveContainerView +extension StatusView: AdaptiveContainerView { + public func updateContainerViewComponentsLayoutMarginsRelativeArrangementBehavior(isEnabled: Bool) { + let margin = isEnabled ? StatusView.containerLayoutMargin : .zero + headerAdaptiveMarginContainerView.margin = margin + authorAdaptiveMarginContainerView.margin = margin + contentAdaptiveMarginContainerView.margin = margin + pollAdaptiveMarginContainerView.margin = margin + actionToolbarAdaptiveMarginContainerView.margin = margin + statusMetricViewAdaptiveMarginContainerView.margin = margin } } diff --git a/MastodonSDK/Sources/MastodonUI/View/Control/ActionToolbarContainer.swift b/MastodonSDK/Sources/MastodonUI/View/Control/ActionToolbarContainer.swift index 3b4a9737..449254d2 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Control/ActionToolbarContainer.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Control/ActionToolbarContainer.swift @@ -48,10 +48,7 @@ public final class ActionToolbarContainer: UIView { extension ActionToolbarContainer { - private func _init() { - container.preservesSuperviewLayoutMargins = true - container.isLayoutMarginsRelativeArrangement = true - + private func _init() { container.translatesAutoresizingMaskIntoConstraints = false addSubview(container) NSLayoutConstraint.activate([ @@ -93,7 +90,7 @@ extension ActionToolbarContainer { replyButton.accessibilityLabel = L10n.Common.Controls.Status.Actions.reply reblogButton.accessibilityLabel = L10n.Common.Controls.Status.Actions.reblog // needs update to follow state favoriteButton.accessibilityLabel = L10n.Common.Controls.Status.Actions.favorite // needs update to follow state - shareButton.accessibilityLabel = L10n.Common.Controls.Status.Actions.menu + shareButton.accessibilityLabel = L10n.Common.Controls.Actions.share switch style { case .inline: @@ -219,6 +216,7 @@ extension ActionToolbarContainer { public func configureReply(count: Int, isEnabled: Bool) { let title = ActionToolbarContainer.title(from: count) replyButton.setTitle(title, for: .normal) + replyButton.accessibilityLabel = "\(count) reply" // TODO: i18n } public func configureReblog(count: Int, isEnabled: Bool, isHighlighted: Bool) { @@ -230,6 +228,13 @@ extension ActionToolbarContainer { reblogButton.tintColor = tintColor reblogButton.setTitleColor(tintColor, for: .normal) reblogButton.setTitleColor(tintColor, for: .highlighted) + + if isHighlighted { + reblogButton.accessibilityTraits.insert(.selected) + } else { + reblogButton.accessibilityTraits.remove(.selected) + } + reblogButton.accessibilityLabel = L10n.Plural.Count.reblog(count) } public func configureFavorite(count: Int, isEnabled: Bool, isHighlighted: Bool) { @@ -242,6 +247,13 @@ extension ActionToolbarContainer { favoriteButton.tintColor = tintColor favoriteButton.setTitleColor(tintColor, for: .normal) favoriteButton.setTitleColor(tintColor, for: .highlighted) + + if isHighlighted { + favoriteButton.accessibilityTraits.insert(.selected) + } else { + favoriteButton.accessibilityTraits.remove(.selected) + } + favoriteButton.accessibilityLabel = L10n.Plural.Count.favorite(count) } } diff --git a/MastodonSDK/Sources/MastodonUI/View/Control/SpoilerBannerView.swift b/MastodonSDK/Sources/MastodonUI/View/Control/SpoilerBannerView.swift index 9b5aa5a0..b7056a7a 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Control/SpoilerBannerView.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Control/SpoilerBannerView.swift @@ -6,8 +6,9 @@ // import UIKit -import MastodonAsset import MetaTextKit +import MastodonAsset +import MastodonLocalization public final class SpoilerBannerView: UIView { @@ -22,7 +23,7 @@ public final class SpoilerBannerView: UIView { let label = UILabel() label.textColor = Asset.Colors.Label.primary.color label.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 17, weight: .regular)) - label.text = "Hide" // TODO: i18n + label.text = L10n.Common.Controls.Status.Actions.hide return label }() diff --git a/MastodonSDK/Sources/MastodonUI/View/Control/SpoilerOverlayView.swift b/MastodonSDK/Sources/MastodonUI/View/Control/SpoilerOverlayView.swift index cf84bfa8..17360d54 100644 --- a/MastodonSDK/Sources/MastodonUI/View/Control/SpoilerOverlayView.swift +++ b/MastodonSDK/Sources/MastodonUI/View/Control/SpoilerOverlayView.swift @@ -70,6 +70,8 @@ extension SpoilerOverlayView { bottomPaddingView.setContentCompressionResistancePriority(.defaultLow - 100, for: .vertical) spoilerMetaLabel.isUserInteractionEnabled = false + + isAccessibilityElement = true } public func setComponentHidden(_ isHidden: Bool) { diff --git a/MastodonSDK/Tests/MastodonSDKTests/API/MastodonSDK+API+OAuthTests.swift b/MastodonSDK/Tests/MastodonSDKTests/API/MastodonSDK+API+OAuthTests.swift index b14aad24..c1f09eb9 100644 --- a/MastodonSDK/Tests/MastodonSDKTests/API/MastodonSDK+API+OAuthTests.swift +++ b/MastodonSDK/Tests/MastodonSDKTests/API/MastodonSDK+API+OAuthTests.swift @@ -22,7 +22,7 @@ extension MastodonSDKTests { os_log("%{public}s[%{public}ld], %{public}s: (%s) authorizeURL %s", ((#file as NSString).lastPathComponent), #line, #function, domain, authorizeURL.absoluteString) XCTAssertEqual( authorizeURL.absoluteString, - "https://\(domain)/oauth/authorize?response_type=code&client_id=StubClientID&redirect_uri=mastodon://joinmastodon.org/oauth&scope=read%20write%20follow%20push" + "\(URL.httpScheme(domain: domain))://\(domain)/oauth/authorize?response_type=code&client_id=StubClientID&redirect_uri=mastodon://joinmastodon.org/oauth&scope=read%20write%20follow%20push" ) } diff --git a/MastodonTests/Info.plist b/MastodonTests/Info.plist index 1c2f9cec..73f11cd2 100644 --- a/MastodonTests/Info.plist +++ b/MastodonTests/Info.plist @@ -17,6 +17,6 @@ <key>CFBundleShortVersionString</key> <string>1.3.0</string> <key>CFBundleVersion</key> - <string>96</string> + <string>109</string> </dict> </plist> diff --git a/MastodonTests/MastodonTests.swift b/MastodonTests/MastodonTests.swift index 5da71aa4..7264dde6 100644 --- a/MastodonTests/MastodonTests.swift +++ b/MastodonTests/MastodonTests.swift @@ -8,6 +8,7 @@ import XCTest @testable import Mastodon +@MainActor class MastodonTests: XCTestCase { override func setUpWithError() throws { @@ -43,4 +44,20 @@ extension MastodonTests { } wait(for: [expectation], timeout: 10) } + + @available(iOS 15.0, *) + func testConnectOnion() async throws { + let request = URLRequest( + url: URL(string: "http://a232ncr7jexk2chvubaq2v6qdizbocllqap7mnn7w7vrdutyvu32jeyd.onion/@k0gen")!, + cachePolicy: .reloadIgnoringLocalAndRemoteCacheData, + timeoutInterval: 10 + ) + do { + let data = try await URLSession.shared.data(for: request, delegate: nil) + print(data) + } catch { + debugPrint(error) + assertionFailure(error.localizedDescription) + } + } } diff --git a/MastodonUITests/Info.plist b/MastodonUITests/Info.plist index 1c2f9cec..73f11cd2 100644 --- a/MastodonUITests/Info.plist +++ b/MastodonUITests/Info.plist @@ -17,6 +17,6 @@ <key>CFBundleShortVersionString</key> <string>1.3.0</string> <key>CFBundleVersion</key> - <string>96</string> + <string>109</string> </dict> </plist> diff --git a/MastodonUITests/MastodonUISnapshotTests.swift b/MastodonUITests/MastodonUISnapshotTests.swift new file mode 100644 index 00000000..d3c5d2bf --- /dev/null +++ b/MastodonUITests/MastodonUISnapshotTests.swift @@ -0,0 +1,454 @@ +// +// MastodonUISnapshotTests.swift +// MastodonUITests +// +// Created by MainasuK on 2022-3-2. +// + +import XCTest + +extension UInt64 { + static let second: UInt64 = 1_000_000_000 +} + +@MainActor +class MastodonUISnapshotTests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + override class func tearDown() { + super.tearDown() + let app = XCUIApplication() + print(app.debugDescription) + } + +} + +extension MastodonUISnapshotTests { + + func testSmoke() async throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + // Any test you write for XCTest can be annotated as throws and async. + // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. + // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. + + } + +} + +extension MastodonUISnapshotTests { + + func takeSnapshot(name: String) { + let snapshot = XCUIScreen.main.screenshot() + let attachment = XCTAttachment( + uniformTypeIdentifier: "public.png", + name: "\(name).\(UIDevice.current.name).png", + payload: snapshot.pngRepresentation, + userInfo: nil + ) + attachment.lifetime = .keepAlways + add(attachment) + } + + // make tab display by tap it + private func tapTab(app: XCUIApplication, tab: String) { + let searchTab = app.tabBars.buttons[tab] + if searchTab.exists { searchTab.tap() } + + let searchCell = app.collectionViews.cells[tab] + if searchCell.exists { searchCell.tap() } + } + + private func showTitleButtonMenu(app: XCUIApplication) async throws { + let titleButton = app.navigationBars.buttons["TitleButton"].firstMatch + XCTAssert(titleButton.waitForExistence(timeout: 5)) + titleButton.press(forDuration: 1.0) + try await Task.sleep(nanoseconds: .second * 1) + } + + private func snapshot( + name: String, + count: Int = 3, + task: (_ app: XCUIApplication) async throws -> Void + ) async rethrows { + var app = XCUIApplication() + + // pass -1 to debug test case + guard count >= 0 else { + app.launch() + try await task(app) + takeSnapshot(name: name) + return + } + + // Light Mode + for index in 0..<count { + app.launch() + try await task(app) + + let name = "\(name).light.\(index+1)" + takeSnapshot(name: name) + } + + // Dark Mode + app = XCUIApplication() + app.launchArguments.append("UIUserInterfaceStyleForceDark") + for index in 0..<count { + app.launch() + try await task(app) + + let name = "\(name).dark.\(index+1)" + takeSnapshot(name: name) + } + } + +} + +// MARK: - Home +extension MastodonUISnapshotTests { + + func testSnapshotHome() async throws { + try await snapshot(name: "Home") { app in + tapTab(app: app, tab: "Home") + try await Task.sleep(nanoseconds: .second * 3) + } + } + +} + +// MARK: - Thread +extension MastodonUISnapshotTests { + + func testSnapshotThread() async throws { + try await snapshot(name: "Thread") { app in + let threadID = ProcessInfo.processInfo.environment["thread_id"]! + try await coordinateToThread(app: app, id: threadID) + try await Task.sleep(nanoseconds: .second * 5) + } + } + + // use debug entry goto thread scene by thread ID + // assert the thread ID is valid for current sign in user server + private func coordinateToThread(app: XCUIApplication, id: String) async throws { + try await Task.sleep(nanoseconds: .second * 1) + + try await showTitleButtonMenu(app: app) + + let showMenu = app.collectionViews.buttons["Show…"].firstMatch + XCTAssert(showMenu.waitForExistence(timeout: 3)) + showMenu.tap() + try await Task.sleep(nanoseconds: .second * 1) + + let threadAction = app.collectionViews.buttons["Thread"].firstMatch + XCTAssert(threadAction.waitForExistence(timeout: 3)) + threadAction.tap() + try await Task.sleep(nanoseconds: .second * 1) + + let textField = app.alerts.textFields.firstMatch + XCTAssert(textField.waitForExistence(timeout: 3)) + textField.typeText(id) + try await Task.sleep(nanoseconds: .second * 1) + + let showAction = app.alerts.buttons["Show"].firstMatch + XCTAssert(showAction.waitForExistence(timeout: 3)) + showAction.tap() + try await Task.sleep(nanoseconds: .second * 1) + } + +} + +// MARK: - Profile +extension MastodonUISnapshotTests { + + func testSnapshotProfile() async throws { + try await snapshot(name: "Profile") { app in + let profileID = ProcessInfo.processInfo.environment["profile_id"]! + try await coordinateToProfile(app: app, id: profileID) + try await Task.sleep(nanoseconds: .second * 5) + } + } + + // use debug entry goto thread scene by profile ID + // assert the profile ID is valid for current sign in user server + private func coordinateToProfile(app: XCUIApplication, id: String) async throws { + try await Task.sleep(nanoseconds: .second * 1) + + try await showTitleButtonMenu(app: app) + + let showMenu = app.collectionViews.buttons["Show…"].firstMatch + XCTAssert(showMenu.waitForExistence(timeout: 3)) + showMenu.tap() + try await Task.sleep(nanoseconds: .second * 1) + + let profileAction = app.collectionViews.buttons["Profile"].firstMatch + XCTAssert(profileAction.waitForExistence(timeout: 3)) + profileAction.tap() + try await Task.sleep(nanoseconds: .second * 1) + + let textField = app.alerts.textFields.firstMatch + XCTAssert(textField.waitForExistence(timeout: 3)) + textField.typeText(id) + try await Task.sleep(nanoseconds: .second * 1) + + let showAction = app.alerts.buttons["Show"].firstMatch + XCTAssert(showAction.waitForExistence(timeout: 3)) + showAction.tap() + try await Task.sleep(nanoseconds: .second * 1) + } + +} + + +// MARK: - Server Rules +extension MastodonUISnapshotTests { + + func testSnapshotServerRules() async throws { + try await snapshot(name: "ServerRules") { app in + let domain = "mastodon.social" + try await coordinateToOnboarding(app: app, page: .serverRules(domain: domain)) + try await Task.sleep(nanoseconds: .second * 3) + } + } + +} + +// MARK: - Search +extension MastodonUISnapshotTests { + + func testSnapshotSearch() async throws { + try await snapshot(name: "ServerRules") { app in + tapTab(app: app, tab: "Search") + try await Task.sleep(nanoseconds: .second * 3) + } + } + +} + +// MARK: - Compose +extension MastodonUISnapshotTests { + + func testSnapshotCompose() async throws { + try await snapshot(name: "Compose") { app in + // open Compose scene + let composeBarButtonItem = app.navigationBars.buttons["Compose"].firstMatch + let composeCollectionViewCell = app.collectionViews.cells["Compose"] + if composeBarButtonItem.waitForExistence(timeout: 5) { + composeBarButtonItem.tap() + } else if composeCollectionViewCell.waitForExistence(timeout: 5) { + composeCollectionViewCell.tap() + } else { + XCTFail() + } + + // type text + let textView = app.textViews.firstMatch + XCTAssert(textView.waitForExistence(timeout: 5)) + textView.tap() + textView.typeText("Look at that view! #Athens ") + + // tap Add Attachment toolbar button + let addAttachmentButton = app.buttons["Add Attachment"].firstMatch + XCTAssert(addAttachmentButton.waitForExistence(timeout: 5)) + addAttachmentButton.tap() + + // tap Browse menu action to add stub image + let browseButton = app.buttons["Browse"].firstMatch + XCTAssert(browseButton.waitForExistence(timeout: 5)) + browseButton.tap() + + try await Task.sleep(nanoseconds: .second * 10) + } + } + +} + +// MARK: Sign in +extension MastodonUISnapshotTests { + + // Please check the Documentation/Snapshot.md and run this test case in the command line + func testSignInAccount() async throws { + guard let domain = ProcessInfo.processInfo.environment["login_domain"] else { + fatalError("env 'login_domain' missing") + } + guard let email = ProcessInfo.processInfo.environment["login_email"] else { + fatalError("env 'login_email' missing") + } + guard let password = ProcessInfo.processInfo.environment["login_password"] else { + fatalError("env 'login_password' missing") + } + try await signInApplication( + domain: domain, + email: email, + password: password + ) + } + + func signInApplication( + domain: String, + email: String, + password: String + ) async throws { + let app = XCUIApplication() + app.launch() + + try await coordinateToOnboarding(app: app, page: .login(domain: domain)) + + // wait OAuth webpage display + try await Task.sleep(nanoseconds: .second * 10) + + let webview = app.webViews.firstMatch + XCTAssert(webview.waitForExistence(timeout: 10)) + + func tapAuthorizeButton() async throws -> Bool { + let authorizeButton = webview.buttons["AUTHORIZE"].firstMatch + if authorizeButton.exists { + authorizeButton.tap() + try await Task.sleep(nanoseconds: .second * 5) + return true + } + return false + } + + let isAuthorized = try await tapAuthorizeButton() + if !isAuthorized { + let emailTextField = webview.textFields["E-mail address"].firstMatch + XCTAssert(emailTextField.waitForExistence(timeout: 10)) + emailTextField.tap() + emailTextField.typeText(email) + + let passwordTextField = webview.secureTextFields["Password"].firstMatch + XCTAssert(passwordTextField.waitForExistence(timeout: 3)) + passwordTextField.tap() + passwordTextField.typeText(password) + + let goKeyboardButton = XCUIApplication().keyboards.buttons["Go"].firstMatch + XCTAssert(goKeyboardButton.waitForExistence(timeout: 3)) + goKeyboardButton.tap() + + var retry = 0 + let retryLimit = 20 + while webview.exists { + guard retry < retryLimit else { + fatalError("Cannot complete OAuth process") + } + retry += 1 + + // will break due to webview dismiss + _ = try await tapAuthorizeButton() + + print("Please enter the sign-in confirm code. Retry in 5s") + try await Task.sleep(nanoseconds: .second * 5) + } + } else { + // Done + } + + print("OAuth finish") + } + + enum OnboardingPage { + case welcome + case login(domain: String) + case serverRules(domain: String) + } + + private func coordinateToOnboarding(app: XCUIApplication, page: OnboardingPage) async throws { + // check in Onboarding or not + let loginButton = app.buttons["Log In"].firstMatch + try await Task.sleep(nanoseconds: .second * 3) + let loginButtonExists = loginButton.exists + + // goto Onboarding scene if already sign-in + if !loginButtonExists { + try await showTitleButtonMenu(app: app) + + let showMenu = app.collectionViews.buttons["Show…"].firstMatch + XCTAssert(showMenu.waitForExistence(timeout: 3)) + showMenu.tap() + try await Task.sleep(nanoseconds: .second * 1) + + let welcomeAction = app.collectionViews.buttons["Welcome"].firstMatch + XCTAssert(welcomeAction.waitForExistence(timeout: 3)) + welcomeAction.tap() + try await Task.sleep(nanoseconds: .second * 1) + } + + func type(domain: String) async throws { + // type domain + let domainTextField = app.textFields.firstMatch + XCTAssert(domainTextField.waitForExistence(timeout: 5)) + domainTextField.tap() + + // Skip system keyboard swipe input guide + try await skipKeyboardSwipeInputGuide(app: app) + domainTextField.typeText(domain) + XCUIApplication().keyboards.buttons["Done"].firstMatch.tap() + } + + switch page { + case .welcome: + break + case .login(let domain): + // Tap login button + XCTAssert(loginButtonExists) + loginButton.tap() + // type domain + try await type(domain: domain) + // add system alert monitor + // A. The monitor not works + // addUIInterruptionMonitor(withDescription: "Authentication Alert") { alert in + // alert.buttons["Continue"].firstMatch.tap() + // return true + // } + // tap next + try await selectServerAndContinue(app: app, domain: domain) + // wait authentication alert display + try await Task.sleep(nanoseconds: .second * 3) + // B. Workaround + let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard") + let continueButton = springboard.buttons["Continue"].firstMatch + XCTAssert(continueButton.waitForExistence(timeout: 3)) + continueButton.tap() + case .serverRules(let domain): + // Tap sign up button + let signUpButton = app.buttons["Get Started"].firstMatch + XCTAssert(signUpButton.waitForExistence(timeout: 3)) + signUpButton.tap() + // type domain + try await type(domain: domain) + // tap next + try await selectServerAndContinue(app: app, domain: domain) + } + } + + private func selectServerAndContinue(app: XCUIApplication, domain: String) async throws { + // wait searching + try await Task.sleep(nanoseconds: .second * 3) + + // tap server + let cell = app.cells.containing(.staticText, identifier: domain).firstMatch + XCTAssert(cell.waitForExistence(timeout: 5)) + cell.tap() + + // tap next button + let nextButton = app.buttons.matching(NSPredicate(format: "enabled == true")).matching(identifier: "Next").firstMatch + XCTAssert(nextButton.waitForExistence(timeout: 3)) + nextButton.tap() + } + + private func skipKeyboardSwipeInputGuide(app: XCUIApplication) async throws { + let swipeInputLabel = app.staticTexts["Speed up your typing by sliding your finger across the letters to compose a word."].firstMatch + try await Task.sleep(nanoseconds: .second * 3) + guard swipeInputLabel.exists else { return } + let continueButton = app.buttons["Continue"] + continueButton.tap() + } + +} diff --git a/NotificationService/Info.plist b/NotificationService/Info.plist index 80653438..215b572b 100644 --- a/NotificationService/Info.plist +++ b/NotificationService/Info.plist @@ -19,7 +19,7 @@ <key>CFBundleShortVersionString</key> <string>1.3.0</string> <key>CFBundleVersion</key> - <string>96</string> + <string>109</string> <key>NSExtension</key> <dict> <key>NSExtensionPointIdentifier</key> diff --git a/Podfile b/Podfile index 3d4bcb82..ad7715ab 100644 --- a/Podfile +++ b/Podfile @@ -16,7 +16,7 @@ target 'Mastodon' do pod 'Sourcery', '~> 1.6.1' # DEBUG - pod 'FLEX', '~> 4.4.0', :configurations => ['Debug'] + pod 'FLEX', '~> 4.4.0', :configurations => ['Debug', "Release Snapshot"] target 'MastodonTests' do inherit! :search_paths diff --git a/Podfile.lock b/Podfile.lock index 0593a8e2..f8dde693 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -40,6 +40,6 @@ SPEC CHECKSUMS: SwiftGen: 67860cc7c3cfc2ed25b9b74cfd55495fc89f9108 "UITextField+Shake": 298ac5a0f239d731bdab999b19b628c956ca0ac3 -PODFILE CHECKSUM: 1426a4b78d8d711a5ae7600b9deea8986ddfdf7d +PODFILE CHECKSUM: c471d1f9c923dc63bf8684415c79b85adb2ac36b -COCOAPODS: 1.11.2 +COCOAPODS: 1.11.3 diff --git a/README.md b/README.md index 4e785f29..bf35b459 100644 --- a/README.md +++ b/README.md @@ -4,85 +4,20 @@ <a href="https://apps.apple.com/us/app/mastodon-for-iphone/id1571998974?itsct=apps_box_badge&itscg=30200" style="display: inline-block; overflow: hidden; border-top-left-radius: 13px; border-top-right-radius: 13px; border-bottom-right-radius: 13px; border-bottom-left-radius: 13px; width: 250px; height: 83px;"><img src="https://tools.applemediaservices.com/api/badges/download-on-the-app-store/black/en-us?size=250x83&releaseDate=1627603200&h=72b0c8495c2c0af1291efef280c4c2c1" alt="Download on the App Store" style="border-top-left-radius: 13px; border-top-right-radius: 13px; border-bottom-right-radius: 13px; border-bottom-left-radius: 13px; width: 250px; height: 83px;"></a> -## Requirements +## Introduction -- Xcode 12.5+ -- Swift 5.3+ -- iOS 14.0+ +This is the repository for the official iOS App for Mastodon. You can install it from the App Store now. You can build the app from source and file bug report here. -## Setup -We need the latest version of Xcode from App Store. And use Cocoapods for dependency management. +Read this blog post for this app to learn more. +> [Developing an official iOS app for Mastodon](https://blog.joinmastodon.org/2021/02/developing-an-official-ios-app-for-mastodon/) -### CocoaPods +## Getting Start +- Read the setup guide [here](./Documentation/Setup.md) +- About [contributing](./Documentation/CONTRIBUTING.md) +- [Documentation folder](./Documentation/) -#### For the Intel Mac - -```zsh -sudo gem install cocoapods -sudo gem install cocoapods-keys -pod install -``` - -#### For the M1 Mac - -```zsh -sudo gem install cocoapods -sudo gem install cocoapods-keys - -# pod install may not works on M1 Mac. Fix by install ffi -# ref: https://github.com/CocoaPods/CocoaPods/issues/10220 -sudo arch -x86_64 gem install ffi - -arch -x86_64 pod install -``` - -## Start - -1. Open `Mastodon.xcworkspace` -2. Wait the Swift Package Dependencies resolved. -2. Check the signing settings make sure choose a team. [More info…](https://help.apple.com/xcode/mac/current/#/dev23aab79b4) -3. Select `Mastodon` scheme and run it. - -#### Contributors -The app require the `App Group` capability. To make sure it works for your developer membership. Please check [AppName.swift](AppShared/AppName.swift) file and set another unique `groupID` and update `App Group` settings. - -The app is compatible with [toot-relay](https://github.com/DagAgren/toot-relay) APNs. You can set your push notification endpoint via cocoapod-keys. - - -## Acknowledgements - -- [AlamofireImage](https://github.com/Alamofire/AlamofireImage) -- [AlamofireNetworkActivityIndicator](https://github.com/Alamofire/AlamofireNetworkActivityIndicator) -- [Alamofire](https://github.com/Alamofire/Alamofire) -- [CommonOSLog](https://github.com/mainasuk/CommonOSLog) -- [CryptoSwift](https://github.com/krzyzanowskim/CryptoSwift) -- [DateToolSwift](https://github.com/MatthewYork/DateTools) -- [DiffableDataSources](https://github.com/ra1028/DiffableDataSources) -- [DifferenceKit](https://github.com/ra1028/DifferenceKit) -- [FLAnimatedImage](https://github.com/Flipboard/FLAnimatedImage) -- [FLEX](https://github.com/FLEXTool/FLEX) -- [FPSIndicator](https://github.com/MainasuK/FPSIndicator) -- [Fuzi](https://github.com/cezheng/Fuzi) -- [Kanna](https://github.com/tid-kijyun/Kanna) -- [KeychainAccess](https://github.com/kishikawakatsumi/KeychainAccess.git) -- [Kingfisher](https://github.com/onevcat/Kingfisher) -- [MetaTextKit](https://github.com/TwidereProject/MetaTextKit) -- [Nuke-FLAnimatedImage-Plugin](https://github.com/kean/Nuke-FLAnimatedImage-Plugin) -- [Nuke](https://github.com/kean/Nuke) -- [Pageboy](https://github.com/uias/Pageboy#the-basics) -- [PanModal](https://github.com/slackhq/PanModal.git) -- [SDWebImage](https://github.com/SDWebImage/SDWebImage) -- [swift-collections](https://github.com/apple/swift-collections) -- [swift-nio](https://github.com/apple/swift-nio) -- [SwiftGen](https://github.com/SwiftGen/SwiftGen) -- [SwiftUI-Introspect](https://github.com/siteline/SwiftUI-Introspect) -- [SwiftyJSON](https://github.com/SwiftyJSON/SwiftyJSON) -- [Tabman](https://github.com/uias/Tabman) -- [TwidereX-iOS](https://github.com/TwidereProject/TwidereX-iOS) -- [ThirdPartyMailer](https://github.com/vtourraine/ThirdPartyMailer) -- [TOCropViewController](https://github.com/TimOliver/TOCropViewController) -- [TwitterProfile](https://github.com/OfTheWolf/TwitterProfile) -- [UITextView-Placeholder](https://github.com/devxoul/UITextView-Placeholder) +## Acknowledgments +Thanks to these open-sources projects listed [here](./Documentation/Acknowledgments.md). ## License diff --git a/ShareActionExtension/Info.plist b/ShareActionExtension/Info.plist index 41f25630..82ba5658 100644 --- a/ShareActionExtension/Info.plist +++ b/ShareActionExtension/Info.plist @@ -19,13 +19,15 @@ <key>CFBundleShortVersionString</key> <string>1.3.0</string> <key>CFBundleVersion</key> - <string>96</string> + <string>109</string> <key>NSExtension</key> <dict> <key>NSExtensionAttributes</key> <dict> <key>NSExtensionActivationRule</key> <dict> + <key>NSExtensionActivationSupportsText</key> + <true/> <key>NSExtensionActivationSupportsWebURLWithMaxCount</key> <integer>1</integer> <key>NSExtensionActivationSupportsImageWithMaxCount</key> diff --git a/ShareActionExtension/Scene/ShareViewModel.swift b/ShareActionExtension/Scene/ShareViewModel.swift index fe54e7e5..fbad8220 100644 --- a/ShareActionExtension/Scene/ShareViewModel.swift +++ b/ShareActionExtension/Scene/ShareViewModel.swift @@ -262,6 +262,10 @@ extension ShareViewModel { itemProviders.append(contentsOf: item.attachments ?? []) } + let _textProvider = itemProviders.first { provider in + return provider.hasRepresentationConforming(toTypeIdentifier: UTType.plainText.identifier, fileOptions: []) + } + let _urlProvider = itemProviders.first { provider in return provider.hasRepresentationConforming(toTypeIdentifier: UTType.url.identifier, fileOptions: []) } @@ -274,25 +278,51 @@ extension ShareViewModel { return provider.hasRepresentationConforming(toTypeIdentifier: UTType.image.identifier, fileOptions: []) } - if let urlProvider = _urlProvider { - urlProvider.loadItem(forTypeIdentifier: UTType.url.identifier) { [weak self] item, error in - guard let self = self else { return } - guard let url = item as? URL else { return } - DispatchQueue.main.async { - self.composeViewModel.statusContent = "\(url.absoluteString) " - } - } - } else if let movieProvider = _movieProvider { + Task { @MainActor in + async let text = ShareViewModel.loadText(textProvider: _textProvider) + async let url = ShareViewModel.loadURL(textProvider: _urlProvider) + + let content = await [text, url] + .compactMap { $0 } + .joined(separator: " ") + self.composeViewModel.statusContent = content + } + + if let movieProvider = _movieProvider { composeViewModel.setupAttachmentViewModels([ StatusAttachmentViewModel(itemProvider: movieProvider) ]) - } else { + } else if !imageProviders.isEmpty { let viewModels = imageProviders.map { provider in StatusAttachmentViewModel(itemProvider: provider) } composeViewModel.setupAttachmentViewModels(viewModels) } + } + + private static func loadText(textProvider: NSItemProvider?) async -> String? { + guard let textProvider = textProvider else { return nil } + do { + let item = try await textProvider.loadItem(forTypeIdentifier: UTType.plainText.identifier) + guard let text = item as? String else { return nil } + return text + } catch { + return nil + } + } + + private static func loadURL(textProvider: NSItemProvider?) async -> String? { + guard let textProvider = textProvider else { return nil } + do { + let item = try await textProvider.loadItem(forTypeIdentifier: UTType.url.identifier) + guard let url = item as? URL else { return nil } + return url.absoluteString + } catch { + return nil + } + } + } extension ShareViewModel { diff --git a/ShareActionExtension/Scene/View/StatusEditorView.swift b/ShareActionExtension/Scene/View/StatusEditorView.swift index c945874e..595057fa 100644 --- a/ShareActionExtension/Scene/View/StatusEditorView.swift +++ b/ShareActionExtension/Scene/View/StatusEditorView.swift @@ -81,7 +81,10 @@ public struct StatusEditorView: UIViewRepresentable { } public func textViewDidChange(_ textView: UITextView) { - parent.string = textView.text + // prevent break IME input + if textView.markedTextRange == nil { + parent.string = textView.text + } } func updateLayout(width: CGFloat) {