Compare commits

...

31 Commits

Author SHA1 Message Date
Arkadiusz Fal
a65db8555b Bump build number to 139 2023-03-12 22:56:23 +01:00
Arkadiusz Fal
afc1a25c26 Update changelog 2023-03-12 22:56:23 +01:00
Arkadiusz Fal
4851db4879 Fix loading channels data in Favorites 2023-03-12 22:52:54 +01:00
Arkadiusz Fal
912e1d1a23 Add Japanese localization 2023-03-12 22:46:36 +01:00
maboroshin
acc880fd47 Translated using Weblate (Japanese)
Currently translated at 97.6% (462 of 473 strings)

Translation: Yattee/Localizable.strings
Translate-URL: https://hosted.weblate.org/projects/yattee/localizable-strings/ja/
2023-03-12 22:45:10 +01:00
maboroshin
30e587ea97 Added translation using Weblate (Japanese) 2023-03-12 22:45:10 +01:00
mere
d723b2d6f1 Translated using Weblate (Romanian)
Currently translated at 100.0% (473 of 473 strings)

Translation: Yattee/Localizable.strings
Translate-URL: https://hosted.weblate.org/projects/yattee/localizable-strings/ro/
2023-03-12 22:45:10 +01:00
joaooliva
f7c0f8dd34 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (473 of 473 strings)

Translation: Yattee/Localizable.strings
Translate-URL: https://hosted.weblate.org/projects/yattee/localizable-strings/pt_BR/
2023-03-12 22:45:10 +01:00
mere
5f53515bdd Translated using Weblate (Romanian)
Currently translated at 98.3% (465 of 473 strings)

Translation: Yattee/Localizable.strings
Translate-URL: https://hosted.weblate.org/projects/yattee/localizable-strings/ro/
2023-03-12 22:45:10 +01:00
Bharathi
ad4920e0f2 Translated using Weblate (German)
Currently translated at 100.0% (473 of 473 strings)

Translation: Yattee/Localizable.strings
Translate-URL: https://hosted.weblate.org/projects/yattee/localizable-strings/de/
2023-03-12 22:45:10 +01:00
Arkadiusz Fal
e467b21c9d Translated using Weblate (Polish)
Currently translated at 100.0% (473 of 473 strings)

Translation: Yattee/Localizable.strings
Translate-URL: https://hosted.weblate.org/projects/yattee/localizable-strings/pl/
2023-03-01 23:39:45 +01:00
Anonymous
f94a00a7bb Translated using Weblate (English)
Currently translated at 100.0% (473 of 473 strings)

Translation: Yattee/Localizable.strings
Translate-URL: https://hosted.weblate.org/projects/yattee/localizable-strings/en/
2023-03-01 23:39:45 +01:00
Arkadiusz Fal
f7b35925b4 Change syntax to overcome compiler issue 2023-02-28 22:13:52 +01:00
Arkadiusz Fal
5bac92fdbf Bump build number to 138 2023-02-28 21:31:58 +01:00
Arkadiusz Fal
bf2c9a9e43 Update changelog 2023-02-28 21:31:26 +01:00
Arkadiusz Fal
f8d79bb08c Add browsing setting for unwatched feed
Fix #383
2023-02-28 21:27:47 +01:00
Arkadiusz Fal
b9ad5bc633 Hide share button when it should not be available 2023-02-28 21:04:42 +01:00
Arkadiusz Fal
f1e132a909 Add channel tabs and pagination
Fix #135
2023-02-28 21:04:42 +01:00
Arkadiusz Fal
d58026bcef Fix favorite channel button on tvOS 2023-02-26 19:14:06 +01:00
Anonymous
4697aa9696 Translated using Weblate (Swedish)
Currently translated at 24.1% (105 of 435 strings)

Translation: Yattee/Localizable.strings
Translate-URL: https://hosted.weblate.org/projects/yattee/localizable-strings/sv/
2023-02-26 18:55:38 +01:00
Anonymous
dbf3537f22 Translated using Weblate (Arabic)
Currently translated at 97.4% (424 of 435 strings)

Translation: Yattee/Localizable.strings
Translate-URL: https://hosted.weblate.org/projects/yattee/localizable-strings/ar/
2023-02-26 18:55:38 +01:00
Anonymous
474e280faa Translated using Weblate (Czech)
Currently translated at 98.8% (430 of 435 strings)

Translation: Yattee/Localizable.strings
Translate-URL: https://hosted.weblate.org/projects/yattee/localizable-strings/cs/
2023-02-26 18:55:38 +01:00
Anonymous
04fe18ac4c Translated using Weblate (Spanish)
Currently translated at 26.2% (114 of 435 strings)

Translation: Yattee/Localizable.strings
Translate-URL: https://hosted.weblate.org/projects/yattee/localizable-strings/es/
2023-02-26 18:55:38 +01:00
Anonymous
66665db344 Translated using Weblate (Turkish)
Currently translated at 52.8% (230 of 435 strings)

Translation: Yattee/Localizable.strings
Translate-URL: https://hosted.weblate.org/projects/yattee/localizable-strings/tr/
2023-02-26 18:55:38 +01:00
Arkadiusz Fal
38612eae52 Translated using Weblate (Norwegian Bokmål)
Currently translated at 69.1% (301 of 435 strings)

Translation: Yattee/Localizable.strings
Translate-URL: https://hosted.weblate.org/projects/yattee/localizable-strings/nb_NO/
2023-02-26 18:55:38 +01:00
Anonymous
80c1f63e35 Translated using Weblate (Norwegian Bokmål)
Currently translated at 69.1% (301 of 435 strings)

Translation: Yattee/Localizable.strings
Translate-URL: https://hosted.weblate.org/projects/yattee/localizable-strings/nb_NO/
2023-02-26 18:55:38 +01:00
Arkadiusz Fal
f4fb31e9e2 Translated using Weblate (Hindi)
Currently translated at 78.1% (340 of 435 strings)

Translation: Yattee/Localizable.strings
Translate-URL: https://hosted.weblate.org/projects/yattee/localizable-strings/hi/
2023-02-26 18:55:38 +01:00
Anonymous
44ff68b3c1 Translated using Weblate (Hindi)
Currently translated at 78.1% (340 of 435 strings)

Translation: Yattee/Localizable.strings
Translate-URL: https://hosted.weblate.org/projects/yattee/localizable-strings/hi/
2023-02-26 18:55:38 +01:00
Anonymous
737f762bfb Translated using Weblate (French)
Currently translated at 90.8% (395 of 435 strings)

Translation: Yattee/Localizable.strings
Translate-URL: https://hosted.weblate.org/projects/yattee/localizable-strings/fr/
2023-02-26 18:55:38 +01:00
Arkadiusz Fal
2844838485 Update workflows 2023-02-26 18:54:12 +01:00
Arkadiusz Fal
f39accdf7e Update workflows 2023-02-26 18:42:43 +01:00
39 changed files with 2320 additions and 162 deletions

34
.github/workflows/bump-build.yml vendored Normal file
View File

@@ -0,0 +1,34 @@
name: Bump build number
on:
workflow_dispatch:
env:
APP_NAME: Yattee
jobs:
bump_build:
name: Bump build number
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- name: Configure git
run: |
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.0'
bundler-cache: true
- uses: maierj/fastlane-action@v3.0.0
with:
lane: bump_build
- run: echo "BUILD_NUMBER=$(cat Yattee.xcodeproj/project.pbxproj | grep -m 1 CURRENT_PROJECT_VERSION | cut -d' ' -f3 | sed 's/;//g')" >> $GITHUB_ENV
- name: Create Pull Request
uses: peter-evans/create-pull-request@v4
with:
token: ${{ secrets.GIT_AUTHORIZATION }}
branch: actions/bump-build-to-${{ env.BUILD_NUMBER }}
base: main
title: Bump build number to ${{ env.BUILD_NUMBER }}

View File

@@ -20,29 +20,7 @@ env:
TESTFLIGHT_EXTERNAL_GROUPS: ${{ secrets.TESTFLIGHT_EXTERNAL_GROUPS }}
jobs:
bump_build:
name: Bump build number
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- name: Configure git
run: |
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.0'
bundler-cache: true
- uses: maierj/fastlane-action@v3.0.0
with:
lane: bump_build
- name: Push changes
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GIT_AUTHORIZATION }}
branch: ${{ github.ref }}
testflight:
needs: bump_build
strategy:
matrix:
lane: ['mac beta', 'ios beta', 'tvos beta']
@@ -50,8 +28,6 @@ jobs:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
with:
ref: main
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.0'
@@ -69,13 +45,10 @@ jobs:
path: fastlane/builds/**/*.ipa
if-no-files-found: ignore
mac_notarized:
needs: bump_build
name: Build and notarize macOS app
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
with:
ref: main
- uses: ruby/setup-ruby@v1
with:
ruby-version: '3.0'
@@ -101,21 +74,16 @@ jobs:
path: ${{ env.ZIP_PATH }}
if-no-files-found: error
release:
needs: ['bump_build', 'testflight', 'mac_notarized']
needs: ['testflight', 'mac_notarized']
name: Create GitHub release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
ref: main
- run: echo "BUILD_NUMBER=$(cat Yattee.xcodeproj/project.pbxproj | grep -m 1 CURRENT_PROJECT_VERSION | cut -d' ' -f3 | sed 's/;//g')" >> $GITHUB_ENV
- run: echo "VERSION_NUMBER=$(cat Yattee.xcodeproj/project.pbxproj | grep -m 1 MARKETING_VERSION | cut -d' ' -f3 | sed 's/;//g')" >> $GITHUB_ENV
- uses: actions/download-artifact@v3
with:
path: artifacts
- name: Display structure of downloaded files
run: ls -R
working-directory: artifacts
- uses: ncipollo/release-action@v1
with:
artifacts: artifacts/**/*.ipa,artifacts/**/*.zip

View File

@@ -1 +0,0 @@
137

View File

@@ -1,10 +1,12 @@
## Build 137
* Added filter to hide Short videos, available via view menu/toolbar button
* Added localizations: Arabic, Portugese, Portuguese (Brazil)
* Fixed reported crashes
* Other minor changes and improvements
## Build 139
* Fixed issue where channels in Favorites would not refresh contents
* Added Japanese localization
### Previous Builds
* Fixed issue with loading channels in Favorites with Invidious
* Added pagination/infinite scroll for channel contents (Invidious and Piped)
* Added support for channel tabs for Invidious (previously available only for Piped)
* Added filter to hide Short videos, available via view menu/toolbar button
* Added localizations: Arabic, Portugese, Portuguese (Brazil)
* Added browsing setting: "Show unwatched feed badges"
* Fixed reported crashes
* Other minor changes and improvements

View File

@@ -109,17 +109,22 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
content.json.arrayValue.map(self.extractChannel)
}
configureTransformer(pathPattern("channels/*"), requestMethods: [.get]) { (content: Entity<JSON>) -> Channel in
self.extractChannel(from: content.json)
configureTransformer(pathPattern("channels/*"), requestMethods: [.get]) { (content: Entity<JSON>) -> ChannelPage in
self.extractChannelPage(from: content.json, forceNotLast: true)
}
configureTransformer(pathPattern("channels/*/videos"), requestMethods: [.get]) { (content: Entity<JSON>) -> ChannelPage in
self.extractChannelPage(from: content.json)
}
configureTransformer(pathPattern("channels/*/latest"), requestMethods: [.get]) { (content: Entity<JSON>) -> [Video] in
content.json.dictionaryValue["videos"]?.arrayValue.map(self.extractVideo) ?? []
}
configureTransformer(pathPattern("channels/*/playlists"), requestMethods: [.get]) { (content: Entity<JSON>) -> [ContentItem] in
let playlists = (content.json.dictionaryValue["playlists"]?.arrayValue ?? []).compactMap { self.extractChannelPlaylist(from: $0) }
return ContentItem.array(of: playlists)
["latest", "playlists", "streams", "shorts", "channels", "videos"].forEach { type in
configureTransformer(pathPattern("channels/*/\(type)"), requestMethods: [.get]) { (content: Entity<JSON>) -> ChannelPage in
self.extractChannelPage(from: content.json)
}
}
configureTransformer(pathPattern("playlists/*"), requestMethods: [.get]) { (content: Entity<JSON>) -> ChannelPlaylist in
@@ -266,11 +271,18 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
.onCompletion { _ in onCompletion() }
}
func channel(_ id: String, contentType: Channel.ContentType, data _: String?) -> Resource {
if contentType == .playlists {
return resource(baseURL: account.url, path: basePathAppending("channels/\(id)/playlists"))
func channel(_ id: String, contentType: Channel.ContentType, data _: String?, page: String?) -> Resource {
if page.isNil, contentType == .videos {
return resource(baseURL: account.url, path: basePathAppending("channels/\(id)"))
}
return resource(baseURL: account.url, path: basePathAppending("channels/\(id)"))
var resource = resource(baseURL: account.url, path: basePathAppending("channels/\(id)/\(contentType.invidiousID)"))
if let page, !page.isEmpty {
resource = resource.withParam("continuation", page)
}
return resource
}
func channelByName(_: String) -> Resource? {
@@ -504,6 +516,14 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
thumbnailURL = "\(accountUrlComponents.scheme ?? "https"):\(thumbnailURL)"
}
let tabs = json["tabs"].arrayValue.compactMap { name in
if let name = name.string, let type = Channel.ContentType.from(name) {
return Channel.Tab(contentType: type, data: "")
}
return nil
}
return Channel(
app: .invidious,
id: json["authorId"].stringValue,
@@ -514,7 +534,8 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
subscriptionsCount: json["subCount"].int,
subscriptionsText: json["subCountText"].string,
totalViews: json["totalViews"].int,
videos: json.dictionaryValue["latestVideos"]?.arrayValue.map(extractVideo) ?? []
videos: json.dictionaryValue["latestVideos"]?.arrayValue.map(extractVideo) ?? [],
tabs: tabs
)
}
@@ -552,6 +573,33 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
}
}
private static var contentItemsKeys = ["items", "videos", "latestVideos", "playlists", "relatedChannels"]
private func extractChannelPage(from json: JSON, forceNotLast: Bool = false) -> ChannelPage {
let nextPage = json.dictionaryValue["continuation"]?.string
var contentItems = [ContentItem]()
var items = [ContentItem]()
if let key = Self.contentItemsKeys.first(where: { json.dictionaryValue.keys.contains($0) }),
let items = json.dictionaryValue[key]
{
contentItems = extractContentItems(from: items)
}
var last = false
if !forceNotLast {
last = nextPage?.isEmpty ?? true
}
return ChannelPage(
results: contentItems,
channel: extractChannel(from: json),
nextPage: nextPage,
last: last
)
}
private func extractStreams(from json: JSON) -> [Stream] {
let hls = extractHLSStreams(from: json)
if json["liveNow"].boolValue {
@@ -668,4 +716,33 @@ final class InvidiousAPI: Service, ObservableObject, VideosAPI {
)
}
}
private func extractContentItems(from json: JSON) -> [ContentItem] {
json.arrayValue.compactMap { extractContentItem(from: $0) }
}
private func extractContentItem(from json: JSON) -> ContentItem? {
let type = json.dictionaryValue["type"]?.string
if type == "channel" {
return ContentItem(channel: extractChannel(from: json))
} else if type == "playlist" {
return ContentItem(playlist: extractChannelPlaylist(from: json))
} else if type == "video" {
return ContentItem(video: extractVideo(from: json))
}
return nil
}
}
extension Channel.ContentType {
var invidiousID: String {
switch self {
case .livestreams:
return "streams"
default:
return rawValue
}
}
}

View File

@@ -284,7 +284,7 @@ final class PeerTubeAPI: Service, ObservableObject, VideosAPI {
.onCompletion { _ in onCompletion() }
}
func channel(_ id: String, contentType: Channel.ContentType, data _: String?) -> Resource {
func channel(_ id: String, contentType: Channel.ContentType, data _: String?, page _: String?) -> Resource {
if contentType == .playlists {
return resource(baseURL: account.url, path: basePathAppending("channels/\(id)/playlists"))
}

View File

@@ -6,6 +6,7 @@ import SwiftyJSON
final class PipedAPI: Service, ObservableObject, VideosAPI {
static var disallowedVideoCodecs = ["av01"]
static var authorizedEndpoints = ["subscriptions", "subscribe", "unsubscribe", "user/playlists"]
static var contentItemsKeys = ["items", "content", "relatedStreams"]
@Published var account: Account!
@@ -40,8 +41,25 @@ final class PipedAPI: Service, ObservableObject, VideosAPI {
$0.headers["Authorization"] = self.account.token
}
configureTransformer(pathPattern("channel/*")) { (content: Entity<JSON>) -> Channel? in
self.extractChannel(from: content.json)
configureTransformer(pathPattern("channel/*")) { (content: Entity<JSON>) -> ChannelPage in
let nextPage = content.json.dictionaryValue["nextpage"]?.string
let channel = self.extractChannel(from: content.json)
return ChannelPage(
results: self.extractContentItems(from: self.contentItemsDictionary(from: content.json)),
channel: channel,
nextPage: nextPage,
last: nextPage.isNil
)
}
configureTransformer(pathPattern("/nextpage/channel/*")) { (content: Entity<JSON>) -> ChannelPage in
let nextPage = content.json.dictionaryValue["nextpage"]?.string
return ChannelPage(
results: self.extractContentItems(from: self.contentItemsDictionary(from: content.json)),
channel: self.extractChannel(from: content.json),
nextPage: nextPage,
last: nextPage.isNil
)
}
configureTransformer(pathPattern("channels/tabs*")) { (content: Entity<JSON>) -> [ContentItem] in
@@ -159,13 +177,23 @@ final class PipedAPI: Service, ObservableObject, VideosAPI {
resource(baseURL: account.url, path: "login")
}
func channel(_ id: String, contentType: Channel.ContentType, data: String?) -> Resource {
if contentType == .videos {
return resource(baseURL: account.url, path: "channel/\(id)")
func channel(_ id: String, contentType: Channel.ContentType, data: String?, page: String?) -> Resource {
let path = page.isNil ? "channel" : "nextpage/channel"
var channel: Siesta.Resource
if contentType == .videos || data.isNil {
channel = resource(baseURL: account.url, path: "\(path)/\(id)")
} else {
channel = resource(baseURL: account.url, path: "channels/tabs")
.withParam("data", data)
}
return resource(baseURL: account.url, path: "channels/tabs")
.withParam("data", data)
if let page, !page.isEmpty {
channel = channel.withParam("nextpage", page)
}
return channel
}
func channelByName(_ name: String) -> Resource? {
@@ -700,4 +728,14 @@ final class PipedAPI: Service, ObservableObject, VideosAPI {
return Chapter(title: title, image: image, start: start)
}
}
private func contentItemsDictionary(from content: JSON) -> JSON {
if let key = Self.contentItemsKeys.first(where: { content.dictionaryValue.keys.contains($0) }),
let items = content.dictionaryValue[key]
{
return items
}
return .null
}
}

View File

@@ -8,7 +8,7 @@ protocol VideosAPI {
static func withAnonymousAccountForInstanceURL(_ url: URL) -> Self
func channel(_ id: String, contentType: Channel.ContentType, data: String?) -> Resource
func channel(_ id: String, contentType: Channel.ContentType, data: String?, page: String?) -> Resource
func channelByName(_ name: String) -> Resource?
func channelByUsername(_ username: String) -> Resource?
func channelVideos(_ id: String) -> Resource
@@ -72,8 +72,8 @@ protocol VideosAPI {
}
extension VideosAPI {
func channel(_ id: String, contentType: Channel.ContentType, data: String? = nil) -> Resource {
channel(id, contentType: contentType, data: data)
func channel(_ id: String, contentType: Channel.ContentType, data: String? = nil, page: String? = nil) -> Resource {
channel(id, contentType: contentType, data: data, page: page)
}
func loadDetails(

View File

@@ -34,11 +34,11 @@ struct ChannelsCacheModel: CacheModel {
store(channel)
}
func retrieve(_ cacheKey: String) -> Channel? {
func retrieve(_ cacheKey: String) -> ChannelPage? {
logger.debug("retrieving cache for \(cacheKey)")
if let json = try? storage?.object(forKey: cacheKey) {
return Channel.from(json)
return ChannelPage(channel: Channel.from(json))
}
return nil

View File

@@ -110,12 +110,12 @@ final class SubscribedChannelsModel: ObservableObject, CacheModel {
if let json = try? storage?.object(forKey: channelsCacheKey(account)),
let channels = json.dictionaryValue["channels"]
{
return channels.arrayValue.map { json in
return channels.arrayValue.compactMap { json in
let channel = Channel.from(json)
if !channel.hasExtendedDetails,
let cache = ChannelsCacheModel.shared.retrieve(channel.cacheKey)
{
return cache
return cache.channel
}
return channel

View File

@@ -11,6 +11,15 @@ struct Channel: Identifiable, Hashable {
case shorts
case channels
static func from(_ name: String) -> Self? {
let rawValueMatch = allCases.first { $0.rawValue == name }
guard rawValueMatch.isNil else { return rawValueMatch! }
if name == "streams" { return .livestreams }
return nil
}
var id: String {
rawValue
}
@@ -53,6 +62,10 @@ struct Channel: Identifiable, Hashable {
return "person.3"
}
}
var alwaysAvailable: Bool {
self == .videos || self == .playlists
}
}
struct Tab: Identifiable, Hashable {
@@ -110,7 +123,6 @@ struct Channel: Identifiable, Hashable {
}
func hasData(for contentType: ContentType) -> Bool {
guard contentType != .videos, contentType != .playlists else { return true }
return tabs.contains { $0.contentType == contentType }
}
@@ -132,7 +144,7 @@ struct Channel: Identifiable, Hashable {
}
var thumbnailURLOrCached: URL? {
thumbnailURL ?? ChannelsCacheModel.shared.retrieve(cacheKey)?.thumbnailURL
thumbnailURL ?? ChannelsCacheModel.shared.retrieve(cacheKey)?.channel?.thumbnailURL
}
var json: JSON {

8
Model/ChannelPage.swift Normal file
View File

@@ -0,0 +1,8 @@
import Foundation
struct ChannelPage {
var results = [ContentItem]()
var channel: Channel?
var nextPage: String?
var last = false
}

View File

@@ -115,7 +115,7 @@ final class FeedModel: ObservableObject, CacheModel {
}
func calculateUnwatchedFeed() {
guard let account = accounts.current, accounts.signedIn else { return }
guard let account = accounts.current, accounts.signedIn, Defaults[.showUnwatchedFeedBadges] else { return }
let feed = cacheModel.retrieveFeed(account: account)
backgroundContext.perform { [weak self] in
guard let self else { return }

View File

@@ -11,11 +11,12 @@ struct ChannelVideosView: View {
@State private var shareURL: URL?
@State private var subscriptionToggleButtonDisabled = false
@State private var page: ChannelPage?
@State private var contentType = Channel.ContentType.videos
@StateObject private var contentTypeItems = Store<[ContentItem]>()
@State private var descriptionExpanded = false
@StateObject private var store = Store<Channel>()
@StateObject private var store = Store<ChannelPage>()
@Environment(\.colorScheme) private var colorScheme
@@ -35,14 +36,10 @@ struct ChannelVideosView: View {
@Default(.hideShorts) private var hideShorts
var presentedChannel: Channel? {
store.item ?? channel ?? recents.presentedChannel
store.item?.channel ?? channel ?? recents.presentedChannel
}
var contentItems: [ContentItem] {
guard contentType != .videos else {
return ContentItem.array(of: presentedChannel?.videos ?? [])
}
return contentTypeItems.collection
}
@@ -63,6 +60,8 @@ struct ChannelVideosView: View {
viewsLabel
subscriptionToggleButton
favoriteButton
.labelStyle(.iconOnly)
}
contentTypePicker
.pickerStyle(.automatic)
@@ -99,6 +98,7 @@ struct ChannelVideosView: View {
banner
}
}
.environment(\.loadMoreContentHandler) { loadNextPage() }
.environment(\.inChannelView, true)
.environment(\.listingStyle, channelPlaylistListingStyle)
.environment(\.hideShorts, hideShorts)
@@ -159,9 +159,7 @@ struct ChannelVideosView: View {
}
ToolbarItem {
if let presentedChannel {
FavoriteButton(item: FavoriteItem(section: .channel(accounts.app.appType.rawValue, presentedChannel.id, presentedChannel.name)))
}
favoriteButton
}
ToolbarItem {
@@ -180,14 +178,10 @@ struct ChannelVideosView: View {
store.replace(cache)
}
resource?.loadIfNeeded()?.onSuccess { response in
if let channel: Channel = response.typedContent() {
ChannelsCacheModel.shared.store(channel)
}
}
load()
}
.onChange(of: contentType) { _ in
resource?.load()
load()
}
#if os(iOS)
.navigationBarTitleDisplayMode(.inline)
@@ -211,8 +205,14 @@ struct ChannelVideosView: View {
}
}
@ViewBuilder var favoriteButton: some View {
if let presentedChannel {
FavoriteButton(item: FavoriteItem(section: .channel(accounts.app.appType.rawValue, presentedChannel.id, presentedChannel.name)))
}
}
var thumbnail: some View {
ChannelAvatarView(channel: store.item)
ChannelAvatarView(channel: store.item?.channel)
#if os(tvOS)
.frame(width: 80, height: 80, alignment: .trailing)
#else
@@ -232,7 +232,7 @@ struct ChannelVideosView: View {
var subscriptionsLabel: some View {
Group {
if let subscribers = store.item?.subscriptionsString {
if let subscribers = store.item?.channel?.subscriptionsString {
HStack(spacing: 0) {
Text(subscribers)
Image(systemName: "person.2.fill")
@@ -251,7 +251,7 @@ struct ChannelVideosView: View {
var viewsLabel: some View {
HStack(spacing: 0) {
if let views = store.item?.totalViewsString {
if let views = store.item?.channel?.totalViewsString {
Text(views)
Image(systemName: "eye.fill")
@@ -322,7 +322,7 @@ struct ChannelVideosView: View {
Picker("Content type", selection: $contentType) {
if let channel = presentedChannel {
ForEach(Channel.ContentType.allCases, id: \.self) { type in
if channel.hasData(for: type) {
if typeAvailable(type) {
Label(type.description, systemImage: type.systemImage).tag(type)
}
}
@@ -330,16 +330,20 @@ struct ChannelVideosView: View {
}
}
private func typeAvailable(_ type: Channel.ContentType) -> Bool {
type.alwaysAvailable || (presentedChannel?.hasData(for: type) ?? false)
}
private var resource: Resource? {
guard let channel = presentedChannel else { return nil }
let data = contentType != .videos ? channel.tabs.first(where: { $0.contentType == contentType })?.data : nil
let resource = accounts.api.channel(channel.id, contentType: contentType, data: data)
if contentType == .videos {
resource.addObserver(store)
} else {
resource.addObserver(contentTypeItems)
}
resource.addObserver(contentTypeItems)
return resource
}
@@ -418,6 +422,42 @@ struct ChannelVideosView: View {
Label("Mark channel feed as unwatched", systemImage: "checkmark.circle")
}
}
func load() {
resource?.load().onSuccess { response in
if let page: ChannelPage = response.typedContent() {
if let channel = page.channel {
ChannelsCacheModel.shared.store(channel)
}
self.page = page
self.contentTypeItems.replace(page.results)
}
}
.onFailure { error in
navigation.presentAlert(title: "Could not load channel data", message: error.userMessage)
}
}
func loadNextPage() {
guard let channel = presentedChannel, let pageToLoad = page, !pageToLoad.last else {
return
}
var next = pageToLoad.nextPage
if contentType == .videos, !pageToLoad.last {
next = next ?? ""
}
let data = contentType != .videos ? channel.tabs.first(where: { $0.contentType == contentType })?.data : nil
accounts.api.channel(channel.id, contentType: contentType, data: data, page: next).load().onSuccess { response in
if let page: ChannelPage = response.typedContent() {
self.page = page
let keys = self.contentTypeItems.collection.map(\.cacheKey)
let items = self.contentTypeItems.collection + page.results.filter { !keys.contains($0.cacheKey) }
self.contentTypeItems.replace(items)
}
}
}
}
struct ChannelVideosView_Previews: PreviewProvider {

View File

@@ -51,6 +51,7 @@ extension Defaults.Keys {
#if os(iOS)
static let lockPortraitWhenBrowsing = Key<Bool>("lockPortraitWhenBrowsing", default: UIDevice.current.userInterfaceIdiom == .phone)
#endif
static let showUnwatchedFeedBadges = Key<Bool>("showUnwatchedFeedBadges", default: false)
static let expandChannelDescription = Key<Bool>("expandChannelDescription", default: false)
static let channelOnThumbnail = Key<Bool>("channelOnThumbnail", default: false)
static let timeOnThumbnail = Key<Bool>("timeOnThumbnail", default: true)

View File

@@ -74,9 +74,10 @@ struct FavoriteItemView: View {
case let .channel(_, id, name):
var channel = Channel(app: .invidious, id: id, name: name)
if let cache = ChannelsCacheModel.shared.retrieve(channel.cacheKey),
!cache.videos.isEmpty
let cacheChannel = cache.channel,
!cacheChannel.videos.isEmpty
{
contentItems = ContentItem.array(of: cache.videos)
contentItems = ContentItem.array(of: cacheChannel.videos)
}
onSuccess = { response in
@@ -87,6 +88,12 @@ struct FavoriteItemView: View {
channel.videos = videos
ChannelsCacheModel.shared.store(channel)
store.contentItems = ContentItem.array(of: videos)
} else if let channelPage: ChannelPage = response.typedContent() {
if let channel = channelPage.channel {
ChannelsCacheModel.shared.store(channel)
}
store.contentItems = channelPage.results
}
}
case let .channelPlaylist(_, id, title):

View File

@@ -8,6 +8,8 @@ struct AppSidebarSubscriptions: View {
@ObservedObject private var subscriptions = SubscribedChannelsModel.shared
@ObservedObject private var accounts = AccountsModel.shared
@Default(.showUnwatchedFeedBadges) private var showUnwatchedFeedBadges
var body: some View {
Section(header: Text("Subscriptions")) {
ForEach(subscriptions.all) { channel in
@@ -26,7 +28,7 @@ struct AppSidebarSubscriptions: View {
Spacer()
}
.backport
.badge(feedCount.unwatchedByChannelText(channel))
.badge(showUnwatchedFeedBadges ? feedCount.unwatchedByChannelText(channel) : nil)
}
.contextMenu {
if subscriptions.isSubscribing(channel.id) {

View File

@@ -13,6 +13,7 @@ struct AppTabNavigation: View {
@Default(.showDocuments) private var showDocuments
@Default(.showOpenActionsToolbarItem) private var showOpenActionsToolbarItem
@Default(.visibleSections) private var visibleSections
@Default(.showUnwatchedFeedBadges) private var showUnwatchedFeedBadges
let persistenceController = PersistenceController.shared
@@ -95,7 +96,7 @@ struct AppTabNavigation: View {
}
.tag(TabSelection.subscriptions)
.backport
.badge(feedCount.unwatchedText)
.badge(showUnwatchedFeedBadges ? feedCount.unwatchedText : nil)
}
private var subscriptionsVisible: Bool {

View File

@@ -12,6 +12,7 @@ struct Sidebar: View {
#if os(iOS)
@Default(.showDocuments) private var showDocuments
#endif
@Default(.showUnwatchedFeedBadges) private var showUnwatchedFeedBadges
var body: some View {
ScrollViewReader { scrollView in
@@ -79,7 +80,7 @@ struct Sidebar: View {
.accessibility(label: Text("Subscriptions"))
}
.backport
.badge(feedCount.unwatchedText)
.badge(showUnwatchedFeedBadges ? feedCount.unwatchedText : nil)
.contextMenu {
playUnwatchedButton
toggleWatchedButton

View File

@@ -7,6 +7,7 @@ struct BrowsingSettings: View {
@Default(.roundedThumbnails) private var roundedThumbnails
#endif
@Default(.accountPickerDisplaysAnonymousAccounts) private var accountPickerDisplaysAnonymousAccounts
@Default(.showUnwatchedFeedBadges) private var showUnwatchedFeedBadges
#if os(iOS)
@Default(.homeRecentDocumentsItems) private var homeRecentDocumentsItems
@Default(.lockPortraitWhenBrowsing) private var lockPortraitWhenBrowsing
@@ -223,6 +224,12 @@ struct BrowsingSettings: View {
#endif
Toggle("Show anonymous accounts", isOn: $accountPickerDisplaysAnonymousAccounts)
Toggle("Show unwatched feed badges", isOn: $showUnwatchedFeedBadges)
.onChange(of: showUnwatchedFeedBadges) { newValue in
if newValue {
FeedModel.shared.calculateUnwatchedFeed()
}
}
}
Toggle("Open channels with description expanded", isOn: $expandChannelDescription)

View File

@@ -243,7 +243,7 @@ struct SettingsView: View {
private var windowHeight: Double {
switch selection {
case .browsing:
return 820
return 840
case .player:
return 450
case .controls:

View File

@@ -9,6 +9,7 @@ struct ChannelsView: View {
@ObservedObject private var feedCount = UnwatchedFeedCountModel.shared
@Default(.showCacheStatus) private var showCacheStatus
@Default(.showUnwatchedFeedBadges) private var showUnwatchedFeedBadges
var body: some View {
List {
@@ -26,7 +27,7 @@ struct ChannelsView: View {
}
}
.backport
.badge(feedCount.unwatchedByChannelText(channel))
.badge(showUnwatchedFeedBadges ? feedCount.unwatchedByChannelText(channel) : nil)
}
.contextMenu {
if subscriptions.isSubscribing(channel.id) {

View File

@@ -21,27 +21,27 @@ struct ShareButton<LabelView: View>: View {
@ViewBuilder var body: some View {
// TODO: this should work with other content item types
Menu {
if let video = contentItem.video,
!video.localStreamIsFile
{
if video.localStreamIsRemoteURL {
remoteURLAction
} else {
instanceActions
Divider()
if !accounts.isEmpty {
youtubeActions
if let video = contentItem.video {
Menu {
if !video.localStreamIsFile {
if video.localStreamIsRemoteURL {
remoteURLAction
} else {
instanceActions
Divider()
if !accounts.isEmpty {
youtubeActions
}
}
}
} label: {
label
}
} label: {
label
.menuStyle(.borderlessButton)
#if os(macOS)
.frame(maxWidth: 60)
#endif
}
.menuStyle(.borderlessButton)
#if os(macOS)
.frame(maxWidth: 60)
#endif
}
private var instanceActions: some View {

View File

@@ -493,3 +493,12 @@
"Share%@link" = "مشاركة الرابط %@";
"Instance of current account" = "مثيل الحساب الحالي";
"Seek gesture sensitivity" = "إطار حساسية الإيماءات";
"Video" = "";
"Audio" = "";
"Honor orientation lock" = "";
"Proxy videos" = "";
"Seek gesture speed" = "";
"Seek with horizontal swipe on video" = "";
"System controls show buttons for %@" = "";
"Wiki" = "";
"Sample Rate" = "";

View File

@@ -498,3 +498,7 @@
"Default Profile" = "Výchozí profil";
"Copy%@link" = "Zkopírovat%@odkaz";
"Share%@link" = "Sdílet%@odkaz";
"Verified" = "";
"Shorts" = "";
"Channel" = "";
"Live Streams" = "";

View File

@@ -4,7 +4,7 @@
"Accounts" = "Konten";
"Add Account" = "Konto hinzufügen";
"Add Location" = "Ort hinzufügen";
"Add Location..." = "Ort hinzufügen...";
"Add Location..." = "Ort hinzufügen";
"Add to Playlist" = "Zur Wiedergabeliste hinzufügen";
"Backend" = "Backend";
"Badge color" = "Abzeichen Farbe";
@@ -73,11 +73,11 @@
"%@ subscribers" = "%@ Abonnenten";
" subscribers" = " Abonnenten";
"%@ Playlist" = "%@ Wiedergabeliste";
"Add Account..." = "Konto hinzufügen...";
"Add profile..." = "Profil hinzufügen...";
"Add Account..." = "Konto hinzufügen";
"Add profile..." = "Profil hinzufügen";
"Add to Favorites" = "Zu den Favoriten hinzufügen";
"Add Quality Profile" = "Qualitätsprofil hinzufügen";
"Add to Playlist..." = "Zur Wiedergabeliste hinzufügen...";
"Add to Playlist..." = "Zur Wiedergabeliste hinzufügen";
"Automatic" = "Automatisch";
"Clear Search History" = "Suchverlauf löschen";
"Continue" = "Fortsetzen";
@@ -111,7 +111,7 @@
/* Trending category, section containing all kinds of videos */
"All" = "Alle";
"Always use AVPlayer for live videos" = "Verwende immer AVPlayer für Live-Videos";
"Always use AVPlayer for live videos" = "Immer AVPlayer für Live-Videos nutzen";
"Anonymous" = "Anonym";
/* Video date filter in search
@@ -502,3 +502,41 @@
"Shorts" = "Shorts";
"Verified" = "Verifiziert";
"Channel" = "Kanal";
"Short videos: visible" = "Kurze Videos: sichtbar";
"Player Bar" = "Spielerleiste";
"Short videos: hidden" = "Kurze Videos: versteckt";
"Play all unwatched" = "Alle ungesehen abspielen";
"Double tap gesture" = "Doppeltippgeste";
"Clear all" = "Alles löschen";
"Hide player" = "Spieler ausblenden";
"Close video" = "Video schließen";
"Total size: %@" = "Gesamtgröße: %@";
"Show cache status" = "Cachestatus anzeigen";
"Maximum feed items" = "Maximale Feed-Elemente";
"Mark channel feed as watched" = "Kanal-Feed als angesehen markieren";
"Controls button: forwards" = "Steuertaste: vorwärts";
"Open expanded" = "Erweitert öffnen";
"Mark channel feed as unwatched" = "Kanal-Feed als ungesehen markieren";
"System controls" = "Systemsteuerung";
"Gesture: fowards" = "Geste: vorwärts";
"Controls Buttons" = "Steuerelemente Tasten";
"Controls button: backwards" = "Steuertaste: rückwärts";
"Tap and hold channel thumbnail to open context menu with more actions" = "Tippen und halten Sie die Kanal-Miniaturansicht, um das Kontextmenü mit weiteren Aktionen zu öffnen";
"Always show controls buttons" = "Steuerungsschaltflächen immer einblenden";
"Show unwatched feed badges" = "Ungeöffnete Feed-Badges anzeigen";
"Maximum width expanded" = "Maximalbreite erweitert";
"Right click channel thumbnail to open context menu with more actions" = "Klicken Sie mit der rechten Maustaste auf die Miniaturansicht des Kanals, um das Kontextmenü mit weiteren Aktionen zu öffnen";
"Gesture: backwards" = "Geste: rückwärts";
"Gesture settings control skipping interval for double tap gesture on left/right side of the player. Changing system controls settings requires restart." = "Gesteneinstellungen steuern das Überspringungsintervall für Doppeltippgesten auf der linken/rechten Seite des Players. Das Ändern der Einstellungen der Systemsteuerung erfordert einen Neustart.";
"Gesture settings control skipping interval for double click on left/right side of the player. Changing system controls settings requires restart." = "Gesteneinstellungen steuern das Überspringungsintervall für Doppelklicks auf der linken/rechten Seite des Players. Das Ändern der Einstellungen der Systemsteuerung erfordert einen Neustart.";
"Gesture settings control skipping interval for remote arrow buttons (for 2nd generation Siri Remote or newer). Changing system controls settings requires restart." = "Gesteneinstellungen steuern das Überspringungsintervall für die Pfeiltasten der Fernbedienung (für Siri Remote der 2. Generation oder neuer). Das Ändern der Einstellungen der Systemsteuerung erfordert einen Neustart.";
"Actions Buttons" = "Aktionen-Schaltflächen";
"Play next item" = "Nächstes Element abspielen";
"Lock orientation" = "Ausrichtung sperren";
"Music Mode" = "Musikmodus";
"Open channels with description expanded" = "Offene Kanäle mit erweiterter Beschreibung";
"Cache" = "Cache";
"Subscribe/Unsubscribe" = "Abonnieren/abbestellen";
"Are you sure you want to clear cache?" = "Möchten Sie den Cache wirklich löschen?";
"Single tap gesture" = "Einmalige Antippen-Geste";
"Seeking" = "Suchend";

View File

@@ -500,3 +500,41 @@
"Shorts" = "Shorts";
"Verified" = "Verified";
"Channel" = "Channel";
"Open expanded" = "Open expanded";
"Mark channel feed as unwatched" = "Mark channel feed as unwatched";
"Mark channel feed as watched" = "Mark channel feed as watched";
"Short videos: visible" = "Short videos: visible";
"Player Bar" = "Player Bar";
"Short videos: hidden" = "Short videos: hidden";
"Play all unwatched" = "Play all unwatched";
"Double tap gesture" = "Double tap gesture";
"Tap and hold channel thumbnail to open context menu with more actions" = "Tap and hold channel thumbnail to open context menu with more actions";
"Always show controls buttons" = "Always show controls buttons";
"Single tap gesture" = "Single tap gesture";
"Maximum width expanded" = "Maximum width expanded";
"Clear all" = "Clear all";
"Right click channel thumbnail to open context menu with more actions" = "Right click channel thumbnail to open context menu with more actions";
"Show unwatched feed badges" = "Show unwatched feed badges";
"Seeking" = "Seeking";
"Gesture: fowards" = "Gesture: fowards";
"Controls Buttons" = "Controls Buttons";
"System controls" = "System controls";
"Controls button: backwards" = "Controls button: backwards";
"Controls button: forwards" = "Controls button: forwards";
"Gesture: backwards" = "Gesture: backwards";
"Gesture settings control skipping interval for double tap gesture on left/right side of the player. Changing system controls settings requires restart." = "Gesture settings control skipping interval for double tap gesture on left/right side of the player. Changing system controls settings requires restart.";
"Hide player" = "Hide player";
"Gesture settings control skipping interval for double click on left/right side of the player. Changing system controls settings requires restart." = "Gesture settings control skipping interval for double click on left/right side of the player. Changing system controls settings requires restart.";
"Gesture settings control skipping interval for remote arrow buttons (for 2nd generation Siri Remote or newer). Changing system controls settings requires restart." = "Gesture settings control skipping interval for remote arrow buttons (for 2nd generation Siri Remote or newer). Changing system controls settings requires restart.";
"Actions Buttons" = "Actions Buttons";
"Play next item" = "Play next item";
"Lock orientation" = "Lock orientation";
"Music Mode" = "Music Mode";
"Close video" = "Close video";
"Total size: %@" = "Total size: %@";
"Open channels with description expanded" = "Open channels with description expanded";
"Cache" = "Cache";
"Subscribe/Unsubscribe" = "Subscribe/Unsubscribe";
"Show cache status" = "Show cache status";
"Maximum feed items" = "Maximum feed items";
"Are you sure you want to clear cache?" = "Are you sure you want to clear cache?";

View File

@@ -124,3 +124,381 @@
"Browsing" = "Navegando por";
"Buffering stream..." = "Cargando flujo de datos...";
"Cellular" = "Celular";
"Save" = "";
"Search history is empty" = "";
"Address" = "";
"Could not refresh Subscriptions" = "";
"You can use automatic profile selection based on current device status or switch it in video playback settings controls." = "";
"URL to Open" = "";
"Could not delete document" = "";
"Show Favorites" = "";
"Current Location" = "";
"Show Home" = "";
"Are you sure you want to remove this document?" = "";
/* Video date filter in search */
"Today" = "";
"Opening audio stream..." = "";
"Open Video" = "";
"I want to ask a question" = "";
"Save history of played videos" = "";
"Promoting a product or service that is directly related to the creator themselves. This usually includes merchandise or promotion of monetized platforms." = "";
"Show only icons" = "";
"FPS" = "";
"Enter links to open, one per line" = "";
"Sample Rate" = "";
"Playback Mode" = "";
"Channels" = "";
"For custom locations you can configure Frontend URL in Locations settings" = "";
"Cached time" = "";
"Could not find any links to open in your clipboard" = "";
"Orientation" = "";
/* SponsorBlock category name */
"Offtopic in Music Videos" = "";
"Public Manifest" = "";
"This will remove all your custom profiles and return their default values. This cannot be reverted." = "";
"Left" = "";
"Video Details" = "";
"Only for local files and URLs" = "";
"\"%@\" will be irreversibly removed from this device." = "";
/* Player controls layout size */
"Small" = "";
"Now Playing" = "";
"Stream & Player" = "";
"Picture in Picture" = "";
"Visibility" = "";
"Edit Favorites…" = "";
"Center" = "";
"Wiki" = "";
"Live Streams" = "";
"Make default" = "";
"Dropped frames" = "";
"Show icons and text when space permits" = "";
"Hardware decoder" = "";
"Show Open Videos quick actions" = "";
"Upload date" = "";
"Home" = "";
"Switch to public locations" = "";
"Verified" = "";
"History" = "";
"Locations Manifest" = "";
"Playlist is empty\n\nTap and hold on a video and then \n\"Add to Playlist\"" = "";
"Play Now" = "";
"Enter link to open" = "";
"Share..." = "";
"Restore default profiles..." = "";
"Round corners" = "";
"SponsorBlock" = "";
"Statistics" = "";
"Matrix Channel" = "";
"More info can be found in:" = "";
"Resolution" = "";
"Open Videos" = "";
"Show progress of watching on thumbnails" = "";
"Medium quality" = "";
"Welcome" = "";
"Could not open Files" = "";
"Add Channels, Playlists and Searches to Favorites using" = "";
"Restart" = "";
"Shorts" = "";
"Not available" = "";
"Pages buttons" = "";
"No documents" = "";
/* Loading stream OSD */
"Opening %@ stream..." = "";
"Documents" = "";
"Thumbnails" = "";
"Password" = "";
"Show playback statistics" = "";
"Remove Location" = "";
"Inspector visibility" = "";
"Open \"Playlists\" tab to create new one" = "";
"Show Inspector" = "";
/* Video date filter in search */
"Week" = "";
"Recent Documents" = "";
"Segments typically found at the start of a video that include an animation, still frame or clip which are also seen in other videos by the same creator." = "";
"Restart the app to apply the settings above." = "";
"Show sidebar when space permits" = "";
"Share %@ link with time" = "";
"Rate & Captions" = "";
/* SponsorBlock category name */
"Outro" = "";
"Always" = "";
"Show anonymous accounts" = "";
"Play in PiP" = "";
/* SponsorBlock category name */
"Sponsor" = "";
"Rate" = "";
"Reload manifest" = "";
"Playback queue is empty" = "";
"Videos" = "";
/* Selected video was played on given date */
"Watched %@" = "";
"You have no playlists\n\nTap on \"New Playlist\" to create one" = "";
"I like this app!" = "";
/* Video sort order in search */
"Rating" = "";
"Actions buttons" = "";
"Files" = "";
"Sign In Required" = "";
"Buttons labels" = "";
"Next" = "";
"Default Profile" = "";
"Paste" = "";
"Regular Size" = "";
"File" = "";
"Right" = "";
"Reset search filters" = "";
"Channel" = "";
"Open Files" = "";
"You can find information about using Yattee in the Wiki pages." = "";
"Lock portrait mode" = "";
"Shuffle" = "";
/* Loading stream OSD */
"Loading streams..." = "";
"Public Locations" = "";
"Yattee" = "";
"No results" = "";
"Driver" = "";
"Remove from history" = "";
"Red" = "";
"Are you sure you want to remove %@ location?" = "";
"Share" = "";
"Share %@ link" = "";
"Reset watched status when playing again" = "";
"Show sidebar" = "";
"You need to create an instance and accounts\nto access %@ section" = "";
"Refresh" = "";
"I am lost" = "";
/* Player controls layout size */
"Medium" = "";
"Typically near or at the end of the video when the credits pop up and/or endcards are shown." = "";
"This information will be processed only on your device and used to connect you to the server in the specified country." = "";
"Part of a video promoting a product or service not directly related to the creator. The creator will receive payment or compensation in the form of money or free products." = "";
"You have no Playlists" = "";
"System controls show buttons for %@" = "";
"No chapters information available" = "";
/* Video date filter in search */
"Month" = "";
"Shuffle All" = "";
"Large layout is not suitable for all devices and using it may cause controls not to fit on the screen." = "";
"Music" = "";
"Name" = "";
"New Playlist" = "";
"Quality Profile" = "";
"Queue" = "";
"You can switch between profiles in playback settings controls." = "";
"Could not load streams" = "";
"Settings" = "";
"Show history" = "";
"unknown" = "";
"%@ formats" = "";
"Quality" = "";
"Any format" = "";
"Honor orientation lock" = "";
"I found a bug /" = "";
"I have a feature request" = "";
"LIVE" = "";
/* Video duration filter in search */
"Long" = "";
"Low quality" = "";
"Lowest" = "";
"Movies" = "";
"MPV Documentation" = "";
"Pause when entering background" = "";
"Pause when player is closed" = "";
"Play" = "";
"Play All" = "";
"Preferred Formats" = "";
"Profiles" = "";
"Queue is empty" = "";
"Recents" = "";
"Remove from Playlist" = "";
"Remove from the queue" = "";
"Replies" = "";
"Reset" = "";
"Save history of searches, channels and playlists" = "";
"Search" = "";
"Seek gesture sensitivity" = "";
"Select location closest to you:" = "";
/* SponsorBlock category name */
"Self-promotion" = "";
"Show keywords" = "";
"Show channel name" = "";
"Show video length" = "";
"Sort" = "";
"Sort: %@" = "";
"Trending" = "";
/* Player controls layout size for TV */
"TV" = "";
"You need to select an account\nto access %@ section" = "";
"Unlisted" = "";
"Could not open playlist" = "";
"Could not extract video ID" = "";
"Highest" = "";
"Highest quality" = "";
/* Video date filter in search */
"Hour" = "";
"If you are interested what's coming in future updates, you can track project Milestones." = "";
"If you are reporting a bug, include all relevant details (especially: app version, used device and system version, steps to reproduce)." = "";
"Info" = "";
"Instance of current account" = "";
/* SponsorBlock category name */
"Interaction" = "";
"Interface" = "";
/* SponsorBlock category name */
"Intro" = "";
"Issues Tracker" = "";
/* Selected video has just finished playing */
"Just watched" = "";
/* Player controls layout size */
"Large" = "";
"Loading..." = "";
"Locations" = "";
"Low" = "";
"Mark as watched" = "";
"Mark video as watched after playing" = "";
"Mark watched videos with" = "";
"Matrix Chat" = "";
"Milestones" = "";
"No description" = "";
"No Playlists" = "";
"Not Playing" = "";
"Normal" = "";
"Nothing" = "";
"Only when signed in" = "";
"Open Settings" = "";
"Player" = "";
"Pause" = "";
"Play Last" = "";
"Play Music" = "";
"Play Next" = "";
"Playlist" = "";
"Playlist \"%@\" will be deleted.\nIt cannot be reverted." = "";
"Playlists" = "";
"Popular" = "";
"Proxy videos" = "";
"Regular size" = "";
"Related" = "";
/* Video sort order in search */
"Relevance" = "";
"Remove" = "";
"Remove from Favorites" = "";
"Rotate to portrait when exiting fullscreen" = "";
"Search..." = "";
"Sections" = "";
"Seek gesture speed" = "";
"Seek with horizontal swipe on video" = "";
/* Video duration filter in search */
"Short" = "";
"Show account username" = "";
"Sidebar" = "";
/* Player controls layout size */
"Smaller" = "";
"Source" = "";
"SponsorBlock API Instance" = "";
"Subscribe" = "";
/* Subscriptions title */
"Subscriptions" = "";
"Switch to other public location" = "";
"System controls buttons" = "";
"That's nice to hear. It is fun to deliver apps other people want to use. You can consider donating to the project or help by contributing to new features development." = "";
"Unsubscribe" = "";
"URL" = "";
"Used to create links from videos, channels and playlists" = "";
"Username" = "";
/* Player controls layout size */
"Very Large" = "";
/* Video sort order in search */
"Views" = "";
"Watched" = "";
"When partially watched video is played" = "";
"Wi-Fi" = "";
"Yattee %@ (build %@)" = "";
/* Video date filter in search */
"Year" = "";
"Public" = "";
"Private" = "";
"Playing Next" = "";
"Current Playlist" = "";
"Stream FPS" = "";
"Keep last played video in the queue after restart" = "";
"It can be changed later in settings. You can use your own locations too." = "";
"Press and hold remote button to open captions and quality menus" = "";
"Comments are disabled" = "";
"No comments" = "";
"Share Logs..." = "";
"Open logs in Finder" = "";
"Could not open video" = "";
"Channel could not be found" = "";
"Could not extract channel information" = "";
"Could not extract SID from received cookies: %@" = "";
"Could not update your token." = "";
"Could not refresh Trending" = "";
"This URL could not be opened" = "";
"Could not refresh Popular" = "";
"Could not create share link" = "";
"This video could not be opened" = "";
"No locations available at the moment" = "";
"Could not refresh Playlists" = "";
/* Selected video is being played */
"Watching now" = "";
"If you want this app to be available in your language, join translation project." = "";
"Translations" = "";
"Increase rate" = "";
"Could not extract playlist ID" = "";
"Could not load video" = "";
"Playback" = "";
"Restart/Play next" = "";
"This cannot be reverted" = "";
"This cannot be reverted. You might need to switch between views or restart the app to see changes." = "";
"Could not open channel" = "";
"Recent History" = "";
"Share files from Finder on a Mac\nor iTunes on Windows" = "";
"Pages toolbar position" = "";
"Video actions buttons" = "";
"Video" = "";
"Show Open Videos toolbar button" = "";
"Show Documents" = "";
"Clear Queue before opening" = "";
"Open" = "";
"Add" = "";
"Hide" = "";
"Format" = "";
"Audio" = "";
"Codec" = "";
"Size" = "";
"Remove…" = "";
"Playback history is empty" = "";
"Copy%@link" = "";
"Share%@link" = "";

View File

@@ -462,3 +462,43 @@
"Playback Mode" = "Mode Playback";
"Add" = "Ajouter";
"Hide" = "Cacher";
"Size" = "";
"Address" = "";
"Could not delete document" = "";
"Could not find any links to open in your clipboard" = "";
"Center" = "";
"Locations Manifest" = "";
"Actions buttons" = "";
"Sample Rate" = "";
"FPS" = "";
"Remove…" = "";
"Live Streams" = "";
"\"%@\" will be irreversibly removed from this device." = "";
"Remove Location" = "";
"Open Video" = "";
"Video actions buttons" = "";
"Documents" = "";
"Show Open Videos toolbar button" = "";
"File" = "";
"Are you sure you want to remove this document?" = "";
"Left" = "";
"Shorts" = "";
"Copy%@link" = "";
"Verified" = "";
"Show sidebar" = "";
"Driver" = "";
"Show Open Videos quick actions" = "";
"Format" = "";
"Are you sure you want to remove %@ location?" = "";
"Show only icons" = "";
"Audio" = "";
"Share files from Finder on a Mac\nor iTunes on Windows" = "";
"Channel" = "";
"Inspector visibility" = "";
"Video" = "";
"Right" = "";
"Show icons and text when space permits" = "";
"Codec" = "";
"Default Profile" = "";
"Playback history is empty" = "";
"Share%@link" = "";

View File

@@ -407,3 +407,98 @@
"No comments" = "कोई टिप्पणी नहीं";
"No chapters information available" = "कोई अध्याय जानकारी उपलब्ध नहीं";
"Comments are disabled" = "टिप्पणियाँ अक्षम हैं";
"Open Video" = "";
"Reload manifest" = "";
"Pages buttons" = "";
"Open Files" = "";
"Channels" = "";
"Locations Manifest" = "";
"Could not delete document" = "";
"Show Inspector" = "";
"Could not load streams" = "";
"Address" = "";
"Playback Mode" = "";
"Left" = "";
"Show icons and text when space permits" = "";
"FPS" = "";
"Buttons labels" = "";
"Remove…" = "";
"Driver" = "";
"Show only icons" = "";
"Could not load video" = "";
"Are you sure you want to remove this document?" = "";
"Hide" = "";
"\"%@\" will be irreversibly removed from this device." = "";
"Could not open Files" = "";
"Video Details" = "";
"Open" = "";
"Open Videos" = "";
"Show Documents" = "";
"Inspector visibility" = "";
"Add" = "";
"Show Favorites" = "";
"Clear Queue before opening" = "";
"If you want this app to be available in your language, join translation project." = "";
"Documents" = "";
"Playback history is empty" = "";
"Show sidebar" = "";
"Live Streams" = "";
"Enter links to open, one per line" = "";
"Verified" = "";
"No documents" = "";
"Show Open Videos toolbar button" = "";
"Could not refresh Subscriptions" = "";
"Remove Location" = "";
"Only for local files and URLs" = "";
"Codec" = "";
"File" = "";
"Could not extract playlist ID" = "";
"Paste" = "";
"Could not extract SID from received cookies: %@" = "";
"Files" = "";
"Show Home" = "";
"Could not extract channel information" = "";
"Enter link to open" = "";
"Home" = "";
"No locations available at the moment" = "";
"Could not find any links to open in your clipboard" = "";
"Audio" = "";
"Actions buttons" = "";
"Share" = "";
"Always" = "";
"Format" = "";
"Share files from Finder on a Mac\nor iTunes on Windows" = "";
"Share%@link" = "";
"Could not open video" = "";
"Center" = "";
"Size" = "";
"Recent Documents" = "";
"This video could not be opened" = "";
"Video" = "";
"URL to Open" = "";
"Edit Favorites…" = "";
"Video actions buttons" = "";
"Right" = "";
"Shorts" = "";
"For custom locations you can configure Frontend URL in Locations settings" = "";
"Could not create share link" = "";
"Sample Rate" = "";
"Translations" = "";
"Open logs in Finder" = "";
"Could not refresh Playlists" = "";
"Could not update your token." = "";
"Could not refresh Trending" = "";
"Could not open playlist" = "";
"This URL could not be opened" = "";
"Could not open channel" = "";
"Channel could not be found" = "";
"Could not refresh Popular" = "";
"Could not extract video ID" = "";
"Channel" = "";
"Are you sure you want to remove %@ location?" = "";
"Recent History" = "";
"Show Open Videos quick actions" = "";
"Pages toolbar position" = "";
"Default Profile" = "";
"Copy%@link" = "";
"Share Logs..." = "";

View File

@@ -0,0 +1,532 @@
"Formats will be selected in order as listed.\nHLS is an adaptive format (resolution setting does not apply)." = "形式は一覧の順に選択されます。\nHLS は適応的な形式です (解像度設定が適用されない)。";
"Save history of searches, channels and playlists" = "検索、チャンネル、プレイリストの履歴を保存";
"Statistics" = "統計";
"Apply to all" = "これをすべてに適用";
"Reload manifest" = "マニフェストを再読込";
"Left" = "左";
"Codec" = "コーデック";
"Add profile..." = "プロファイルの追加...";
"Add Quality Profile" = "品質プロファイルを追加";
" subscribers" = " 人の登録者";
"%@ subscribers" = "%@ 人の登録者";
"Accounts are not supported for the application of this instance" = "このインスタンスはアカウントに対応していません";
"%lld videos" = "本の動画";
"%@ Channel" = "%@ チャンネル";
"%@ Playlist" = "%@ プレイリスト";
"Add Location" = "場所を追加";
"Add Location..." = "場所を追加...";
"Advanced" = "高度";
"Add to Favorites" = "お気に入りに追加";
"Add to %@" = "%@に追加";
"Are you sure you want to clear history of watched videos?" = "視聴済み動画の履歴を消去しますか?";
"Are you sure you want to delete playlist?" = "プレイリストを消去しますか?";
"Backend" = "バックエンド";
"Badge color" = "バッジの色";
"Badge" = "バッジ";
"Badge & Decreased opacity" = "バッジと透明化";
"Blue" = "青";
"Buffering stream..." = "ストリームのバッファ中...";
"Cancel" = "キャンセル";
"Button" = "ボタン";
"Captions" = "字幕";
"Categories to Skip" = "この分類を飛ばす";
"Clear the queue" = "再生待ちを消去";
"Charging" = "充電中";
"Clear" = "消去";
"Close PiP when player is opened" = "プレイヤーが開いたら PiP を閉じる";
"Connection failed" = "接続失敗";
"Close Video" = "動画を閉じる";
"Close video after playing last in the queue" = "再生待ちの最後を再生後に動画を閉じる";
"Continue" = "続き";
"Continue from %@" = "%@から続ける";
"Comments" = "コメント";
"Create Playlist" = "プレイリストの作成";
"Could not load locations manifest" = "場所のマニフェストが読み込めません";
"Copy %@ link" = "%@ リンクをコピー";
"Copy %@ link with time" = "%@ リンクを時間指定でコピー";
"Current: %@\n%@" = "現在: %@\n%@";
"Decreased opacity" = "透明化";
"Delete" = "削除";
"Custom Locations" = "場所の指定";
"Decrease rate" = "評価を下げる";
"Done" = "完了";
"Discord Server" = "Discord のサーバー";
"Duration" = "長さ";
"Edit" = "編集";
"Edit Playlist" = "プレイリストを編集";
"Donations" = "寄付";
"Don't use public locations" = "公開された場所を使用しない";
"Enable logging" = "ログ記録を有効化";
"Enable Return YouTube Dislike" = "";
"Error" = "エラー";
"Error when accessing playlist" = "プレイリストのアクセス時にエラー";
"Enter fullscreen in landscape" = "横向きなら全画面にする";
"Favorites" = "お気に入り";
"Filter" = "絞り込み";
"Filter: active" = "絞り込み中";
"Finding something to play..." = "再生したいものを検索...";
"Find Other" = "ほかを探す";
"High" = "高";
"Fullscreen size" = "全画面時のサイズ";
"Frontend URL" = "フロントエンドの URL";
"Gaming" = "ゲーム";
"Highest" = "最高";
"Highest quality" = "最高品質";
"Honor orientation lock" = "向きのロックに従う";
"Increase rate" = "評価を上げる";
/* SponsorBlock category name */
"Intro" = "導入シーン";
/* Selected video has just finished playing */
"Just watched" = "いま視聴済み";
/* Player controls layout size */
"Large" = "大";
/* Loading stream OSD */
"Loading streams..." = "ストリームを読み込み中...";
"Lock portrait mode" = "縦モードをロック";
"LIVE" = "ライブ";
"Locations" = "場所";
/* Video duration filter in search */
"Long" = "長い";
"Mark watched videos with" = "視聴済みの表示方法";
"Mark as watched" = "視聴済みにする";
"Medium quality" = "中品質";
"More info can be found in:" = "詳細情報は以下:";
"MPV Documentation" = "MPV の説明文書";
"Movies" = "動画";
"Music" = "音楽";
"Name" = "名前";
"Not available" = "利用できません";
/* SponsorBlock category name */
"Offtopic in Music Videos" = "音楽の動画で脱線した内容";
"Only when signed in" = "ログイン時のみ";
"Orientation" = "向き";
"Opening audio stream..." = "音声ストリームを開始中...";
/* Loading stream OSD */
"Opening %@ stream..." = "%@ ストリームを開始中...";
/* SponsorBlock category name */
"Outro" = "終了シーン";
"Pause" = "停止";
"Play in PiP" = "PiPで再生";
"Playback" = "再生";
"Play Music" = "音楽を再生";
"Profiles" = "プロファイル";
"Popular" = "人気";
"Public Manifest" = "公開のマニフェスト";
"Queue" = "再生待ち";
"Red" = "赤";
"Recents" = "最近";
"Rate" = "評価";
"Refresh" = "更新";
/* Video sort order in search */
"Relevance" = "関連度";
"Remove" = "除去";
"Reset search filters" = "絞り込みを初期化";
"Remove from history" = "履歴から除去";
"Replies" = "返信";
"Rotate to portrait when exiting fullscreen" = "全画面終了時に縦に回転";
"Restart" = "もう一回再生";
"Resolution" = "解像度";
"Restore default profiles..." = "標準のプロファイルを復元...";
"Save" = "保存";
"Round corners" = "角を丸める";
"Seek gesture sensitivity" = "シークのジェスチャー感度";
"Seek with horizontal swipe on video" = "動画で水平スワイプでシーク";
"Search" = "検索";
"Search..." = "検索...";
"Select location closest to you:" = "あなたの場所に近い場所を選択:";
"Share %@ link" = "%@ リンクを共有";
"Share %@ link with time" = "%@ リンクを時間指定で共有";
"Show playback statistics" = "再生データの統計を表示";
"Show progress of watching on thumbnails" = "サムネイル上に進行状態を表示";
"Show sidebar when space permits" = "空きがあればサイドバーを表示";
"Show video length" = "動画の長さを表示";
"Show keywords" = "キーワードを表示";
/* SponsorBlock category name */
"Sponsor" = "広告主";
"SponsorBlock" = "SponsorBlock";
"SponsorBlock API Instance" = "SponsorBlock API インスタンス";
"Source" = "入力";
"System controls buttons" = "システム制御ボタン";
/* Subscriptions title */
"Subscriptions" = "登録チャンネル";
"Switch to other public location" = "ほかの公開された場所に切り替え";
"This cannot be reverted" = "元に戻せません";
"This cannot be reverted. You might need to switch between views or restart the app to see changes." = "元に戻せません。変更の確認には、表示を切り替えたり、アプリの再起動が必要なこともあります。";
"Trending" = "急上昇";
"Unsubscribe" = "登録解除";
"Upload date" = "公開日";
"Username" = "ユーザー名";
/* Video sort order in search */
"Views" = "視聴回数";
"Watched" = "視聴済み";
"Used to create links from videos, channels and playlists" = "動画、チャンネル、プレイリストからのリンク作成に使用";
"When partially watched video is played" = "一部視聴済みの動画の再生時";
/* Selected video was played on given date */
"Watched %@" = "視聴日 %@";
"Welcome" = "ようこそ";
"Yattee" = "Yattee";
"Yattee %@ (build %@)" = "Yattee %@ (ビルド %@)";
"You have no playlists\n\nTap on \"New Playlist\" to create one" = "プレイリストなし\n\n作成には「新規プレイリスト」をタップ";
"Private" = "非公開";
"Unlisted" = "限定公開";
"Current Location" = "現在の場所";
"You can switch between profiles in playback settings controls." = "再生設定の制御からプロファイルを切り替えできます。";
"Add Channels, Playlists and Searches to Favorites using" = "チャンネル、プレイリスト、検索をお気に入りにするには";
"Stream FPS" = "ストリーム FPS";
"Dropped frames" = "フレーム落ち";
"Keep last played video in the queue after restart" = "再起動しても再生待ちの最後の動画を維持";
"It can be changed later in settings. You can use your own locations too." = "設定は後で変更できます。場所の指定も可能です。";
"Comments are disabled" = "コメント無効です";
"Could not refresh Subscriptions" = "登録チャンネルを更新できません";
"Could not load streams" = "ストリームを開けません";
"Could not refresh Popular" = "人気を更新できません";
"Could not open playlist" = "プレイリストを開けません";
"This video could not be opened" = "この動画を開けません";
"Could not extract playlist ID" = "プレイリストの ID を抽出できません";
"Could not load video" = "動画を読み込めません";
"Translations" = "翻訳";
"Could not refresh Playlists" = "プレイリストを更新できません";
"No locations available at the moment" = "現時点で利用可能な場所がありません";
"Show Open Videos quick actions" = "クイック操作に動画を開くを表示";
"Show Documents" = "文書を表示";
"Pages toolbar position" = "ページのツールバー位置";
"Buttons labels" = "ボタンのラベル";
"Clear Queue before opening" = "開く前に再生待ちを消去";
"Video actions buttons" = "動画操作のボタン";
"Enter link to open" = "開きたいリンクを入力";
"Pages buttons" = "ページのボタン";
"Paste" = "貼り付け";
"Add" = "追加";
"Right" = "右";
"Show icons and text when space permits" = "空きがあればアイコンと文字を表示";
"Only for local files and URLs" = "ローカルのファイルとURLのみ";
"Channels" = "チャンネル";
"Driver" = "ドライバー";
"Documents" = "文書";
"Audio" = "音声";
"Actions buttons" = "操作ボタン";
"Default Profile" = "標準のプロファイル";
"Remove Location" = "場所を削除";
"Locations Manifest" = "場所のマニフェスト";
"Copy%@link" = "%@リンクをコピー";
"Share%@link" = "%@リンクを共有";
"\"%@\" will be irreversibly removed from this device." = "「%@」はこの端末から完全に削除されます。";
"Are you sure you want to remove %@ location?" = "場所 %@ を削除しますか?";
"Live Streams" = "ライブ配信";
"Mark channel feed as watched" = "チャンネルフィードを視聴済みにする";
"Short videos: visible" = "ショート動画: 表示";
"Tap and hold channel thumbnail to open context menu with more actions" = "チャンネルのサムネイルをタップで押し続けると、操作用のメニューが表示されます";
"Maximum width expanded" = "展開時に幅を最大化";
"Gesture: fowards" = "ジェスチャー: 進む";
"Gesture: backwards" = "ジェスチャー: 戻る";
"Lock orientation" = "向きをロック";
"Total size: %@" = "合計サイズ: %@";
"Music Mode" = "音楽モード";
"Cache" = "キャッシュ";
"Open channels with description expanded" = "説明を表示してチャンネルを開く";
"History" = "履歴";
"Password" = "パスワード";
"Could not open Files" = "ファイルを開けませんでした";
"File" = "ファイル";
"Address" = "アドレス";
"Open Settings" = "設定を開く";
"Home" = "ホーム";
"Show Home" = "ホームを表示";
"Files" = "ファイル";
"Share" = "共有";
"Format" = "形式";
"Center" = "中央";
"Size" = "サイズ";
"Show sidebar" = "サイドバーを表示";
"Open Files" = "ファイルを開く";
"FPS" = "FPS";
"Remove…" = "除去…";
"No documents" = "文書なし";
"Share files from Finder on a Mac\nor iTunes on Windows" = "Mac の Finder か Windows の\niTunes からファイルを登録";
"Show only icons" = "アイコンのみ表示";
"Sample Rate" = "サンプルレート";
"Playback history is empty" = "再生履歴は空です";
"Clear All Recents" = "最近の項目をすべて消去";
"Matrix Chat" = "Matrix のチャット";
"Settings" = "設定";
"I am lost" = "困っている";
"Video" = "動画";
"Recent History" = "最近の履歴";
"Could not find any links to open in your clipboard" = "クリップボード内に開けるリンクが見つかりません";
"Could not delete document" = "文書を削除できません";
"Open Video" = "動画を開く";
"Are you sure you want to remove this document?" = "この文書を除去しますか?";
/* Video sort order in search */
"Rating" = "評価";
"Recent Documents" = "最近開いた文書";
"Not Playing" = "再生なし";
"Help" = "ヘルプ";
"Nothing" = "なし";
"Contact" = "問い合わせ先";
/* Video date filter in search */
"Hour" = "時間";
"I have a feature request" = "機能を要望したい";
"I want to ask a question" = "質問がある";
"You can find information about using Yattee in the Wiki pages." = "Wiki から Yattee の使い方を探せますよ。";
"Bugs and great feature ideas can be sent to the GitHub issues tracker. " = "バグや素晴らしい機能のアイデアは、GitHub の issue へどうぞ。 ";
"That's nice to hear. It is fun to deliver apps other people want to use. You can consider donating to the project or help by contributing to new features development." = "嬉しいです。みんなが使いたいアプリを提供することは楽しいものです。あなたもプロジェクトに寄付したり、新機能の開発にご参加ください。";
"Hide player" = "プレイヤーを非表示";
"I found a bug /" = "バグを発見 /";
"I like this app!" = "このアプリいいね!";
"If you are interested what's coming in future updates, you can track project Milestones." = "今後の更新に興味があれば、このプロジェクトのマイルストーンを追跡できます。";
"Info" = "情報";
"If you are reporting a bug, include all relevant details (especially: app version, used device and system version, steps to reproduce)." = "バグ報告には、関連するすべての詳細もお願いします (特にアプリのバージョン、端末とシステムのバージョン、再現手順)。";
"Wiki" = "Wiki";
"Milestones" = "マイルストーン";
/* Video date filter in search */
"Year" = "年";
"Discussions take place in Discord and Matrix. It's a good spot for general questions." = "Discord と Matrix で交流しています。一般的な質問に適した場所です。";
"This URL could not be opened" = "この URL を開けませんでした";
"Matrix Channel" = "Matrix のチャンネル";
"Issues Tracker" = "Issue を表示";
/* Player controls layout size */
"Medium" = "中";
/* Video date filter in search */
"Month" = "月";
"Contributing" = "貢献する";
"If you want this app to be available in your language, join translation project." = "あなたの言語で利用したければ、翻訳プロジェクトにご参加ください。";
"Enter links to open, one per line" = "開きたいリンクを1行ごとに入力";
"Open Videos" = "動画を開く";
"Always" = "常に";
/* Player controls layout size */
"Small" = "小";
"URL" = "URL";
"Playing Next" = "次に再生";
"Playback Mode" = "再生モード";
"Play Now" = "すぐ再生";
"Play Next" = "次に再生";
"Play Last" = "最後に再生";
"Play" = "再生";
"Playlist" = "プレイリスト";
"Playlists" = "プレイリスト";
"Picture in Picture" = "ピクチャーインピクチャー";
"Shuffle" = "シャッフル";
"Sidebar" = "サイドバー";
"Play All" = "すべて再生";
"Player" = "プレイヤー";
"Shuffle All" = "すべてシャッフル";
"Sign In Required" = "要ログイン";
/* Player controls layout size */
"Smaller" = "最小";
"Playback queue is empty" = "再生待ちなし";
"Browsing" = "ブラウズ";
"Connected successfully (%@)" = "接続成功 (%@)";
/* Video duration filter in search */
"Short" = "短い";
"Show channel name" = "チャンネル名を表示";
"Show history" = "履歴を表示";
"Share..." = "共有...";
"Show account username" = "アカウントのユーザー名を表示";
"Show anonymous accounts" = "匿名アカウントを表示";
"Close" = "閉じる";
"Hide sidebar" = "サイドバーを非表示";
"Open" = "開く";
"Hide" = "非表示";
"Remove from the queue" = "再生待ちから除去";
"URL to Open" = "開きたい URL";
"Queue is empty" = "再生待ちなし";
"Battery" = "バッテリー";
"Interface" = "外観";
"Close player when closing video" = "動画を閉じたらプレイヤーを閉じる";
"Close player when starting PiP" = "PiP開始時にプレイヤーを閉じる";
"Show Open Videos toolbar button" = "ツールバーに動画を開くを表示";
"Pause when player is closed" = "プレイヤーを閉じたら停止";
"Pause when entering background" = "バックグラウンドに入るときに停止";
"Actions Buttons" = "操作ボタン";
"Stream & Player" = "ストリームとプレイヤー";
"Accounts" = "アカウント";
"Add Account..." = "アカウントを追加...";
"Controls" = "制御";
"Normal" = "通常";
"No results" = "結果なし";
"10 seconds forwards/backwards" = "10秒進む/戻る";
"No Playlists" = "プレイリストなし";
"Next" = "次";
"No description" = "説明なし";
"Low" = "低";
"Regular size" = "通常時のサイズ";
/* Player controls layout size */
"Very Large" = "巨大";
"Add Account" = "アカウントを追加";
"Seek gesture speed" = "シークのジェスチャー速度";
"New Playlist" = "新規プレイリスト";
"Lowest" = "最低";
"Low quality" = "低品質";
"Regular Size" = "通常時のサイズ";
"Large layout is not suitable for all devices and using it may cause controls not to fit on the screen." = "大きな表示はあらゆる端末では適さず、生魚ボタンが画面に収まらないことがあります。";
"Seeking" = "シーク";
"Always show controls buttons" = "常に制御ボタンを表示";
"Controls button: backwards" = "制御ボタン: 戻る";
"Controls Buttons" = "制御ボタン";
"Play next item" = "次の項目を再生";
"Close video" = "動画を閉じる";
"System controls" = "システム制御";
"Show cache status" = "キャッシュの状態を表示";
"Maximum feed items" = "フィードの最大数";
"Are you sure you want to clear cache?" = "キャッシュを削除しますか?";
"Controls button: forwards" = "制御ボタン: 進む";
"Subscribe/Unsubscribe" = "チャンネル登録/解除";
"Open logs in Finder" = "FInder でログを開く";
"Search history is empty" = "検索履歴なし";
"Video Details" = "動画の細部";
"Close PiP and open player when application enters foreground" = "アプリにフォーカスが移ったら PiP を閉じてプレーヤーを開く";
"Could not update your token." = "トークンを更新できません。";
"Channel" = "チャンネル";
"Close PiP when starting playing other video" = "ほかの動画の再生を開始したら PiP を閉じる";
"Any format" = "全形式";
"Share Logs..." = "ログを共有…";
"Could not open video" = "動画を開けません";
"Channel could not be found" = "チャンネルが見つかりません";
"Loading..." = "読み込み中...";
"Hardware decoder" = "ハードウェアデコーダー";
"%@ formats" = "%@ 形式";
"No chapters information available" = "利用できるチャプター情報なし";
"No comments" = "コメントなし";
"Could not extract SID from received cookies: %@" = "受信したクッキーから SID を抽出できません: %@";
"Anonymous" = "匿名";
/* Video date filter in search
Video duration filter in search */
"Any" = "すべて";
"Could not create share link" = "共有リンクを作成できません";
"Could not extract video ID" = "動画 ID を抽出できません";
"Playlist is empty\n\nTap and hold on a video and then \n\"Add to Playlist\"" = "プレイリストなし\n\n動画をタップし続け\n「プレイリストに追加」";
"Could not open channel" = "チャンネルを開けません";
"Wi-Fi" = "Wi-Fi";
"You have no Playlists" = "プレイリストなし";
"Current Playlist" = "現在のプレイリスト";
"Could not extract channel information" = "チャンネル情報を抽出できません";
"Shorts" = "ショート";
"Add to Playlist" = "プレイリストに追加";
"Add to Playlist..." = "プレイリストに追加...";
/* Trending category, section containing all kinds of videos */
"All" = "すべて";
"Are you sure you want to restore default quality profiles?" = "初期値の品質プロファイルを復元しますか?";
"This will remove all your custom profiles and return their default values. This cannot be reverted." = "作成したプロファイルがすべて削除され初期値に戻ります。元に戻せません。";
"Thumbnails" = "サムネイル";
"Restart/Play next" = "もう一回再生/次を再生";
"Cellular" = "構成";
"Edit Quality Profile" = "品質プロファイルを編集";
"Edit..." = "編集...";
"Preferred Formats" = "優先する形式";
"Quality Profile" = "品質プロファイル";
/* Video date filter in search */
"Today" = "今日";
/* Player controls layout size for TV */
"TV" = "TV";
"unknown" = "不明";
/* Video date filter in search */
"Week" = "週";
"Make default" = "標準にする";
"Save history of played videos" = "再生した動画の履歴を保存";
"You can use automatic profile selection based on current device status or switch it in video playback settings controls." = "現在の端末の状態に基づく自動的なプロファイル選択を使うか、動画の再生設定の制御から切り替えるできます。";
"Related" = "関連";
"Country Name or Code" = "国名か国名コード";
/* Video sort order in search */
"Date" = "日時";
/* Locations settings, custom instance is selected as current */
"Custom" = "指定";
"Country" = "国";
"Sort" = "並び替え";
"Clear History" = "履歴を消去";
"Based on system color scheme" = "システムのカラーテーマに従う";
"Restart the app to apply the settings above." = "この設定を適用するにはアプリを再起動します。";
"Now Playing" = "再生中";
"Show Favorites" = "お気に入りを表示";
"Clear all" = "すべて消去";
"Could not refresh Trending" = "急上昇のページを更新できません";
"Edit Favorites…" = "お気に入りを編集…";
"Remove from Favorites" = "お気に入りから除去";
"Sort: %@" = "並び替え: %@";
"Are you sure you want to unsubscribe from %@?" = "%@から登録解除しますか?";
"Automatic" = "自動";
"Autoplaying Next" = "自動で次を再生";
"Subscribe" = "登録";
"Mark video as watched after playing" = "この割合を再生したら視聴済みにする";
/* Selected video is being played */
"Watching now" = "視聴中";
"Reset watched status when playing again" = "再び見る時に視聴状態を初期化";
"Clear All" = "すべて消去";
"Instance of current account" = "現在のアカウントのインスタンス";
"Category" = "分類";
/* SponsorBlock category name */
"Interaction" = "操作の呼びかけ";
/* SponsorBlock category name */
"Self-promotion" = "自己宣伝";
"Quality" = "品質";
"Are you sure you want to clear search history?" = "検索履歴を消去しますか?";
"For videos which feature music as the primary content." = "音楽を主なコンテンツとする動画用です。";
"Always use AVPlayer for live videos" = "ライブ配信には常に AVPlayer を使用";
"Clear Search History" = "検索履歴を消去";
"Disabled" = "無効化";
"Chapters" = "チャプター";
"Clear Search History..." = "検索履歴を消去...";
"Open \"Playlists\" tab to create new one" = "新たに「プレイリスト」タブを開く";
"Public" = "公開";
"Playlist \"%@\" will be deleted.\nIt cannot be reverted." = "プレイリスト「%@」を削除します。\n元に戻せません。";
"Promoting a product or service that is directly related to the creator themselves. This usually includes merchandise or promotion of monetized platforms." = "作成者と直接関係する商品やサービスを宣伝すること。通常、商品や収益化されたプラットフォームの宣伝が含まれます。";
"Remove from Playlist" = "プレイリストから除去";
"Reset" = "初期化";
"Segments typically found at the start of a video that include an animation, still frame or clip which are also seen in other videos by the same creator." = "動画の冒頭で、同じ作成者の他の動画でも見られるアニメーション、静止画やクリップを含む部分。";
"This information will be processed only on your device and used to connect you to the server in the specified country." = "この情報は、この端末上でのみ処理され、指定した国のサーバーに接続するために使用されます。";
"Videos" = "動画";
"Typically near or at the end of the video when the credits pop up and/or endcards are shown." = "クレジットのポップアップやエンドカードが表示される、映像の最後のあたりに表示されます。";
"Verified" = "認証済み";
"Mark channel feed as unwatched" = "チャンネルフィードを未視聴にする";
"Open expanded" = "展開時に";
"Short videos: hidden" = "ショート動画: 非表示";
"Player Bar" = "プレイヤーのバー";
"Play all unwatched" = "未視聴をすべて再生";
"Double tap gesture" = "ダブルタップ";
"Single tap gesture" = "シングルタップ";
"Right click channel thumbnail to open context menu with more actions" = "チャンネルのサムネイルを右クリックすると、操作用のメニューが表示されます";
"Show unwatched feed badges" = "未視聴のフィードのバッジを表示";
"Gesture settings control skipping interval for remote arrow buttons (for 2nd generation Siri Remote or newer). Changing system controls settings requires restart." = "ジェスチャーの設定で、リモコンの矢印ボタンによるスキップ間隔を変更しますSiri Remote 第二世代以降用)。システム制御の設定を変更には、再起動が必要です。";
"Gesture settings control skipping interval for double click on left/right side of the player. Changing system controls settings requires restart." = "ジェスチャーの設定で、プレイヤーの左右をダブルクリックした時のスキップ間隔を変更します。システム制御の設定を変更するには、再起動が必要です。";
"Gesture settings control skipping interval for double tap gesture on left/right side of the player. Changing system controls settings requires restart." = "ジェスチャーの設定で、プレイヤーの左右をダブルタップした時のスキップ間隔を変更します。システム制御の設定を変更するには、再起動が必要です。";
"Part of a video promoting a product or service not directly related to the creator. The creator will receive payment or compensation in the form of money or free products." = "作成者と直接関係のない製品やサービスを宣伝する部分。作成者は金銭や商品提供によって報酬を受け取ります。";
"Press and hold remote button to open captions and quality menus" = "リモコンのボタンを長押しすると、字幕と品質のメニューが表示されます";
"For custom locations you can configure Frontend URL in Locations settings" = "場所を指定するには、場所の設定からフロントエンドのURLを設定します";
"Public Locations" = "公開された場所";
"Switch to public locations" = "公開された場所に切り替え";
"Explicit reminders to like, subscribe or interact with them on any paid or free platform(s) (e.g. click on a video)." = "有料/無料のプラットフォームかを問わず、いいね、登録などを明示的に操作を促す(例: 動画をクリック)。";

View File

@@ -405,3 +405,98 @@
"No chapters information available" = "Ingen tilgjengelig kapittelinfo";
"Comments are disabled" = "Kommentarer er avskrudd";
"Press and hold remote button to open captions and quality menus" = "Trykk og hold fjernknappen for å åpne meny for undertekster og kvalitet";
"Paste" = "";
"Codec" = "";
"Open Videos" = "";
"Files" = "";
"Open Video" = "";
"Show only icons" = "";
"Show Open Videos toolbar button" = "";
"Channels" = "";
"Buttons labels" = "";
"Could not open Files" = "";
"Reload manifest" = "";
"Right" = "";
"Show Favorites" = "";
"Only for local files and URLs" = "";
"Enter link to open" = "";
"Left" = "";
"Are you sure you want to remove this document?" = "";
"Recent Documents" = "";
"Share files from Finder on a Mac\nor iTunes on Windows" = "";
"Address" = "";
"File" = "";
"Share" = "";
"Could not delete document" = "";
"Are you sure you want to remove %@ location?" = "";
"Size" = "";
"Always" = "";
"Video actions buttons" = "";
"Edit Favorites…" = "";
"Sample Rate" = "";
"Show Inspector" = "";
"Remove Location" = "";
"Format" = "";
"Verified" = "";
"Show icons and text when space permits" = "";
"Could not extract video ID" = "";
"Open Files" = "";
"Driver" = "";
"Show Open Videos quick actions" = "";
"Enter links to open, one per line" = "";
"No locations available at the moment" = "";
"Video Details" = "";
"Add" = "";
"Show Home" = "";
"Pages buttons" = "";
"Center" = "";
"Shorts" = "";
"Open" = "";
"Locations Manifest" = "";
"FPS" = "";
"Inspector visibility" = "";
"Show Documents" = "";
"Open logs in Finder" = "";
"Documents" = "";
"Could not update your token." = "";
"Remove…" = "";
"Hide" = "";
"Actions buttons" = "";
"Audio" = "";
"Could not extract SID from received cookies: %@" = "";
"Playback Mode" = "";
"Clear Queue before opening" = "";
"Could not create share link" = "";
"Could not refresh Playlists" = "";
"Could not refresh Subscriptions" = "";
"Translations" = "";
"This URL could not be opened" = "";
"For custom locations you can configure Frontend URL in Locations settings" = "";
"Could not refresh Trending" = "";
"If you want this app to be available in your language, join translation project." = "";
"This video could not be opened" = "";
"Could not open channel" = "";
"Could not open playlist" = "";
"Could not load streams" = "";
"Could not open video" = "";
"Could not extract channel information" = "";
"Could not load video" = "";
"Could not extract playlist ID" = "";
"Could not refresh Popular" = "";
"Channel could not be found" = "";
"Live Streams" = "";
"Channel" = "";
"No documents" = "";
"\"%@\" will be irreversibly removed from this device." = "";
"Recent History" = "";
"Home" = "";
"Pages toolbar position" = "";
"URL to Open" = "";
"Video" = "";
"Could not find any links to open in your clipboard" = "";
"Show sidebar" = "";
"Default Profile" = "";
"Playback history is empty" = "";
"Copy%@link" = "";
"Share%@link" = "";
"Share Logs..." = "";

View File

@@ -503,3 +503,41 @@
"Shorts" = "Shorts";
"Verified" = "Zweryfikowano";
"Channel" = "Kanał";
"Short videos: visible" = "Krótkie wideo: widoczne";
"Mark channel feed as watched" = "Oznacz najnowsze z kanału jako obejrzane";
"Short videos: hidden" = "Krótkie wideo: ukryte";
"Mark channel feed as unwatched" = "Oznacz najnowsze z kanału jako nieobejrzane";
"Play all unwatched" = "Odtwórz nieobejrzane";
"Player Bar" = "Pasek odtwarzacza";
"Double tap gesture" = "Gest podwójnego stuknięcia";
"Open expanded" = "Domyślnie rozwinięty";
"Always show controls buttons" = "Zawsze pokazuj przyciski akcji";
"Controls button: backwards" = "Przycisk: do tyłu";
"Single tap gesture" = "Gest pojedynczego stuknięcia";
"Maximum width expanded" = "Maksymalna szerokość rozwinięcia";
"Tap and hold channel thumbnail to open context menu with more actions" = "Wciśnij i przytrzymaj miniaturkę kanału aby otworzyć menu dla innych akcji";
"Clear all" = "Wyczyść wszystko";
"Right click channel thumbnail to open context menu with more actions" = "Kliknij prawym na miniaturkę kanału aby otworzyć menu innych akcji";
"Show unwatched feed badges" = "Pokaż licznik nieobejrzanych z subskrybcji";
"Seeking" = "Przewijanie";
"Gesture: fowards" = "Gest: do przodu";
"System controls" = "Kontrolki systemu";
"Controls button: forwards" = "Przycisk: do przodu";
"Gesture: backwards" = "Gest: do tyłu";
"Gesture settings control skipping interval for double tap gesture on left/right side of the player. Changing system controls settings requires restart." = "Ustawienia gestu dotyczą podwójnego stuknięcia po lewej/prawej stronie odtwarzacza. Zmiana ustawień kontrolek systemu wymaga ponownego uruchomienia aplikacji.";
"Hide player" = "Ukryj odtwarzacz";
"Gesture settings control skipping interval for remote arrow buttons (for 2nd generation Siri Remote or newer). Changing system controls settings requires restart." = "Ustawienia gestu dotyczą przycisków na pilocie Apple TV (Siri Remote drugiej generacji albo nowszy). Zmiana ustawień kontrolek systemu wymaga ponownego uruchomienia aplikacji.";
"Controls Buttons" = "Przyciski kontrolek";
"Play next item" = "Odtwórz następny";
"Lock orientation" = "Zablokuj orientację";
"Music Mode" = "Tryb Muzyki";
"Close video" = "Zamknij wideo";
"Total size: %@" = "Całkowity rozmiar: %@";
"Actions Buttons" = "Przyciski akcji";
"Subscribe/Unsubscribe" = "Subskrybuj/Odsubskrybuj";
"Cache" = "Pamięć podręczna";
"Show cache status" = "Pokaż status pamięci podręcznej";
"Maximum feed items" = "Maksymalna liczba nieobejrzanych z subskrybcji";
"Open channels with description expanded" = "Otwórz kanały z rozwiniętym opisem";
"Gesture settings control skipping interval for double click on left/right side of the player. Changing system controls settings requires restart." = "Ustawienia gestu dotyczą podwójnego kliknięcia po lewej/prawej stronie odtwarzacza. Zmiana ustawień kontrolek systemu wymaga ponownego uruchomienia aplikacji.";
"Are you sure you want to clear cache?" = "Czy na pewno chcesz wyczyścić pamięć podręczną?";

View File

@@ -259,7 +259,7 @@
"Watched %@" = "Assistido %@";
"Welcome" = "Boas-vindas";
"Watched" = "Assistido";
"You can use automatic profile selection based on current device status or switch it in video playback settings controls." = "Você pode usar a seleção automática de perfil baseado no status do dispositivo atual ou mudar nós controles dos ajustes de playback de vídeo.";
"You can use automatic profile selection based on current device status or switch it in video playback settings controls." = "Você pode usar a seleção automática de perfil baseado no status do dispositivo atual ou mudar nos controles dos ajustes de playback de vídeo.";
/* Player controls layout size for TV */
"TV" = "TV";
@@ -502,3 +502,41 @@
"Live Streams" = "Transmissões ao Vivo";
"Verified" = "Verificado";
"Channel" = "Canal";
"Short videos: visible" = "Vídeos curtos: visíveis";
"Mark channel feed as unwatched" = "Marcar feed do canal como não visto";
"Double tap gesture" = "Gesto de dois toques";
"Close video" = "Fechar vídeo";
"Maximum feed items" = "Máximo de itens do feed";
"Open expanded" = "Abrir expandido";
"Mark channel feed as watched" = "Marcar feed do canal como visto";
"Short videos: hidden" = "Vídeos curtos: ocultos";
"Play all unwatched" = "Tocar todos não vistos";
"Tap and hold channel thumbnail to open context menu with more actions" = "Toque e segure a miniatura do canal para abrir um menu contextual com mais ações";
"Single tap gesture" = "Gesto de um toque";
"Maximum width expanded" = "Largura máxima expandida";
"Right click channel thumbnail to open context menu with more actions" = "Clique com o botão direito na miniatura do canal para abrir um menu contextual com mais ações";
"Gesture: fowards" = "Gesto: para frente";
"Controls Buttons" = "Botões de Controle";
"System controls" = "Controles do sistema";
"Controls button: backwards" = "Botão de controle: para trás";
"Hide player" = "Esconder player";
"Actions Buttons" = "Botões de Ação";
"Play next item" = "Tocar próximo item";
"Lock orientation" = "Travar orientação";
"Music Mode" = "Modo Música";
"Total size: %@" = "Tamanho total: %@";
"Open channels with description expanded" = "Abrir canais com descrição expandida";
"Cache" = "Cache";
"Show cache status" = "Mostrar status de cache";
"Player Bar" = "Barra do Player";
"Gesture settings control skipping interval for double tap gesture on left/right side of the player. Changing system controls settings requires restart." = "As configurações de gesto controlam o intervalo de pulo para o gesto de dois toques no lado esquerdo/direito do player. Mudar as configurações dos controles do sistema requer reinício.";
"Gesture settings control skipping interval for remote arrow buttons (for 2nd generation Siri Remote or newer). Changing system controls settings requires restart." = "As configurações de gesto controlam o intervalo de pulo para os botões de seta do controle remoto (para Siri Remote de 2ª geração ou posteriores). Mudar as configurações dos controles do sistema requer reinício.";
"Seeking" = "Busca";
"Show unwatched feed badges" = "Mostrar ícone de feed não visto";
"Clear all" = "Limpar tudo";
"Gesture: backwards" = "Gesto: para trás";
"Always show controls buttons" = "Sempre mostrar botões de controle";
"Controls button: forwards" = "Botão de controle: para frente";
"Subscribe/Unsubscribe" = "Inscrever/Desinscrever";
"Are you sure you want to clear cache?" = "Tem certeza que deseja limpar o cache?";
"Gesture settings control skipping interval for double click on left/right side of the player. Changing system controls settings requires restart." = "As configurações de gesto controlam o intervalo de pulo para o clique duplo no lado direito/esquerdo do player. Mudar as configurações dos controles do sistema requer reinício.";

View File

@@ -502,3 +502,41 @@
"Shorts" = "Shorts";
"Verified" = "Verificat";
"Channel" = "Canal";
"Open expanded" = "Deschide extins";
"Mark channel feed as unwatched" = "Marcați feedul canalului ca nevizionat";
"Mark channel feed as watched" = "Marcați feedul canalului ca vizionat";
"Short videos: visible" = "Videoclipuri scurte: vizibile";
"Player Bar" = "Bară playerului";
"Short videos: hidden" = "Videoclipuri scurte: ascunse";
"Play all unwatched" = "Redă toate nevizionate";
"Double tap gesture" = "Atingeți de două ori gest";
"Tap and hold channel thumbnail to open context menu with more actions" = "Atingeți lung miniatura canalului pentru a deschide meniul contextual cu mai multe acțiuni";
"Always show controls buttons" = "Afișați întotdeauna butoanele de control";
"Single tap gesture" = "Gest cu o singură atingere";
"Maximum width expanded" = "Lățimea maximă extinsă";
"Clear all" = "Ștergeți tot";
"Right click channel thumbnail to open context menu with more actions" = "Faceți clic dreapta pe miniatura canalului pentru a deschide meniul contextual cu mai multe acțiuni";
"Show unwatched feed badges" = "Afișați insigne de feed nevizionate";
"Gesture: fowards" = "Gestul: înainte";
"System controls" = "Controale de sistem";
"Controls button: backwards" = "Buton de control: înapoi";
"Controls button: forwards" = "Buton de control: înainte";
"Gesture: backwards" = "Gestul: înapoi";
"Gesture settings control skipping interval for double tap gesture on left/right side of the player. Changing system controls settings requires restart." = "Setările pentru gesturi controlează intervalul de ignorare pentru gestul de atingere dublă în partea stângă/dreapta a playerului. Modificarea setărilor comenzilor sistemului necesită repornire.";
"Hide player" = "Ascunde player-ul";
"Gesture settings control skipping interval for double click on left/right side of the player. Changing system controls settings requires restart." = "Setările gesturilor controlează intervalul de ignorare pentru dublu clic pe partea stângă/dreapta a playerului. Modificarea setărilor comenzilor sistemului necesită repornirea.";
"Gesture settings control skipping interval for remote arrow buttons (for 2nd generation Siri Remote or newer). Changing system controls settings requires restart." = "Setările gesturilor controlează intervalul de ignorare pentru butoanele săgeți de la distanță (pentru telecomanda Siri de a doua generație sau mai nouă). Modificarea setărilor comenzilor sistemului necesită repornire.";
"Controls Buttons" = "Butoane de control";
"Actions Buttons" = "Butoane de acțiuni";
"Play next item" = "Redă următorul element";
"Lock orientation" = "Blocare orientare";
"Music Mode" = "Modul Muzică";
"Close video" = "Închideți video";
"Seeking" = "Căutarea";
"Total size: %@" = "Marimea totala: %@";
"Open channels with description expanded" = "Deschideți canale cu descrierea extinsă";
"Cache" = "Cache";
"Subscribe/Unsubscribe" = "Abonează-te/Dezabonează-te";
"Show cache status" = "Afișați starea cache-ului";
"Maximum feed items" = "Numărul maxim de articole de feed";
"Are you sure you want to clear cache?" = "Sigur doriți să ștergeți memoria cache?";

View File

@@ -111,3 +111,394 @@
"Find Other" = "Letar annat";
"Finding something to play..." = "Letar något att spela...";
"10 seconds forwards/backwards" = "10 sekunder framåt/bakåt";
"Low" = "";
/* Player controls layout size */
"Large" = "";
"Interface" = "";
"Increase rate" = "";
"If you are reporting a bug, include all relevant details (especially: app version, used device and system version, steps to reproduce)." = "";
"Playlist \"%@\" will be deleted.\nIt cannot be reverted." = "";
"You need to select an account\nto access %@ section" = "";
"Playlists" = "";
/* Video date filter in search
Video duration filter in search */
"Any" = "";
"Password" = "";
"Play All" = "";
"That's nice to hear. It is fun to deliver apps other people want to use. You can consider donating to the project or help by contributing to new features development." = "";
"Quality Profile" = "";
"Popular" = "";
"Promoting a product or service that is directly related to the creator themselves. This usually includes merchandise or promotion of monetized platforms." = "";
"Now Playing" = "";
/* Loading stream OSD */
"Loading streams..." = "";
"Typically near or at the end of the video when the credits pop up and/or endcards are shown." = "";
"Picture in Picture" = "";
"Playlist" = "";
"Queue is empty" = "";
"Search history is empty" = "";
"Pause" = "";
"LIVE" = "";
"Play Next" = "";
"Play Music" = "";
"Channels" = "";
"Show icons and text when space permits" = "";
"Instance of current account" = "";
"You can find information about using Yattee in the Wiki pages." = "";
"Driver" = "";
/* Selected video has just finished playing */
"Just watched" = "";
"Preferred Formats" = "";
"Play in PiP" = "";
"Pause when entering background" = "";
"You need to create an instance and accounts\nto access %@ section" = "";
"This information will be processed only on your device and used to connect you to the server in the specified country." = "";
"Are you sure you want to remove %@ location?" = "";
"Trending" = "";
"Regular Size" = "";
"Public Manifest" = "";
"Player" = "";
"Info" = "";
"Sort" = "";
"Unlisted" = "";
"System controls buttons" = "";
"Show Open Videos quick actions" = "";
"Orientation" = "";
"Not Playing" = "";
"Restore default profiles..." = "";
"More info can be found in:" = "";
"Rate" = "";
"Restart the app to apply the settings above." = "";
/* Player controls layout size for TV */
"TV" = "";
"Recent History" = "";
"Remove from Favorites" = "";
"No documents" = "";
"Play Last" = "";
"Documents" = "";
"Could not load video" = "";
"Could not open playlist" = "";
"System controls show buttons for %@" = "";
/* SponsorBlock category name */
"Intro" = "";
"Next" = "";
"Sort: %@" = "";
"Locations" = "";
"Could not extract video ID" = "";
"Unsubscribe" = "";
"Nothing" = "";
"File" = "";
"Restart" = "";
"You have no Playlists" = "";
/* Video date filter in search */
"Hour" = "";
"Playback history is empty" = "";
"Refresh" = "";
"For custom locations you can configure Frontend URL in Locations settings" = "";
"Remove" = "";
"Default Profile" = "";
"Buttons labels" = "";
"Public Locations" = "";
"I like this app!" = "";
"Current Location" = "";
"Share files from Finder on a Mac\nor iTunes on Windows" = "";
"Could not delete document" = "";
"Video actions buttons" = "";
"Show anonymous accounts" = "";
"Show Documents" = "";
"Center" = "";
"Not available" = "";
/* SponsorBlock category name */
"Offtopic in Music Videos" = "";
"SponsorBlock API Instance" = "";
"Remove Location" = "";
"Resolution" = "";
"Show Inspector" = "";
"Low quality" = "";
/* SponsorBlock category name */
"Outro" = "";
"Lock portrait mode" = "";
"Issues Tracker" = "";
"Copy%@link" = "";
"Switch to public locations" = "";
"Private" = "";
"Backend" = "";
"For videos which feature music as the primary content." = "";
"Formats will be selected in order as listed.\nHLS is an adaptive format (resolution setting does not apply)." = "";
"Frontend URL" = "";
"Fullscreen size" = "";
"Gaming" = "";
"Help" = "";
"Hide sidebar" = "";
"High" = "";
"Highest" = "";
"Highest quality" = "";
"History" = "";
"Honor orientation lock" = "";
"I am lost" = "";
"I found a bug /" = "";
"I have a feature request" = "";
"I want to ask a question" = "";
"If you are interested what's coming in future updates, you can track project Milestones." = "";
/* SponsorBlock category name */
"Interaction" = "";
"Large layout is not suitable for all devices and using it may cause controls not to fit on the screen." = "";
"Loading..." = "";
/* Video duration filter in search */
"Long" = "";
"Lowest" = "";
"Mark as watched" = "";
"Mark video as watched after playing" = "";
"Mark watched videos with" = "";
"Matrix Channel" = "";
"Matrix Chat" = "";
/* Player controls layout size */
"Medium" = "";
"Medium quality" = "";
"Milestones" = "";
/* Video date filter in search */
"Month" = "";
"Movies" = "";
"MPV Documentation" = "";
"Music" = "";
"Name" = "";
"New Playlist" = "";
"No description" = "";
"No Playlists" = "";
"No results" = "";
"Normal" = "";
"Only when signed in" = "";
"Open \"Playlists\" tab to create new one" = "";
"Open Settings" = "";
/* Loading stream OSD */
"Opening %@ stream..." = "";
"Opening audio stream..." = "";
"Part of a video promoting a product or service not directly related to the creator. The creator will receive payment or compensation in the form of money or free products." = "";
"Pause when player is closed" = "";
"Play" = "";
"Play Now" = "";
"Playback" = "";
"Profiles" = "";
"Proxy videos" = "";
"Quality" = "";
"Queue" = "";
/* Video sort order in search */
"Rating" = "";
"Recents" = "";
"Red" = "";
"Regular size" = "";
"Related" = "";
/* Video sort order in search */
"Relevance" = "";
"Remove from history" = "";
"Remove from Playlist" = "";
"Remove from the queue" = "";
"Replies" = "";
"Reset" = "";
"Reset search filters" = "";
"Reset watched status when playing again" = "";
"Restart/Play next" = "";
"Rotate to portrait when exiting fullscreen" = "";
"Round corners" = "";
"Save history of played videos" = "";
"Save history of searches, channels and playlists" = "";
"Search" = "";
"Search..." = "";
"Sections" = "";
"Save" = "";
"Seek gesture speed" = "";
"Seek gesture sensitivity" = "";
"Seek with horizontal swipe on video" = "";
"Segments typically found at the start of a video that include an animation, still frame or clip which are also seen in other videos by the same creator." = "";
"Select location closest to you:" = "";
/* SponsorBlock category name */
"Self-promotion" = "";
"Settings" = "";
"Share %@ link" = "";
"Share %@ link with time" = "";
"Share..." = "";
/* Video duration filter in search */
"Short" = "";
"Show account username" = "";
"Show channel name" = "";
"Show history" = "";
"Show keywords" = "";
"Show playback statistics" = "";
"Show progress of watching on thumbnails" = "";
"Show sidebar when space permits" = "";
"Show video length" = "";
"Shuffle" = "";
"Shuffle All" = "";
"Sidebar" = "";
"Sign In Required" = "";
/* Player controls layout size */
"Small" = "";
/* Player controls layout size */
"Smaller" = "";
"Source" = "";
"SponsorBlock" = "";
"Subscribe" = "";
/* Subscriptions title */
"Subscriptions" = "";
"Switch to other public location" = "";
"This cannot be reverted" = "";
/* SponsorBlock category name */
"Sponsor" = "";
"This cannot be reverted. You might need to switch between views or restart the app to see changes." = "";
/* Video date filter in search */
"Today" = "";
"This will remove all your custom profiles and return their default values. This cannot be reverted." = "";
"Thumbnails" = "";
"unknown" = "";
"Upload date" = "";
"URL" = "";
"Used to create links from videos, channels and playlists" = "";
"Username" = "";
/* Player controls layout size */
"Very Large" = "";
"Videos" = "";
/* Video sort order in search */
"Views" = "";
"Watched" = "";
/* Selected video was played on given date */
"Watched %@" = "";
/* Selected video is being played */
"Watching now" = "";
/* Video date filter in search */
"Week" = "";
"Welcome" = "";
"When partially watched video is played" = "";
"Wi-Fi" = "";
"Wiki" = "";
"Yattee" = "";
"Yattee %@ (build %@)" = "";
/* Video date filter in search */
"Year" = "";
"You can use automatic profile selection based on current device status or switch it in video playback settings controls." = "";
"You have no playlists\n\nTap on \"New Playlist\" to create one" = "";
"Public" = "";
"Playback queue is empty" = "";
"Playing Next" = "";
"You can switch between profiles in playback settings controls." = "";
"Add Channels, Playlists and Searches to Favorites using" = "";
"Make default" = "";
"Visibility" = "";
"Current Playlist" = "";
"Stream & Player" = "";
"Statistics" = "";
"Hardware decoder" = "";
"Stream FPS" = "";
"Cached time" = "";
"Rate & Captions" = "";
"Dropped frames" = "";
"Any format" = "";
"%@ formats" = "";
"Keep last played video in the queue after restart" = "";
"Playlist is empty\n\nTap and hold on a video and then \n\"Add to Playlist\"" = "";
"It can be changed later in settings. You can use your own locations too." = "";
"Press and hold remote button to open captions and quality menus" = "";
"Comments are disabled" = "";
"No comments" = "";
"No chapters information available" = "";
"Share Logs..." = "";
"Open logs in Finder" = "";
"Could not refresh Subscriptions" = "";
"Could not load streams" = "";
"Could not open video" = "";
"Channel could not be found" = "";
"Could not extract channel information" = "";
"Could not extract SID from received cookies: %@" = "";
"Could not update your token." = "";
"Could not refresh Trending" = "";
"This URL could not be opened" = "";
"Could not open channel" = "";
"Could not refresh Popular" = "";
"Could not create share link" = "";
"This video could not be opened" = "";
"Could not extract playlist ID" = "";
"No locations available at the moment" = "";
"Could not refresh Playlists" = "";
"If you want this app to be available in your language, join translation project." = "";
"Translations" = "";
"Recent Documents" = "";
"Home" = "";
"Show Home" = "";
"Show Favorites" = "";
"Inspector visibility" = "";
"Edit Favorites…" = "";
"Show Open Videos toolbar button" = "";
"Files" = "";
"Pages toolbar position" = "";
"Video Details" = "";
"Reload manifest" = "";
"Clear Queue before opening" = "";
"Open" = "";
"Pages buttons" = "";
"URL to Open" = "";
"Enter link to open" = "";
"Could not open Files" = "";
"Paste" = "";
"Open Videos" = "";
"Enter links to open, one per line" = "";
"Playback Mode" = "";
"Add" = "";
"Hide" = "";
"Always" = "";
"Only for local files and URLs" = "";
"Right" = "";
"Open Files" = "";
"Share" = "";
"Left" = "";
"Format" = "";
"Show only icons" = "";
"Audio" = "";
"Video" = "";
"Codec" = "";
"Size" = "";
"FPS" = "";
"Sample Rate" = "";
"Could not find any links to open in your clipboard" = "";
"Address" = "";
"Remove…" = "";
"Actions buttons" = "";
"Show sidebar" = "";
"Locations Manifest" = "";
"Open Video" = "";
"Share%@link" = "";
"Are you sure you want to remove this document?" = "";
"\"%@\" will be irreversibly removed from this device." = "";
"Live Streams" = "";
"Shorts" = "";
"Verified" = "";
"Channel" = "";

View File

@@ -266,3 +266,239 @@
"Sections" = "Bölümler";
"Save history of searches, channels and playlists" = "Arama, kanal ve çalma listelerinin geçmişini kaydet";
"Restore default profiles..." = "Varsayılan profilleri geri yükle...";
"Visibility" = "";
"Translations" = "";
"Enter links to open, one per line" = "";
"Open Videos" = "";
"Playback Mode" = "";
/* Selected video was played on given date */
"Watched %@" = "";
"Yattee %@ (build %@)" = "";
"That's nice to hear. It is fun to deliver apps other people want to use. You can consider donating to the project or help by contributing to new features development." = "";
"Thumbnails" = "";
"Dropped frames" = "";
"SponsorBlock API Instance" = "";
/* Selected video is being played */
"Watching now" = "";
"Video Details" = "";
"Live Streams" = "";
"Typically near or at the end of the video when the credits pop up and/or endcards are shown." = "";
"Default Profile" = "";
/* Player controls layout size for TV */
"TV" = "";
"Add" = "";
"This URL could not be opened" = "";
"Hide" = "";
"Playing Next" = "";
"Are you sure you want to remove this document?" = "";
"Show channel name" = "";
"Unlisted" = "";
"Paste" = "";
"Rate & Captions" = "";
"Format" = "";
"Right" = "";
"Stream FPS" = "";
"Cached time" = "";
"Sign In Required" = "";
"Could not create share link" = "";
"Locations Manifest" = "";
"When partially watched video is played" = "";
"Open Video" = "";
"Add Channels, Playlists and Searches to Favorites using" = "";
"Always" = "";
/* Video date filter in search */
"Year" = "";
"Playback queue is empty" = "";
"Show Favorites" = "";
"Driver" = "";
"Show progress of watching on thumbnails" = "";
"Left" = "";
"URL to Open" = "";
"Subscribe" = "";
"Yattee" = "";
"Show Documents" = "";
"Press and hold remote button to open captions and quality menus" = "";
"No locations available at the moment" = "";
"Show account username" = "";
"Used to create links from videos, channels and playlists" = "";
"Size" = "";
"You have no playlists\n\nTap on \"New Playlist\" to create one" = "";
"Sort: %@" = "";
"Select location closest to you:" = "";
"Playlist is empty\n\nTap and hold on a video and then \n\"Add to Playlist\"" = "";
/* Video duration filter in search */
"Short" = "";
"Home" = "";
"Remove Location" = "";
"Edit Favorites…" = "";
"Show Open Videos toolbar button" = "";
"Sample Rate" = "";
"Private" = "";
"Browsing" = "";
"Documents" = "";
"FPS" = "";
"Only for local files and URLs" = "";
"Show sidebar" = "";
"Current Playlist" = "";
"Center" = "";
"Address" = "";
"Video actions buttons" = "";
"Keep last played video in the queue after restart" = "";
"Remove…" = "";
"Trending" = "";
"Statistics" = "";
"Copy%@link" = "";
"Now Playing" = "";
"Could not delete document" = "";
"No comments" = "";
"Could not open Files" = "";
"You need to select an account\nto access %@ section" = "";
"Reload manifest" = "";
"Could not refresh Subscriptions" = "";
/* Subscriptions title */
"Subscriptions" = "";
"Upload date" = "";
"This information will be processed only on your device and used to connect you to the server in the specified country." = "";
"Shuffle" = "";
"Buttons labels" = "";
"Share %@ link" = "";
"Could not load streams" = "";
"Playback history is empty" = "";
"Show icons and text when space permits" = "";
"unknown" = "";
"Share..." = "";
/* Video sort order in search */
"Views" = "";
"You need to create an instance and accounts\nto access %@ section" = "";
"Verified" = "";
"Open Files" = "";
"Could not refresh Playlists" = "";
"Actions buttons" = "";
"Any format" = "";
"Show playback statistics" = "";
"Pages buttons" = "";
"Videos" = "";
"Codec" = "";
"Comments are disabled" = "";
"Audio" = "";
"Public" = "";
"Files" = "";
"Show Home" = "";
"Open" = "";
/* Loading stream OSD */
"Opening %@ stream..." = "";
"Clear Queue before opening" = "";
"Copy %@ link with time" = "";
"Show Inspector" = "";
"Make default" = "";
"Are you sure you want to remove %@ location?" = "";
"No chapters information available" = "";
"Share Logs..." = "";
"Enter link to open" = "";
"No documents" = "";
"Inspector visibility" = "";
"Could not update your token." = "";
"Could not find any links to open in your clipboard" = "";
/* Video date filter in search */
"Week" = "";
"Sidebar" = "";
"Show only icons" = "";
"Current: %@\n%@" = "";
"Show anonymous accounts" = "";
"Could not open playlist" = "";
"Round corners" = "";
"URL" = "";
"Recents" = "";
"Show sidebar when space permits" = "";
"System controls buttons" = "";
"Could not extract channel information" = "";
"Public Locations" = "";
"You can find information about using Yattee in the Wiki pages." = "";
/* Player controls layout size */
"Very Large" = "";
"Continue from %@" = "";
"Copy %@ link" = "";
"Seek gesture sensitivity" = "";
"Show keywords" = "";
"Wiki" = "";
"Username" = "";
"Could not extract video ID" = "";
/* Player controls layout size */
"Smaller" = "";
"Sort" = "";
"This cannot be reverted" = "";
"Public Manifest" = "";
"You have no Playlists" = "";
"Watched" = "";
"Could not open video" = "";
"Channel could not be found" = "";
"Show video length" = "";
"Source" = "";
"Welcome" = "";
"Wi-Fi" = "";
"Could not open channel" = "";
"This video could not be opened" = "";
"Could not extract playlist ID" = "";
"Could not load video" = "";
"Decreased opacity" = "";
"Shuffle All" = "";
"Share %@ link with time" = "";
"This cannot be reverted. You might need to switch between views or restart the app to see changes." = "";
"Unsubscribe" = "";
"Current Location" = "";
"Stream & Player" = "";
"Hardware decoder" = "";
"Honor orientation lock" = "";
"Seek with horizontal swipe on video" = "";
"Segments typically found at the start of a video that include an animation, still frame or clip which are also seen in other videos by the same creator." = "";
"Switch to public locations" = "";
"%@ formats" = "";
"Open logs in Finder" = "";
"Could not refresh Popular" = "";
/* SponsorBlock category name */
"Self-promotion" = "";
/* Player controls layout size */
"Small" = "";
/* SponsorBlock category name */
"Sponsor" = "";
"System controls show buttons for %@" = "";
"Show history" = "";
"Could not extract SID from received cookies: %@" = "";
"This will remove all your custom profiles and return their default values. This cannot be reverted." = "";
"Switch to other public location" = "";
"SponsorBlock" = "";
"Seek gesture speed" = "";
"If you want this app to be available in your language, join translation project." = "";
"Could not refresh Trending" = "";
/* Video date filter in search */
"Today" = "";
"Shorts" = "";
"Channel" = "";
"Share files from Finder on a Mac\nor iTunes on Windows" = "";
"\"%@\" will be irreversibly removed from this device." = "";
"Recent Documents" = "";
"Recent History" = "";
"Show Open Videos quick actions" = "";
"Pages toolbar position" = "";
"Video" = "";
"Channels" = "";
"Share" = "";
"File" = "";
"Share%@link" = "";

View File

@@ -830,6 +830,9 @@
37C7A1D6267BFD9D0010EAD6 /* SponsorBlockSegment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37C7A1D4267BFD9D0010EAD6 /* SponsorBlockSegment.swift */; };
37C7A1D7267BFD9D0010EAD6 /* SponsorBlockSegment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37C7A1D4267BFD9D0010EAD6 /* SponsorBlockSegment.swift */; };
37C7A1DA267CACF50010EAD6 /* TrendingCountry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3705B17F267B4DFB00704544 /* TrendingCountry.swift */; };
37C7B21429ABD9F20013C196 /* ChannelPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37C7B21329ABD9F20013C196 /* ChannelPage.swift */; };
37C7B21529ABD9F20013C196 /* ChannelPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37C7B21329ABD9F20013C196 /* ChannelPage.swift */; };
37C7B21629ABD9F20013C196 /* ChannelPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37C7B21329ABD9F20013C196 /* ChannelPage.swift */; };
37C89322294532220032AFD3 /* PlayerOverlayModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37C89321294532220032AFD3 /* PlayerOverlayModifier.swift */; };
37C89323294532220032AFD3 /* PlayerOverlayModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37C89321294532220032AFD3 /* PlayerOverlayModifier.swift */; };
37C89324294532220032AFD3 /* PlayerOverlayModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37C89321294532220032AFD3 /* PlayerOverlayModifier.swift */; };
@@ -1381,6 +1384,7 @@
37AAF27F26737550007FC770 /* SearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchView.swift; sourceTree = "<group>"; };
37AAF28F26740715007FC770 /* Channel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Channel.swift; sourceTree = "<group>"; };
37AAF29F26741C97007FC770 /* FeedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedView.swift; sourceTree = "<group>"; };
37ABD5FE29BE7FA800DDCAD7 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Localizable.strings; sourceTree = "<group>"; };
37B044B626F7AB9000E1419D /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
37B17D9F268A1F25006AEE9B /* VideoContextMenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoContextMenuView.swift; sourceTree = "<group>"; };
37B263192735EAAB00FE0D40 /* FavoriteResourceObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoriteResourceObserver.swift; sourceTree = "<group>"; };
@@ -1432,6 +1436,7 @@
37C3A24C272360470087A57A /* ChannelPlaylist+Fixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ChannelPlaylist+Fixtures.swift"; sourceTree = "<group>"; };
37C3A250272366440087A57A /* ChannelPlaylistView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelPlaylistView.swift; sourceTree = "<group>"; };
37C7A1D4267BFD9D0010EAD6 /* SponsorBlockSegment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SponsorBlockSegment.swift; sourceTree = "<group>"; };
37C7B21329ABD9F20013C196 /* ChannelPage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelPage.swift; sourceTree = "<group>"; };
37C89321294532220032AFD3 /* PlayerOverlayModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerOverlayModifier.swift; sourceTree = "<group>"; };
37C8E700294FC97D00EEAB14 /* QueueView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueueView.swift; sourceTree = "<group>"; };
37CC3F44270CE30600608308 /* PlayerQueueItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlayerQueueItem.swift; sourceTree = "<group>"; };
@@ -2380,6 +2385,7 @@
377F9F79294403DC0043F856 /* Cache */,
3776ADD5287381240078EBC4 /* Captions.swift */,
37AAF28F26740715007FC770 /* Channel.swift */,
37C7B21329ABD9F20013C196 /* ChannelPage.swift */,
37C3A24427235DA70087A57A /* ChannelPlaylist.swift */,
37520698285E8DD300CA655F /* Chapter.swift */,
371B7E5B27596B8400D21217 /* Comment.swift */,
@@ -2821,6 +2827,7 @@
ar,
pt,
"pt-BR",
ja,
);
mainGroup = 37D4B0BC2671614700C925CA;
packageReferences = (
@@ -3237,6 +3244,7 @@
37484C3126FCB8F900287258 /* AccountValidator.swift in Sources */,
377ABC48286E5887009C986F /* Sequence+Unique.swift in Sources */,
37520699285E8DD300CA655F /* Chapter.swift in Sources */,
37C7B21429ABD9F20013C196 /* ChannelPage.swift in Sources */,
37319F0527103F94004ECCD0 /* PlayerQueue.swift in Sources */,
376B2E0726F920D600B1D64D /* SignInRequiredView.swift in Sources */,
37C0697E2725C8D400F7F6CB /* CMTime+DefaultTimescale.swift in Sources */,
@@ -3462,6 +3470,7 @@
37A362BB2953707F00BDF328 /* ClearQueueButton.swift in Sources */,
3752069E285E910600CA655F /* ChapterView.swift in Sources */,
37030FF827B0347C00ECDDAA /* MPVPlayerView.swift in Sources */,
37C7B21529ABD9F20013C196 /* ChannelPage.swift in Sources */,
378E50FC26FE8B9F00F49626 /* Instance.swift in Sources */,
37169AA32729D98A0011DE61 /* InstancesBridge.swift in Sources */,
37B044B826F7AB9000E1419D /* SettingsView.swift in Sources */,
@@ -3882,6 +3891,7 @@
378E50FD26FE8B9F00F49626 /* Instance.swift in Sources */,
37169AA82729E2CC0011DE61 /* AccountsBridge.swift in Sources */,
37C8E703294FC97D00EEAB14 /* QueueView.swift in Sources */,
37C7B21629ABD9F20013C196 /* ChannelPage.swift in Sources */,
3754B01728B7F84D009717C8 /* Constants.swift in Sources */,
37BC50AE2778BCBA00510953 /* HistoryModel.swift in Sources */,
37D526E02720AC4400ED2F5E /* VideosAPI.swift in Sources */,
@@ -3963,6 +3973,7 @@
37E868FD29AA400B003128D0 /* ar */,
37E868FE29AA402D003128D0 /* pt */,
37E868FF29AA407B003128D0 /* pt-BR */,
37ABD5FE29BE7FA800DDCAD7 /* ja */,
);
name = Localizable.strings;
sourceTree = "<group>";
@@ -3977,7 +3988,7 @@
CODE_SIGN_ENTITLEMENTS = "Open in Yattee/Open in Yattee.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 137;
CURRENT_PROJECT_VERSION = 139;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "Open in Yattee/Info.plist";
INFOPLIST_KEY_CFBundleDisplayName = "Open in Yattee";
@@ -4008,7 +4019,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 137;
CURRENT_PROJECT_VERSION = 139;
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 78Z5H3M6RJ;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "Open in Yattee/Info.plist";
@@ -4039,7 +4050,7 @@
buildSettings = {
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 137;
CURRENT_PROJECT_VERSION = 139;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MACOSX_DEPLOYMENT_TARGET = 11.0;
@@ -4059,7 +4070,7 @@
buildSettings = {
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 137;
CURRENT_PROJECT_VERSION = 139;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MACOSX_DEPLOYMENT_TARGET = 11.0;
@@ -4219,7 +4230,7 @@
CODE_SIGN_ENTITLEMENTS = "iOS/Yattee (iOS).entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 137;
CURRENT_PROJECT_VERSION = 139;
ENABLE_PREVIEWS = YES;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
@@ -4272,7 +4283,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 137;
CURRENT_PROJECT_VERSION = 139;
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = 78Z5H3M6RJ;
ENABLE_PREVIEWS = YES;
GCC_PREPROCESSOR_DEFINITIONS = "GLES_SILENCE_DEPRECATION=1";
@@ -4324,7 +4335,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 137;
CURRENT_PROJECT_VERSION = 139;
DEAD_CODE_STRIPPING = YES;
ENABLE_APP_SANDBOX = YES;
ENABLE_HARDENED_RUNTIME = YES;
@@ -4366,7 +4377,7 @@
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "3rd Party Mac Developer Application";
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 137;
CURRENT_PROJECT_VERSION = 139;
DEAD_CODE_STRIPPING = YES;
"DEVELOPMENT_TEAM[sdk=macosx*]" = 78Z5H3M6RJ;
ENABLE_APP_SANDBOX = YES;
@@ -4404,7 +4415,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 137;
CURRENT_PROJECT_VERSION = 139;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
@@ -4428,7 +4439,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 137;
CURRENT_PROJECT_VERSION = 139;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
@@ -4454,7 +4465,7 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 137;
CURRENT_PROJECT_VERSION = 139;
DEAD_CODE_STRIPPING = YES;
GENERATE_INFOPLIST_FILE = YES;
LD_RUNPATH_SEARCH_PATHS = (
@@ -4479,7 +4490,7 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 137;
CURRENT_PROJECT_VERSION = 139;
DEAD_CODE_STRIPPING = YES;
GENERATE_INFOPLIST_FILE = YES;
LD_RUNPATH_SEARCH_PATHS = (
@@ -4505,7 +4516,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 137;
CURRENT_PROJECT_VERSION = 139;
DEVELOPMENT_ASSET_PATHS = "";
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
@@ -4545,7 +4556,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 137;
CURRENT_PROJECT_VERSION = 139;
DEVELOPMENT_ASSET_PATHS = "";
"DEVELOPMENT_TEAM[sdk=appletvos*]" = 78Z5H3M6RJ;
ENABLE_PREVIEWS = YES;
@@ -4586,7 +4597,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 137;
CURRENT_PROJECT_VERSION = 139;
GENERATE_INFOPLIST_FILE = YES;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
@@ -4610,7 +4621,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 137;
CURRENT_PROJECT_VERSION = 139;
GENERATE_INFOPLIST_FILE = YES;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",

View File

@@ -24,9 +24,6 @@ DEVELOPER_APP_IDENTIFIER = ENV['DEVELOPER_APP_IDENTIFIER']
GIT_AUTHORIZATION = ENV['GIT_AUTHORIZATION']
TESTFLIGHT_EXTERNAL_GROUPS = ENV['TESTFLIGHT_EXTERNAL_GROUPS']
AS_CONNECT_BUILD_VERSION_FILENAME = 'AS_CONNECT_BUILD_VERSION'
AS_CONNECT_BUILD_VERSION_PATH = "../#{AS_CONNECT_BUILD_VERSION_FILENAME}"
XCODEPROJ = "#{APP_NAME}.xcodeproj"
def delete_temp_keychain(name)
@@ -57,30 +54,12 @@ end
desc "Bump build number and commit"
lane :bump_build do
as_connect_build_version = File.read(AS_CONNECT_BUILD_VERSION_PATH).to_i
build = get_build_number(xcodeproj: XCODEPROJ).to_i
increment_build_number(xcodeproj: XCODEPROJ)
puts "AS Connect build version: #{as_connect_build_version}"
puts "Current build number: #{build}"
if build <= as_connect_build_version
new_build_number = as_connect_build_version + 1
increment_build_number
actual_build_number = get_build_number(xcodeproj: XCODEPROJ).to_i
puts "Bumped build number to #{actual_build_number}"
File.open(AS_CONNECT_BUILD_VERSION_PATH, 'w+') { |file| file.write("#{new_build_number}\n") }
commit_version_bump(
message: "Bump build number to #{get_build_number(xcodeproj: XCODEPROJ)}",
include: [AS_CONNECT_BUILD_VERSION_FILENAME],
xcodeproj: XCODEPROJ
)
else
puts "Current build number is higher than App Store Connect build version"
end
commit_version_bump(
message: "Bump build number to #{get_build_number(xcodeproj: XCODEPROJ)}",
xcodeproj: XCODEPROJ
)
end
desc "Bump version number and commit"