├── .editorconfig ├── .github └── workflows │ └── main.yml ├── .gitignore ├── .spi.yml ├── Images ├── Apps │ ├── CrossCraft.webp │ ├── FocusBeats.webp │ ├── FreelanceKit.webp │ ├── FreemiumKit.webp │ ├── GuidedGuestMode.webp │ ├── PleydiaOrganizer.webp │ ├── Posters.webp │ └── TranslateKit.webp ├── LabelStyles.jpeg ├── Logo.png ├── MacHelpMenu.jpeg ├── PhoneSettings.jpeg └── ProviderTokenCampaign.jpeg ├── LICENSE ├── Package.swift ├── README.md └── Sources └── LinksKit ├── LinksKit.swift ├── Localizable.xcstrings ├── Model ├── Link.swift ├── LinkMenu.swift ├── LinkSection.swift └── SocialPlatform.swift ├── Styles ├── TitleAndIconBadgeLabelStyle.swift ├── TitleAndTrailingIconBadgeLabelStyle.swift └── TitleAndTrailingIconLabelStyle.swift └── Views ├── LinkSectionsView.swift └── LinksView.swift /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | 6 | indent_style = space 7 | tab_width = 6 8 | indent_size = 3 9 | 10 | end_of_line = lf 11 | insert_final_newline = true 12 | 13 | max_line_length = 160 14 | trim_trailing_whitespace = true 15 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | branches: [main] 6 | 7 | jobs: 8 | test-macos: 9 | runs-on: macos-15 10 | 11 | steps: 12 | - uses: actions/checkout@v4 13 | 14 | - name: Build package 15 | run: swift build 16 | 17 | - name: Run tests 18 | if: hashFiles('Tests/**') != '' 19 | run: swift test 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | xcuserdata/ 5 | DerivedData/ 6 | .swiftpm/configuration/registries.json 7 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata 8 | .netrc 9 | -------------------------------------------------------------------------------- /.spi.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | builder: 3 | configs: 4 | - documentation_targets: [LinksKit] 5 | swift_version: 6.0 6 | -------------------------------------------------------------------------------- /Images/Apps/CrossCraft.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlineDev/LinksKit/ee42ce9a0859794971fd6448ee916db5088595cb/Images/Apps/CrossCraft.webp -------------------------------------------------------------------------------- /Images/Apps/FocusBeats.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlineDev/LinksKit/ee42ce9a0859794971fd6448ee916db5088595cb/Images/Apps/FocusBeats.webp -------------------------------------------------------------------------------- /Images/Apps/FreelanceKit.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlineDev/LinksKit/ee42ce9a0859794971fd6448ee916db5088595cb/Images/Apps/FreelanceKit.webp -------------------------------------------------------------------------------- /Images/Apps/FreemiumKit.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlineDev/LinksKit/ee42ce9a0859794971fd6448ee916db5088595cb/Images/Apps/FreemiumKit.webp -------------------------------------------------------------------------------- /Images/Apps/GuidedGuestMode.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlineDev/LinksKit/ee42ce9a0859794971fd6448ee916db5088595cb/Images/Apps/GuidedGuestMode.webp -------------------------------------------------------------------------------- /Images/Apps/PleydiaOrganizer.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlineDev/LinksKit/ee42ce9a0859794971fd6448ee916db5088595cb/Images/Apps/PleydiaOrganizer.webp -------------------------------------------------------------------------------- /Images/Apps/Posters.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlineDev/LinksKit/ee42ce9a0859794971fd6448ee916db5088595cb/Images/Apps/Posters.webp -------------------------------------------------------------------------------- /Images/Apps/TranslateKit.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlineDev/LinksKit/ee42ce9a0859794971fd6448ee916db5088595cb/Images/Apps/TranslateKit.webp -------------------------------------------------------------------------------- /Images/LabelStyles.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlineDev/LinksKit/ee42ce9a0859794971fd6448ee916db5088595cb/Images/LabelStyles.jpeg -------------------------------------------------------------------------------- /Images/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlineDev/LinksKit/ee42ce9a0859794971fd6448ee916db5088595cb/Images/Logo.png -------------------------------------------------------------------------------- /Images/MacHelpMenu.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlineDev/LinksKit/ee42ce9a0859794971fd6448ee916db5088595cb/Images/MacHelpMenu.jpeg -------------------------------------------------------------------------------- /Images/PhoneSettings.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlineDev/LinksKit/ee42ce9a0859794971fd6448ee916db5088595cb/Images/PhoneSettings.jpeg -------------------------------------------------------------------------------- /Images/ProviderTokenCampaign.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlineDev/LinksKit/ee42ce9a0859794971fd6448ee916db5088595cb/Images/ProviderTokenCampaign.jpeg -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 FlineDev (Cihat Gündüz) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.9 2 | import PackageDescription 3 | 4 | let package = Package( 5 | name: "LinksKit", 6 | defaultLocalization: "en", 7 | platforms: [.iOS(.v16), .macOS(.v13), .tvOS(.v16), .visionOS(.v1), .watchOS(.v9)], 8 | products: [.library(name: "LinksKit", targets: ["LinksKit"])], 9 | targets: [.target(name: "LinksKit", resources: [.process("Localizable.xcstrings")])] 10 | ) 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![LinksKit Logo](https://github.com/FlineDev/LinksKit/blob/main/Images/Logo.png?raw=true) 2 | 3 | [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FFlineDev%2FLinksKit%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/FlineDev/LinksKit) 4 | [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FFlineDev%2FLinksKit%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/FlineDev/LinksKit) 5 | 6 | # LinksKit 7 | 8 | Every app on the App Store must provide essential links like a privacy policy and, if applicable, terms of use (for in-app purchases) to comply with Apple's guidelines. Many apps handle this by adding a "Links" section in their settings, including additional helpful links like app ratings, FAQs, and support options. 9 | 10 | That's where LinksKit comes in: it offers **a simple, ready-to-use solution to handle all these common links**, saving you a ton of time. Whether it's legal, help, or app promotion links, LinksKit covers it. And for macOS, it even supports adding these links right into the **Help** menu! 11 | 12 | iOS Example | macOS Example 13 | ------------------------|------------------------- 14 | | 15 | 16 | ## Usage 17 | 18 | Getting started with LinksKit is easy. After adding the package to your project, simply `import LinksKit` and place a `LinksView()` inside a `List` or `Form` view. But before doing that, you'll need to configure the links you want to include. 19 | 20 | ### Minimal Setup 21 | 22 | For a basic setup, which includes legal links (like privacy policy and terms of use), app rating, and a contact email, you can configure LinksKit like this: 23 | 24 | ```swift 25 | import SwiftUI 26 | 27 | @main 28 | struct YourApp: App { 29 | init() { 30 | // other setup code 31 | 32 | LinksKit.configure( 33 | providerToken: "123456", 34 | linkSections: [ 35 | .helpLinks(appID: "123456789", supportEmail: "support@example.com"), 36 | .legalLinks(privacyURL: URL(string: "https://example.com")!) 37 | ] 38 | ) 39 | } 40 | 41 | var body: some Scene { 42 | // your UI code 43 | } 44 | } 45 | ``` 46 | 47 | > **Tip:** Your `providerToken` already exists and is the same for all your apps. Unfortunately, Apple does not have an easier way to look it up than within the "Campaign" creation form on App Store Connect under Analytics > Acquisition > Campaigns. You don't actually need to press 'Create', just enter some text in the form and you'll see the `pt` parameter in the Campaign Link preview. Campaign links are a great way to track where users are finding your app. Learn more about them [here](https://developer.apple.com/help/app-store-connect/view-app-analytics/manage-campaigns). 48 | 49 | 50 | 51 | > **Note:** LinksKit will automatically add Apple's terms of use link to `.legalLinks` for apps with in-app purchases. No need to configure it yourself – it just works! 🚀 52 | 53 | ### Optional Extras 54 | 55 | LinksKit goes beyond the basics, offering more customization to fit your needs. You can: 56 | 57 | * Add an FAQ link with `faqURL` passed to `.helpLinks` 58 | * Link to your app's or developer's social media with `.socialMenus(appLinks:developerLinks:)` 59 | * Promote your other apps or apps from friends using `.appMenus(ownAppLinks:friendsAppLinks:)` 60 | 61 | Here’s a real-world example from my app [TranslateKit](https://apps.apple.com/app/apple-store/id6476773066?pt=549314&ct=github.com&mt=8), showcasing all of these features: 62 | 63 | ```swift 64 | init() { 65 | // other setup code 66 | 67 | self.configureLinksKit() 68 | } 69 | 70 | func configureLinksKit() { 71 | // App Links 72 | let ownDeveloperApps = LinkSection(entries: [ 73 | .link(.ownApp(id: "6502914189", name: "FreemiumKit: In-App Purchases", systemImage: "cart")), 74 | .link(.ownApp(id: "6480134993", name: "FreelanceKit: Time Tracking", systemImage: "timer")), 75 | ]) 76 | 77 | let ownConsumerApps = LinkSection(entries: [ 78 | .link(.ownApp(id: "6472669260", name: "CrossCraft: Crossword Tests", systemImage: "puzzlepiece")), 79 | .link(.ownApp(id: "6477829138", name: "FocusBeats: Study Music Timer", systemImage: "music.note")), 80 | .link(.ownApp(id: "6587583340", name: "Pleydia Organizer: Media Renamer", systemImage: "popcorn")), 81 | ]) 82 | 83 | let ownVisionApps = LinkSection(entries: [ 84 | .link(.ownApp(id: "6479207869", name: "Guided Guest Mode: Device Demo", systemImage: "questionmark.circle")), 85 | .link(.ownApp(id: "6478062053", name: "Posters: Discover Movies at Home", systemImage: "movieclapper")), 86 | ]) 87 | 88 | let nicosApps = LinkSection(entries: [ 89 | .link(.friendsApp(id: "1249686798", name: "NFC.cool Tools: Tag Reader", systemImage: "tag", providerToken: "106913804")), 90 | .link(.friendsApp(id: "6443995212", name: "Metadata for Fastlane Tools", systemImage: "hammer", providerToken: "106913804")), 91 | ]) 92 | 93 | let jansApps = LinkSection(entries: [ 94 | .link(.friendsApp(id: "6503256642", name: "App Exhibit: Your App Showcase", systemImage: "square.grid.3x3.fill.square")), 95 | ]) 96 | 97 | // Configure LinksKit 98 | LinksKit.configure( 99 | providerToken: "549314", 100 | linkSections: [ 101 | .helpLinks(appID: "6476773066", faqURL: Constants.faqURL, supportEmail: "translatekit@fline.dev"), 102 | .socialMenus( 103 | appLinks: .appSocialLinks( 104 | platforms: [.twitter, .mastodon(instance: "mastodon.social"), .threads], 105 | handle: "TranslateKit", 106 | handleOverrides: [.twitter: "TranslateKitApp"] 107 | ), 108 | developerLinks: .developerSocialLinks( 109 | platforms: [.twitter, .mastodon(instance: "iosdev.space"), .threads], 110 | handle: "Jeehut" 111 | ) 112 | ), 113 | .appMenus( 114 | ownAppLinks: [ownDeveloperApps, ownConsumerApps, ownVisionApps], 115 | friendsAppLinks: [nicosApps, jansApps] 116 | ), 117 | .legalLinks(privacyURL: Constants.privacyPolicyURL) 118 | ] 119 | ) 120 | } 121 | ``` 122 | 123 | > **Tip:** If you have `appLinks` but no `developerLinks` (or vice versa) when using the `.socialMenus` helper, you can just pass `.appSocialLinks` or `.developerSocialLinks` directly instead of passing `.socialMenus`. 124 | 125 | > **Note:** The `.ownApp` and `.friendsApp` helpers behave differently for a reason. LinksKit will automatically append your `providerToken` for your own apps, while you'll need to manually include a `providerToken` for your friends’ apps if you know it. 126 | 127 | ### View Setup 128 | 129 | To add LinksKit to your app’s settings screen, typically structured as a `Form` or `List`, just insert a `LinksView()` like so: 130 | 131 | ```swift 132 | import SwiftUI 133 | 134 | struct SettingsView: View { 135 | var body: some View { 136 | Form { 137 | // other sections/views like a paid status view or app settings 138 | 139 | #if !os(macOS) 140 | LinksView() 141 | #endif 142 | } 143 | } 144 | } 145 | ``` 146 | 147 | And that’s it! If you’re not targeting macOS, the result should look like this: 148 | 149 | 150 | 151 | For macOS apps, the best place for these links is often in the Help menu. You can easily add a `LinksView()` to the menu bar: 152 | 153 | ```swift 154 | import SwiftUI 155 | 156 | @main 157 | struct YourApp: App { 158 | var body: some Scene { 159 | WindowGroup { 160 | // your UI code 161 | } 162 | #if os(macOS) 163 | .commands { 164 | CommandGroup(replacing: .help) { 165 | LinksView() 166 | .labelStyle(.titleAndIcon) 167 | } 168 | } 169 | #endif 170 | } 171 | } 172 | ``` 173 | 174 | Here’s what that will look like on macOS: 175 | 176 | 177 | 178 | ### Custom Links & Menus 179 | 180 | If the default helpers like `.helpLinks` or `.appMenus` don't fit your exact use case, you can create fully custom `LinkSection` instances and add your own links. You can even nest them! For example, `.appMenus` is just a convenience for this equivalent `LinkSection`: 181 | 182 | 183 | ```swift 184 | LinkSection( 185 | title: "App Links", 186 | entries: [ 187 | .menu(LinkMenu( 188 | title: "More Apps from Developer", 189 | systemImage: "plus.square.on.square", 190 | linkSections: [ownDeveloperApps, ownConsumerApps, ownVisionApps] 191 | )), 192 | .menu(LinkMenu( 193 | title: "Apps from Friends", 194 | systemImage: "hand.thumbsup", 195 | linkSections: [nicosApps, jansApps] 196 | )), 197 | ] 198 | ) 199 | ``` 200 | 201 | The `entries` parameter accepts one of `.menu(LinkMenu)` or `.link(Link)` and you can nest as many levels as SwiftUI supports (`.menu` is rendered as a `Menu` view, `.link` as a `Button`). 202 | 203 | ### Label Styles 204 | 205 | LinksKit ships with additional `Label` styles which you can use to give your Form/List view a different look: 206 | 207 | * `.labelStyle(.titleAndTrailingIcon)`: Renders exactly like the default `.titleAndIcon` style, but with the icon at the **trailing** end. 208 | * `.labelStyle(.titleAndIconBadge(color:))`: Resembles Apple's style in the Settings app by adding a colored background to the leading icons. 209 | * `.labelStyle(.titleAndTrailingIconBadge(color:))`: Same as the above, but the icon is placed at the trailing end. 210 | 211 | 212 | 213 | ### Localization 214 | 215 | All of LinksKit's built-in strings are already localized in around 40 languages, covering all the languages supported by iOS. No setup is needed. If you require additional languages, feel free to open an issue on GitHub – I’m happy to add them! 216 | 217 | If you need to localize the names of your apps or any other passed text, you can use `String(localized:)` as usual in your app. 218 | 219 | 220 | ## Showcase 221 | 222 | I extracted this library from my following Indie apps (rate them with 5 stars to support me!): 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 236 | 243 | 244 | 245 | 246 | 251 | 258 | 259 | 260 | 261 | 266 | 273 | 274 | 275 | 276 | 281 | 288 | 289 | 290 | 291 | 296 | 303 | 304 | 305 | 306 | 311 | 318 | 319 | 320 | 321 | 326 | 333 | 334 | 335 | 336 | 341 | 348 | 349 | 350 |
App IconApp Name & DescriptionSupported Platforms
232 | 233 | 234 | 235 | 237 | 238 | TranslateKit: App Localizer 239 | 240 |
241 | Simple drag & drop translation of String Catalog files with support for multiple translation services & smart correctness checks. 242 |
Mac
247 | 248 | 249 | 250 | 252 | 253 | Pleydia Organizer: Movie & Series Renamer 254 | 255 |
256 | Simple, fast, and smart media management for your Movie, TV Show and Anime collection. 257 |
Mac
262 | 263 | 264 | 265 | 267 | 268 | FreemiumKit: In-App Purchases 269 | 270 |
271 | Simple In-App Purchases and Subscriptions for Apple Platforms: Automation, Paywalls, A/B Testing, Live Notifications, PPP, and more. 272 |
iPhone, iPad, Mac, Vision
277 | 278 | 279 | 280 | 282 | 283 | FreelanceKit: Time Tracking 284 | 285 |
286 | Simple & affordable time tracking with a native experience for all  devices. iCloud sync & CSV export included. 287 |
iPhone, iPad, Mac, Vision
292 | 293 | 294 | 295 | 297 | 298 | CrossCraft: Custom Crosswords 299 | 300 |
301 | Create themed & personalized crosswords. Solve them yourself or share them to challenge others. 302 |
iPhone, iPad, Mac, Vision
307 | 308 | 309 | 310 | 312 | 313 | FocusBeats: Pomodoro + Music 314 | 315 |
316 | Deep Focus with proven Pomodoro method & select Apple Music playlists & themes. Automatically pauses music during breaks. 317 |
iPhone, iPad, Mac, Vision
322 | 323 | 324 | 325 | 327 | 328 | Guided Guest Mode 329 | 330 |
331 | Showcase Apple Vision Pro effortlessly to friends & family. Customizable, easy-to-use guides for everyone! 332 |
Vision
337 | 338 | 339 | 340 | 342 | 343 | Posters: Discover Movies at Home 344 | 345 |
346 | Auto-updating & interactive posters for your home with trailers, showtimes, and links to streaming services. 347 |
Vision
351 | -------------------------------------------------------------------------------- /Sources/LinksKit/LinksKit.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// The wrapper to configure LinksKit. 4 | public actor LinksKit { 5 | static var providerToken: String = "" 6 | static var linkSections: [LinkSection] = [] 7 | 8 | /// The main configuration method to be called upon app start to confure the contents of ``LinksView`` for use in settings/help menu. 9 | /// 10 | /// - Parameters: 11 | /// - providerToken: The `pt` query parameter of your app's campaign link. Same for all your apps, thus provided here on top level. 12 | /// - linkSections: The separate link sections you want to auto-render. Use one of the convenience helpers `.helpLinks`, `.socialMenus`, `.appMenus`, `.legalLinks`, or pass a custom ``LegalSection`` with the links/menus of your choice. 13 | public static func configure(providerToken: String, linkSections: [LinkSection]) { 14 | self.providerToken = providerToken 15 | self.linkSections = linkSections 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Sources/LinksKit/Localizable.xcstrings: -------------------------------------------------------------------------------- 1 | { 2 | "sourceLanguage" : "en", 3 | "strings" : { 4 | "App Links" : { 5 | "localizations" : { 6 | "ar" : { 7 | "stringUnit" : { 8 | "state" : "translated", 9 | "value" : "روابط التطبيق" 10 | } 11 | }, 12 | "bg" : { 13 | "stringUnit" : { 14 | "state" : "translated", 15 | "value" : "Връзки с приложения" 16 | } 17 | }, 18 | "ca" : { 19 | "stringUnit" : { 20 | "state" : "translated", 21 | "value" : "Enllaços d'aplicacions" 22 | } 23 | }, 24 | "cs" : { 25 | "stringUnit" : { 26 | "state" : "translated", 27 | "value" : "Odkazy na aplikace" 28 | } 29 | }, 30 | "da" : { 31 | "stringUnit" : { 32 | "state" : "translated", 33 | "value" : "App-links" 34 | } 35 | }, 36 | "de" : { 37 | "stringUnit" : { 38 | "state" : "translated", 39 | "value" : "App Links" 40 | } 41 | }, 42 | "el" : { 43 | "stringUnit" : { 44 | "state" : "translated", 45 | "value" : "Σύνδεσμοι εφαρμογών" 46 | } 47 | }, 48 | "en-GB" : { 49 | "stringUnit" : { 50 | "state" : "translated", 51 | "value" : "App Links" 52 | } 53 | }, 54 | "es" : { 55 | "stringUnit" : { 56 | "state" : "translated", 57 | "value" : "Enlaces App" 58 | } 59 | }, 60 | "fi" : { 61 | "stringUnit" : { 62 | "state" : "translated", 63 | "value" : "Sovelluslinkit" 64 | } 65 | }, 66 | "fr" : { 67 | "stringUnit" : { 68 | "state" : "translated", 69 | "value" : "Liens de l'application" 70 | } 71 | }, 72 | "fr-CA" : { 73 | "stringUnit" : { 74 | "state" : "translated", 75 | "value" : "Liens vers l’application" 76 | } 77 | }, 78 | "he" : { 79 | "stringUnit" : { 80 | "state" : "translated", 81 | "value" : "קישורים לאפליקציות" 82 | } 83 | }, 84 | "hi" : { 85 | "stringUnit" : { 86 | "state" : "translated", 87 | "value" : "ऐप लिंक" 88 | } 89 | }, 90 | "hr" : { 91 | "stringUnit" : { 92 | "state" : "translated", 93 | "value" : "Veze na aplikacije" 94 | } 95 | }, 96 | "hu" : { 97 | "stringUnit" : { 98 | "state" : "translated", 99 | "value" : "App Linkek" 100 | } 101 | }, 102 | "id" : { 103 | "stringUnit" : { 104 | "state" : "translated", 105 | "value" : "Tautan Aplikasi" 106 | } 107 | }, 108 | "it" : { 109 | "stringUnit" : { 110 | "state" : "translated", 111 | "value" : "Link alle app" 112 | } 113 | }, 114 | "ja" : { 115 | "stringUnit" : { 116 | "state" : "translated", 117 | "value" : "アプリリンク" 118 | } 119 | }, 120 | "kk" : { 121 | "stringUnit" : { 122 | "state" : "translated", 123 | "value" : "Бағдарлама сілтемелері" 124 | } 125 | }, 126 | "ko" : { 127 | "stringUnit" : { 128 | "state" : "translated", 129 | "value" : "앱 링크" 130 | } 131 | }, 132 | "ms" : { 133 | "stringUnit" : { 134 | "state" : "translated", 135 | "value" : "Pautan Apl" 136 | } 137 | }, 138 | "nl" : { 139 | "stringUnit" : { 140 | "state" : "translated", 141 | "value" : "App koppelingen" 142 | } 143 | }, 144 | "pl" : { 145 | "stringUnit" : { 146 | "state" : "translated", 147 | "value" : "Linki do aplikacji" 148 | } 149 | }, 150 | "pt-BR" : { 151 | "stringUnit" : { 152 | "state" : "translated", 153 | "value" : "Links de aplicativos" 154 | } 155 | }, 156 | "pt-PT" : { 157 | "stringUnit" : { 158 | "state" : "translated", 159 | "value" : "Ligações da aplicação" 160 | } 161 | }, 162 | "ro" : { 163 | "stringUnit" : { 164 | "state" : "translated", 165 | "value" : "Legături aplicații" 166 | } 167 | }, 168 | "ru" : { 169 | "stringUnit" : { 170 | "state" : "translated", 171 | "value" : "Ссылки на приложения" 172 | } 173 | }, 174 | "sk" : { 175 | "stringUnit" : { 176 | "state" : "translated", 177 | "value" : "Odkazy na aplikácie" 178 | } 179 | }, 180 | "sv" : { 181 | "stringUnit" : { 182 | "state" : "translated", 183 | "value" : "Länkar till appen" 184 | } 185 | }, 186 | "th" : { 187 | "stringUnit" : { 188 | "state" : "translated", 189 | "value" : "ลิงค์แอป" 190 | } 191 | }, 192 | "tr" : { 193 | "stringUnit" : { 194 | "state" : "translated", 195 | "value" : "Uygulama Bağlantıları" 196 | } 197 | }, 198 | "uk" : { 199 | "stringUnit" : { 200 | "state" : "translated", 201 | "value" : "Посилання на додаток" 202 | } 203 | }, 204 | "vi" : { 205 | "stringUnit" : { 206 | "state" : "translated", 207 | "value" : "Liên kết ứng dụng" 208 | } 209 | }, 210 | "zh-Hans" : { 211 | "stringUnit" : { 212 | "state" : "translated", 213 | "value" : "应用程序链接" 214 | } 215 | }, 216 | "zh-Hant" : { 217 | "stringUnit" : { 218 | "state" : "translated", 219 | "value" : "應用連結" 220 | } 221 | }, 222 | "zh-HK" : { 223 | "stringUnit" : { 224 | "state" : "translated", 225 | "value" : "應用連結" 226 | } 227 | } 228 | } 229 | }, 230 | "App on %@" : { 231 | "localizations" : { 232 | "ar" : { 233 | "stringUnit" : { 234 | "state" : "translated", 235 | "value" : "التطبيق على %@" 236 | } 237 | }, 238 | "bg" : { 239 | "stringUnit" : { 240 | "state" : "translated", 241 | "value" : "Приложение на %@" 242 | } 243 | }, 244 | "ca" : { 245 | "stringUnit" : { 246 | "state" : "translated", 247 | "value" : "App on %@" 248 | } 249 | }, 250 | "cs" : { 251 | "stringUnit" : { 252 | "state" : "translated", 253 | "value" : "Aplikace na %@" 254 | } 255 | }, 256 | "da" : { 257 | "stringUnit" : { 258 | "state" : "translated", 259 | "value" : "App på %@" 260 | } 261 | }, 262 | "de" : { 263 | "stringUnit" : { 264 | "state" : "translated", 265 | "value" : "App auf %@" 266 | } 267 | }, 268 | "el" : { 269 | "stringUnit" : { 270 | "state" : "translated", 271 | "value" : "Εφαρμογή στο %@" 272 | } 273 | }, 274 | "en-GB" : { 275 | "stringUnit" : { 276 | "state" : "translated", 277 | "value" : "App on %@" 278 | } 279 | }, 280 | "es" : { 281 | "stringUnit" : { 282 | "state" : "translated", 283 | "value" : "Aplicación en %@" 284 | } 285 | }, 286 | "fi" : { 287 | "stringUnit" : { 288 | "state" : "translated", 289 | "value" : "Sovellus %@" 290 | } 291 | }, 292 | "fr" : { 293 | "stringUnit" : { 294 | "state" : "translated", 295 | "value" : "App sur %@" 296 | } 297 | }, 298 | "fr-CA" : { 299 | "stringUnit" : { 300 | "state" : "translated", 301 | "value" : "App sur %@" 302 | } 303 | }, 304 | "he" : { 305 | "stringUnit" : { 306 | "state" : "translated", 307 | "value" : "אפליקציה ב- %@" 308 | } 309 | }, 310 | "hi" : { 311 | "stringUnit" : { 312 | "state" : "translated", 313 | "value" : "%@ पर अनुप्रयोग" 314 | } 315 | }, 316 | "hr" : { 317 | "stringUnit" : { 318 | "state" : "translated", 319 | "value" : "Aplikacija na %@" 320 | } 321 | }, 322 | "hu" : { 323 | "stringUnit" : { 324 | "state" : "translated", 325 | "value" : "App on %@" 326 | } 327 | }, 328 | "id" : { 329 | "stringUnit" : { 330 | "state" : "translated", 331 | "value" : "Aplikasi pada %@" 332 | } 333 | }, 334 | "it" : { 335 | "stringUnit" : { 336 | "state" : "translated", 337 | "value" : "App su %@" 338 | } 339 | }, 340 | "ja" : { 341 | "stringUnit" : { 342 | "state" : "translated", 343 | "value" : "%@のアプリ" 344 | } 345 | }, 346 | "kk" : { 347 | "stringUnit" : { 348 | "state" : "translated", 349 | "value" : "%@ бағдарламасы" 350 | } 351 | }, 352 | "ko" : { 353 | "stringUnit" : { 354 | "state" : "translated", 355 | "value" : "%@의 앱" 356 | } 357 | }, 358 | "ms" : { 359 | "stringUnit" : { 360 | "state" : "translated", 361 | "value" : "App on %@" 362 | } 363 | }, 364 | "nl" : { 365 | "stringUnit" : { 366 | "state" : "translated", 367 | "value" : "App op %@" 368 | } 369 | }, 370 | "pl" : { 371 | "stringUnit" : { 372 | "state" : "translated", 373 | "value" : "Aplikacja na %@" 374 | } 375 | }, 376 | "pt-BR" : { 377 | "stringUnit" : { 378 | "state" : "translated", 379 | "value" : "Aplicativo em %@" 380 | } 381 | }, 382 | "pt-PT" : { 383 | "stringUnit" : { 384 | "state" : "translated", 385 | "value" : "Aplica-te em %@" 386 | } 387 | }, 388 | "ro" : { 389 | "stringUnit" : { 390 | "state" : "translated", 391 | "value" : "Aplicație pe %@" 392 | } 393 | }, 394 | "ru" : { 395 | "stringUnit" : { 396 | "state" : "translated", 397 | "value" : "Приложение на %@" 398 | } 399 | }, 400 | "sk" : { 401 | "stringUnit" : { 402 | "state" : "translated", 403 | "value" : "Aplikácia na %@" 404 | } 405 | }, 406 | "sv" : { 407 | "stringUnit" : { 408 | "state" : "translated", 409 | "value" : "App på %@" 410 | } 411 | }, 412 | "th" : { 413 | "stringUnit" : { 414 | "state" : "translated", 415 | "value" : "App on %@" 416 | } 417 | }, 418 | "tr" : { 419 | "stringUnit" : { 420 | "state" : "translated", 421 | "value" : "Uygulama %@ üzerinde" 422 | } 423 | }, 424 | "uk" : { 425 | "stringUnit" : { 426 | "state" : "translated", 427 | "value" : "Додаток на %@" 428 | } 429 | }, 430 | "vi" : { 431 | "stringUnit" : { 432 | "state" : "translated", 433 | "value" : "Ứng dụng trên %@" 434 | } 435 | }, 436 | "zh-Hans" : { 437 | "stringUnit" : { 438 | "state" : "translated", 439 | "value" : "%@上的应用程序" 440 | } 441 | }, 442 | "zh-Hant" : { 443 | "stringUnit" : { 444 | "state" : "translated", 445 | "value" : "%@ 上的應用程式" 446 | } 447 | }, 448 | "zh-HK" : { 449 | "stringUnit" : { 450 | "state" : "translated", 451 | "value" : "%@上嘅應用程序" 452 | } 453 | } 454 | } 455 | }, 456 | "Apps from Friends" : { 457 | "localizations" : { 458 | "ar" : { 459 | "stringUnit" : { 460 | "state" : "translated", 461 | "value" : "تطبيقات من الأصدقاء" 462 | } 463 | }, 464 | "bg" : { 465 | "stringUnit" : { 466 | "state" : "translated", 467 | "value" : "Приложения от приятели" 468 | } 469 | }, 470 | "ca" : { 471 | "stringUnit" : { 472 | "state" : "translated", 473 | "value" : "Aplicacions d'amics" 474 | } 475 | }, 476 | "cs" : { 477 | "stringUnit" : { 478 | "state" : "translated", 479 | "value" : "Aplikace od přátel" 480 | } 481 | }, 482 | "da" : { 483 | "stringUnit" : { 484 | "state" : "translated", 485 | "value" : "Apps fra venner" 486 | } 487 | }, 488 | "de" : { 489 | "stringUnit" : { 490 | "state" : "translated", 491 | "value" : "Apps von Freunden" 492 | } 493 | }, 494 | "el" : { 495 | "stringUnit" : { 496 | "state" : "translated", 497 | "value" : "Εφαρμογές από φίλους" 498 | } 499 | }, 500 | "en-GB" : { 501 | "stringUnit" : { 502 | "state" : "translated", 503 | "value" : "Apps from Friends" 504 | } 505 | }, 506 | "es" : { 507 | "stringUnit" : { 508 | "state" : "translated", 509 | "value" : "Aplicaciones de amigos" 510 | } 511 | }, 512 | "fi" : { 513 | "stringUnit" : { 514 | "state" : "translated", 515 | "value" : "Sovellukset ystäviltä" 516 | } 517 | }, 518 | "fr" : { 519 | "stringUnit" : { 520 | "state" : "translated", 521 | "value" : "Applications d'amis" 522 | } 523 | }, 524 | "fr-CA" : { 525 | "stringUnit" : { 526 | "state" : "translated", 527 | "value" : "Applications d’amis" 528 | } 529 | }, 530 | "he" : { 531 | "stringUnit" : { 532 | "state" : "translated", 533 | "value" : "אפליקציות מחברים" 534 | } 535 | }, 536 | "hi" : { 537 | "stringUnit" : { 538 | "state" : "translated", 539 | "value" : "दोस्तों से ऐप्स" 540 | } 541 | }, 542 | "hr" : { 543 | "stringUnit" : { 544 | "state" : "translated", 545 | "value" : "Aplikacije prijatelja" 546 | } 547 | }, 548 | "hu" : { 549 | "stringUnit" : { 550 | "state" : "translated", 551 | "value" : "Alkalmazások barátoktól" 552 | } 553 | }, 554 | "id" : { 555 | "stringUnit" : { 556 | "state" : "translated", 557 | "value" : "Aplikasi dari Teman" 558 | } 559 | }, 560 | "it" : { 561 | "stringUnit" : { 562 | "state" : "translated", 563 | "value" : "Applicazioni di amici" 564 | } 565 | }, 566 | "ja" : { 567 | "stringUnit" : { 568 | "state" : "translated", 569 | "value" : "友人からのアプリ" 570 | } 571 | }, 572 | "kk" : { 573 | "stringUnit" : { 574 | "state" : "translated", 575 | "value" : "Достардан бағдарламалар" 576 | } 577 | }, 578 | "ko" : { 579 | "stringUnit" : { 580 | "state" : "translated", 581 | "value" : "친구의 앱" 582 | } 583 | }, 584 | "ms" : { 585 | "stringUnit" : { 586 | "state" : "translated", 587 | "value" : "Apl daripada Rakan" 588 | } 589 | }, 590 | "nl" : { 591 | "stringUnit" : { 592 | "state" : "translated", 593 | "value" : "Apps van vrienden" 594 | } 595 | }, 596 | "pl" : { 597 | "stringUnit" : { 598 | "state" : "translated", 599 | "value" : "Aplikacje od znajomych" 600 | } 601 | }, 602 | "pt-BR" : { 603 | "stringUnit" : { 604 | "state" : "translated", 605 | "value" : "Aplicativos de amigos" 606 | } 607 | }, 608 | "pt-PT" : { 609 | "stringUnit" : { 610 | "state" : "translated", 611 | "value" : "Aplicações de amigos" 612 | } 613 | }, 614 | "ro" : { 615 | "stringUnit" : { 616 | "state" : "translated", 617 | "value" : "Aplicații de la prieteni" 618 | } 619 | }, 620 | "ru" : { 621 | "stringUnit" : { 622 | "state" : "translated", 623 | "value" : "Приложения от друзей" 624 | } 625 | }, 626 | "sk" : { 627 | "stringUnit" : { 628 | "state" : "translated", 629 | "value" : "Aplikácie od priateľov" 630 | } 631 | }, 632 | "sv" : { 633 | "stringUnit" : { 634 | "state" : "translated", 635 | "value" : "Appar från vänner" 636 | } 637 | }, 638 | "th" : { 639 | "stringUnit" : { 640 | "state" : "translated", 641 | "value" : "แอพจากเพื่อน" 642 | } 643 | }, 644 | "tr" : { 645 | "stringUnit" : { 646 | "state" : "translated", 647 | "value" : "Arkadaşlardan Uygulamalar" 648 | } 649 | }, 650 | "uk" : { 651 | "stringUnit" : { 652 | "state" : "translated", 653 | "value" : "Додатки від друзів" 654 | } 655 | }, 656 | "vi" : { 657 | "stringUnit" : { 658 | "state" : "translated", 659 | "value" : "Ứng dụng từ Friends" 660 | } 661 | }, 662 | "zh-Hans" : { 663 | "stringUnit" : { 664 | "state" : "translated", 665 | "value" : "朋友提供的应用程序" 666 | } 667 | }, 668 | "zh-Hant" : { 669 | "stringUnit" : { 670 | "state" : "translated", 671 | "value" : "好友的應用程式" 672 | } 673 | }, 674 | "zh-HK" : { 675 | "stringUnit" : { 676 | "state" : "translated", 677 | "value" : "好友嘅應用程序" 678 | } 679 | } 680 | } 681 | }, 682 | "Contact Support" : { 683 | "localizations" : { 684 | "ar" : { 685 | "stringUnit" : { 686 | "state" : "translated", 687 | "value" : "التواصل مع الدعم" 688 | } 689 | }, 690 | "bg" : { 691 | "stringUnit" : { 692 | "state" : "translated", 693 | "value" : "Свържете се с Поддръжка" 694 | } 695 | }, 696 | "ca" : { 697 | "stringUnit" : { 698 | "state" : "translated", 699 | "value" : "Contactar amb el servei de suport" 700 | } 701 | }, 702 | "cs" : { 703 | "stringUnit" : { 704 | "state" : "translated", 705 | "value" : "Kontaktovat podporu" 706 | } 707 | }, 708 | "da" : { 709 | "stringUnit" : { 710 | "state" : "translated", 711 | "value" : "Kontakt support" 712 | } 713 | }, 714 | "de" : { 715 | "stringUnit" : { 716 | "state" : "translated", 717 | "value" : "Support kontaktieren" 718 | } 719 | }, 720 | "el" : { 721 | "stringUnit" : { 722 | "state" : "translated", 723 | "value" : "Επικοινωνία με την Υποστήριξη" 724 | } 725 | }, 726 | "en-GB" : { 727 | "stringUnit" : { 728 | "state" : "translated", 729 | "value" : "Contact Support" 730 | } 731 | }, 732 | "es" : { 733 | "stringUnit" : { 734 | "state" : "translated", 735 | "value" : "Contactar con el servicio de soporte" 736 | } 737 | }, 738 | "fi" : { 739 | "stringUnit" : { 740 | "state" : "translated", 741 | "value" : "Ota yhteyttä tukeen" 742 | } 743 | }, 744 | "fr" : { 745 | "stringUnit" : { 746 | "state" : "translated", 747 | "value" : "Contacter l’assistance" 748 | } 749 | }, 750 | "fr-CA" : { 751 | "stringUnit" : { 752 | "state" : "translated", 753 | "value" : "Communiquer avec le service d’assistance" 754 | } 755 | }, 756 | "he" : { 757 | "stringUnit" : { 758 | "state" : "translated", 759 | "value" : "פנייה לתמיכה" 760 | } 761 | }, 762 | "hi" : { 763 | "stringUnit" : { 764 | "state" : "translated", 765 | "value" : "सहायता से संपर्क करें" 766 | } 767 | }, 768 | "hr" : { 769 | "stringUnit" : { 770 | "state" : "translated", 771 | "value" : "Obratite se korisničkoj podršci" 772 | } 773 | }, 774 | "hu" : { 775 | "stringUnit" : { 776 | "state" : "translated", 777 | "value" : "Kapcsolatfelvétel a Támogatással" 778 | } 779 | }, 780 | "id" : { 781 | "stringUnit" : { 782 | "state" : "translated", 783 | "value" : "Hubungi Dukungan" 784 | } 785 | }, 786 | "it" : { 787 | "stringUnit" : { 788 | "state" : "translated", 789 | "value" : "Contatta l'assistenza" 790 | } 791 | }, 792 | "ja" : { 793 | "stringUnit" : { 794 | "state" : "translated", 795 | "value" : "サポートに問い合わせ" 796 | } 797 | }, 798 | "kk" : { 799 | "stringUnit" : { 800 | "state" : "translated", 801 | "value" : "Қолдау көрсету сервисіне хабарласу" 802 | } 803 | }, 804 | "ko" : { 805 | "stringUnit" : { 806 | "state" : "translated", 807 | "value" : "지원팀에 문의" 808 | } 809 | }, 810 | "ms" : { 811 | "stringUnit" : { 812 | "state" : "translated", 813 | "value" : "Hubungi Sokongan" 814 | } 815 | }, 816 | "nl" : { 817 | "stringUnit" : { 818 | "state" : "translated", 819 | "value" : "Neem contact op met ondersteuning" 820 | } 821 | }, 822 | "pl" : { 823 | "stringUnit" : { 824 | "state" : "translated", 825 | "value" : "Skontaktuj się z działem wsparcia" 826 | } 827 | }, 828 | "pt-BR" : { 829 | "stringUnit" : { 830 | "state" : "translated", 831 | "value" : "Contatar o Suporte" 832 | } 833 | }, 834 | "pt-PT" : { 835 | "stringUnit" : { 836 | "state" : "translated", 837 | "value" : "Contactar suporte" 838 | } 839 | }, 840 | "ro" : { 841 | "stringUnit" : { 842 | "state" : "translated", 843 | "value" : "Contactați asistența" 844 | } 845 | }, 846 | "ru" : { 847 | "stringUnit" : { 848 | "state" : "translated", 849 | "value" : "Служба поддержки" 850 | } 851 | }, 852 | "sk" : { 853 | "stringUnit" : { 854 | "state" : "translated", 855 | "value" : "Kontaktovať podporu" 856 | } 857 | }, 858 | "sv" : { 859 | "stringUnit" : { 860 | "state" : "translated", 861 | "value" : "Kontakta supporten" 862 | } 863 | }, 864 | "th" : { 865 | "stringUnit" : { 866 | "state" : "translated", 867 | "value" : "ติดต่อบริการช่วยเหลือ" 868 | } 869 | }, 870 | "tr" : { 871 | "stringUnit" : { 872 | "state" : "translated", 873 | "value" : "Destek ile İletişim Kurun" 874 | } 875 | }, 876 | "uk" : { 877 | "stringUnit" : { 878 | "state" : "translated", 879 | "value" : "Звернутися до Служби підтримки" 880 | } 881 | }, 882 | "vi" : { 883 | "stringUnit" : { 884 | "state" : "translated", 885 | "value" : "Liên hệ hỗ trợ" 886 | } 887 | }, 888 | "zh-Hans" : { 889 | "stringUnit" : { 890 | "state" : "translated", 891 | "value" : "联系支持" 892 | } 893 | }, 894 | "zh-Hant" : { 895 | "stringUnit" : { 896 | "state" : "translated", 897 | "value" : "聯絡支援服務" 898 | } 899 | }, 900 | "zh-HK" : { 901 | "stringUnit" : { 902 | "state" : "translated", 903 | "value" : "聯絡支援" 904 | } 905 | } 906 | } 907 | }, 908 | "Developer on %@" : { 909 | "localizations" : { 910 | "ar" : { 911 | "stringUnit" : { 912 | "state" : "translated", 913 | "value" : "المطور على %@" 914 | } 915 | }, 916 | "bg" : { 917 | "stringUnit" : { 918 | "state" : "translated", 919 | "value" : "Разработчик на %@" 920 | } 921 | }, 922 | "ca" : { 923 | "stringUnit" : { 924 | "state" : "translated", 925 | "value" : "Desenvolupador a %@" 926 | } 927 | }, 928 | "cs" : { 929 | "stringUnit" : { 930 | "state" : "translated", 931 | "value" : "Vývojář na %@" 932 | } 933 | }, 934 | "da" : { 935 | "stringUnit" : { 936 | "state" : "translated", 937 | "value" : "Udvikler på %@" 938 | } 939 | }, 940 | "de" : { 941 | "stringUnit" : { 942 | "state" : "translated", 943 | "value" : "Entwickler auf %@" 944 | } 945 | }, 946 | "el" : { 947 | "stringUnit" : { 948 | "state" : "translated", 949 | "value" : "Προγραμματιστής στο %@" 950 | } 951 | }, 952 | "en-GB" : { 953 | "stringUnit" : { 954 | "state" : "translated", 955 | "value" : "Developer on %@" 956 | } 957 | }, 958 | "es" : { 959 | "stringUnit" : { 960 | "state" : "translated", 961 | "value" : "Desarrollador en %@" 962 | } 963 | }, 964 | "fi" : { 965 | "stringUnit" : { 966 | "state" : "translated", 967 | "value" : "Kehittäjä %@" 968 | } 969 | }, 970 | "fr" : { 971 | "stringUnit" : { 972 | "state" : "translated", 973 | "value" : "Développeur sur %@" 974 | } 975 | }, 976 | "fr-CA" : { 977 | "stringUnit" : { 978 | "state" : "translated", 979 | "value" : "Développeur sur %@" 980 | } 981 | }, 982 | "he" : { 983 | "stringUnit" : { 984 | "state" : "translated", 985 | "value" : "מפתח ב- %@" 986 | } 987 | }, 988 | "hi" : { 989 | "stringUnit" : { 990 | "state" : "translated", 991 | "value" : "%@ पर डेवलपर" 992 | } 993 | }, 994 | "hr" : { 995 | "stringUnit" : { 996 | "state" : "translated", 997 | "value" : "Razvojni programer na %@" 998 | } 999 | }, 1000 | "hu" : { 1001 | "stringUnit" : { 1002 | "state" : "translated", 1003 | "value" : "Fejlesztő a %@" 1004 | } 1005 | }, 1006 | "id" : { 1007 | "stringUnit" : { 1008 | "state" : "translated", 1009 | "value" : "Pengembang pada %@" 1010 | } 1011 | }, 1012 | "it" : { 1013 | "stringUnit" : { 1014 | "state" : "translated", 1015 | "value" : "Sviluppatore su %@" 1016 | } 1017 | }, 1018 | "ja" : { 1019 | "stringUnit" : { 1020 | "state" : "translated", 1021 | "value" : "%@の開発者" 1022 | } 1023 | }, 1024 | "kk" : { 1025 | "stringUnit" : { 1026 | "state" : "translated", 1027 | "value" : "%@ сайтында әзірлеуші" 1028 | } 1029 | }, 1030 | "ko" : { 1031 | "stringUnit" : { 1032 | "state" : "translated", 1033 | "value" : "%@의 개발자" 1034 | } 1035 | }, 1036 | "ms" : { 1037 | "stringUnit" : { 1038 | "state" : "translated", 1039 | "value" : "Developer on %@" 1040 | } 1041 | }, 1042 | "nl" : { 1043 | "stringUnit" : { 1044 | "state" : "translated", 1045 | "value" : "Ontwikkelaar op %@" 1046 | } 1047 | }, 1048 | "pl" : { 1049 | "stringUnit" : { 1050 | "state" : "translated", 1051 | "value" : "Deweloper na %@" 1052 | } 1053 | }, 1054 | "pt-BR" : { 1055 | "stringUnit" : { 1056 | "state" : "translated", 1057 | "value" : "Desenvolvedor em %@" 1058 | } 1059 | }, 1060 | "pt-PT" : { 1061 | "stringUnit" : { 1062 | "state" : "translated", 1063 | "value" : "Desenvolve em %@" 1064 | } 1065 | }, 1066 | "ro" : { 1067 | "stringUnit" : { 1068 | "state" : "translated", 1069 | "value" : "Dezvoltator pe %@" 1070 | } 1071 | }, 1072 | "ru" : { 1073 | "stringUnit" : { 1074 | "state" : "translated", 1075 | "value" : "Разработчик на %@" 1076 | } 1077 | }, 1078 | "sk" : { 1079 | "stringUnit" : { 1080 | "state" : "translated", 1081 | "value" : "Vývojár na %@" 1082 | } 1083 | }, 1084 | "sv" : { 1085 | "stringUnit" : { 1086 | "state" : "translated", 1087 | "value" : "Utvecklare på %@" 1088 | } 1089 | }, 1090 | "th" : { 1091 | "stringUnit" : { 1092 | "state" : "translated", 1093 | "value" : "พัฒนาบน %@" 1094 | } 1095 | }, 1096 | "tr" : { 1097 | "stringUnit" : { 1098 | "state" : "translated", 1099 | "value" : "Geliştirici %@ üzerinde" 1100 | } 1101 | }, 1102 | "uk" : { 1103 | "stringUnit" : { 1104 | "state" : "translated", 1105 | "value" : "Розробник на %@" 1106 | } 1107 | }, 1108 | "vi" : { 1109 | "stringUnit" : { 1110 | "state" : "translated", 1111 | "value" : "Nhà phát triển trên %@" 1112 | } 1113 | }, 1114 | "zh-Hans" : { 1115 | "stringUnit" : { 1116 | "state" : "translated", 1117 | "value" : "%@上的开发人员" 1118 | } 1119 | }, 1120 | "zh-Hant" : { 1121 | "stringUnit" : { 1122 | "state" : "translated", 1123 | "value" : "%@ 上的開發人員" 1124 | } 1125 | }, 1126 | "zh-HK" : { 1127 | "stringUnit" : { 1128 | "state" : "translated", 1129 | "value" : "%@上嘅開發人員" 1130 | } 1131 | } 1132 | } 1133 | }, 1134 | "Follow the App" : { 1135 | "localizations" : { 1136 | "ar" : { 1137 | "stringUnit" : { 1138 | "state" : "translated", 1139 | "value" : "اتبع التطبيق" 1140 | } 1141 | }, 1142 | "bg" : { 1143 | "stringUnit" : { 1144 | "state" : "translated", 1145 | "value" : "Следвайте приложението" 1146 | } 1147 | }, 1148 | "ca" : { 1149 | "stringUnit" : { 1150 | "state" : "translated", 1151 | "value" : "Segueix l'App" 1152 | } 1153 | }, 1154 | "cs" : { 1155 | "stringUnit" : { 1156 | "state" : "translated", 1157 | "value" : "Sledování aplikace" 1158 | } 1159 | }, 1160 | "da" : { 1161 | "stringUnit" : { 1162 | "state" : "translated", 1163 | "value" : "Følg med i appen" 1164 | } 1165 | }, 1166 | "de" : { 1167 | "stringUnit" : { 1168 | "state" : "translated", 1169 | "value" : "Folge der App" 1170 | } 1171 | }, 1172 | "el" : { 1173 | "stringUnit" : { 1174 | "state" : "translated", 1175 | "value" : "Ακολουθήστε την εφαρμογή" 1176 | } 1177 | }, 1178 | "en-GB" : { 1179 | "stringUnit" : { 1180 | "state" : "translated", 1181 | "value" : "Follow the App" 1182 | } 1183 | }, 1184 | "es" : { 1185 | "stringUnit" : { 1186 | "state" : "translated", 1187 | "value" : "Sigue la App" 1188 | } 1189 | }, 1190 | "fi" : { 1191 | "stringUnit" : { 1192 | "state" : "translated", 1193 | "value" : "Seuraa sovellusta" 1194 | } 1195 | }, 1196 | "fr" : { 1197 | "stringUnit" : { 1198 | "state" : "translated", 1199 | "value" : "Suis l'application" 1200 | } 1201 | }, 1202 | "fr-CA" : { 1203 | "stringUnit" : { 1204 | "state" : "translated", 1205 | "value" : "Suivez l’application" 1206 | } 1207 | }, 1208 | "he" : { 1209 | "stringUnit" : { 1210 | "state" : "translated", 1211 | "value" : "עקוב אחר האפליקציה" 1212 | } 1213 | }, 1214 | "hi" : { 1215 | "stringUnit" : { 1216 | "state" : "translated", 1217 | "value" : "ऐप को फॉलो करें" 1218 | } 1219 | }, 1220 | "hr" : { 1221 | "stringUnit" : { 1222 | "state" : "translated", 1223 | "value" : "Pratite aplikaciju" 1224 | } 1225 | }, 1226 | "hu" : { 1227 | "stringUnit" : { 1228 | "state" : "translated", 1229 | "value" : "Kövesse az alkalmazást" 1230 | } 1231 | }, 1232 | "id" : { 1233 | "stringUnit" : { 1234 | "state" : "translated", 1235 | "value" : "Ikuti Aplikasi" 1236 | } 1237 | }, 1238 | "it" : { 1239 | "stringUnit" : { 1240 | "state" : "translated", 1241 | "value" : "Segui l'app" 1242 | } 1243 | }, 1244 | "ja" : { 1245 | "stringUnit" : { 1246 | "state" : "translated", 1247 | "value" : "アプリをフォローする" 1248 | } 1249 | }, 1250 | "kk" : { 1251 | "stringUnit" : { 1252 | "state" : "translated", 1253 | "value" : "Бағдарламаны бақылау" 1254 | } 1255 | }, 1256 | "ko" : { 1257 | "stringUnit" : { 1258 | "state" : "translated", 1259 | "value" : "앱 팔로우하기" 1260 | } 1261 | }, 1262 | "ms" : { 1263 | "stringUnit" : { 1264 | "state" : "translated", 1265 | "value" : "Ikut Aplikasi" 1266 | } 1267 | }, 1268 | "nl" : { 1269 | "stringUnit" : { 1270 | "state" : "translated", 1271 | "value" : "Volg de app" 1272 | } 1273 | }, 1274 | "pl" : { 1275 | "stringUnit" : { 1276 | "state" : "translated", 1277 | "value" : "Śledź aplikację" 1278 | } 1279 | }, 1280 | "pt-BR" : { 1281 | "stringUnit" : { 1282 | "state" : "translated", 1283 | "value" : "Siga o aplicativo" 1284 | } 1285 | }, 1286 | "pt-PT" : { 1287 | "stringUnit" : { 1288 | "state" : "translated", 1289 | "value" : "Segue a aplicação" 1290 | } 1291 | }, 1292 | "ro" : { 1293 | "stringUnit" : { 1294 | "state" : "translated", 1295 | "value" : "Urmăriți aplicația" 1296 | } 1297 | }, 1298 | "ru" : { 1299 | "stringUnit" : { 1300 | "state" : "translated", 1301 | "value" : "Следуй за приложением" 1302 | } 1303 | }, 1304 | "sk" : { 1305 | "stringUnit" : { 1306 | "state" : "translated", 1307 | "value" : "Sledovanie aplikácie" 1308 | } 1309 | }, 1310 | "sv" : { 1311 | "stringUnit" : { 1312 | "state" : "translated", 1313 | "value" : "Följ appen" 1314 | } 1315 | }, 1316 | "th" : { 1317 | "stringUnit" : { 1318 | "state" : "translated", 1319 | "value" : "ติดตามแอพ" 1320 | } 1321 | }, 1322 | "tr" : { 1323 | "stringUnit" : { 1324 | "state" : "translated", 1325 | "value" : "Uygulamayı Takip Edin" 1326 | } 1327 | }, 1328 | "uk" : { 1329 | "stringUnit" : { 1330 | "state" : "translated", 1331 | "value" : "Слідкуйте за додатком" 1332 | } 1333 | }, 1334 | "vi" : { 1335 | "stringUnit" : { 1336 | "state" : "translated", 1337 | "value" : "Theo dõi ứng dụng" 1338 | } 1339 | }, 1340 | "zh-Hans" : { 1341 | "stringUnit" : { 1342 | "state" : "translated", 1343 | "value" : "关注应用程序" 1344 | } 1345 | }, 1346 | "zh-Hant" : { 1347 | "stringUnit" : { 1348 | "state" : "translated", 1349 | "value" : "關注應用程式" 1350 | } 1351 | }, 1352 | "zh-HK" : { 1353 | "stringUnit" : { 1354 | "state" : "translated", 1355 | "value" : "關注應用程序" 1356 | } 1357 | } 1358 | } 1359 | }, 1360 | "Follow the Developer" : { 1361 | "localizations" : { 1362 | "ar" : { 1363 | "stringUnit" : { 1364 | "state" : "translated", 1365 | "value" : "اتبع المطور" 1366 | } 1367 | }, 1368 | "bg" : { 1369 | "stringUnit" : { 1370 | "state" : "translated", 1371 | "value" : "Следвайте разработчика" 1372 | } 1373 | }, 1374 | "ca" : { 1375 | "stringUnit" : { 1376 | "state" : "translated", 1377 | "value" : "Segueix el desenvolupador" 1378 | } 1379 | }, 1380 | "cs" : { 1381 | "stringUnit" : { 1382 | "state" : "translated", 1383 | "value" : "Sledujte vývojáře" 1384 | } 1385 | }, 1386 | "da" : { 1387 | "stringUnit" : { 1388 | "state" : "translated", 1389 | "value" : "Følg udvikleren" 1390 | } 1391 | }, 1392 | "de" : { 1393 | "stringUnit" : { 1394 | "state" : "translated", 1395 | "value" : "Folge dem Entwickler" 1396 | } 1397 | }, 1398 | "el" : { 1399 | "stringUnit" : { 1400 | "state" : "translated", 1401 | "value" : "Ακολουθήστε τον προγραμματιστή" 1402 | } 1403 | }, 1404 | "en-GB" : { 1405 | "stringUnit" : { 1406 | "state" : "translated", 1407 | "value" : "Follow the Developer" 1408 | } 1409 | }, 1410 | "es" : { 1411 | "stringUnit" : { 1412 | "state" : "translated", 1413 | "value" : "Sigue al Desarrollador" 1414 | } 1415 | }, 1416 | "fi" : { 1417 | "stringUnit" : { 1418 | "state" : "translated", 1419 | "value" : "Seuraa kehittäjää" 1420 | } 1421 | }, 1422 | "fr" : { 1423 | "stringUnit" : { 1424 | "state" : "translated", 1425 | "value" : "Suis le développeur" 1426 | } 1427 | }, 1428 | "fr-CA" : { 1429 | "stringUnit" : { 1430 | "state" : "translated", 1431 | "value" : "Suivez le développeur" 1432 | } 1433 | }, 1434 | "he" : { 1435 | "stringUnit" : { 1436 | "state" : "translated", 1437 | "value" : "עקוב אחר המפתח" 1438 | } 1439 | }, 1440 | "hi" : { 1441 | "stringUnit" : { 1442 | "state" : "translated", 1443 | "value" : "डेवलपर का अनुसरण करें" 1444 | } 1445 | }, 1446 | "hr" : { 1447 | "stringUnit" : { 1448 | "state" : "translated", 1449 | "value" : "Pratite programera" 1450 | } 1451 | }, 1452 | "hu" : { 1453 | "stringUnit" : { 1454 | "state" : "translated", 1455 | "value" : "Kövesse a fejlesztőt" 1456 | } 1457 | }, 1458 | "id" : { 1459 | "stringUnit" : { 1460 | "state" : "translated", 1461 | "value" : "Ikuti Pengembang" 1462 | } 1463 | }, 1464 | "it" : { 1465 | "stringUnit" : { 1466 | "state" : "translated", 1467 | "value" : "Segui lo sviluppatore" 1468 | } 1469 | }, 1470 | "ja" : { 1471 | "stringUnit" : { 1472 | "state" : "translated", 1473 | "value" : "開発者をフォローする" 1474 | } 1475 | }, 1476 | "kk" : { 1477 | "stringUnit" : { 1478 | "state" : "translated", 1479 | "value" : "Әзірлеушіні бақылау" 1480 | } 1481 | }, 1482 | "ko" : { 1483 | "stringUnit" : { 1484 | "state" : "translated", 1485 | "value" : "개발자 팔로우" 1486 | } 1487 | }, 1488 | "ms" : { 1489 | "stringUnit" : { 1490 | "state" : "translated", 1491 | "value" : "Ikuti Pemaju" 1492 | } 1493 | }, 1494 | "nl" : { 1495 | "stringUnit" : { 1496 | "state" : "translated", 1497 | "value" : "Volg de ontwikkelaar" 1498 | } 1499 | }, 1500 | "pl" : { 1501 | "stringUnit" : { 1502 | "state" : "translated", 1503 | "value" : "Podążaj za deweloperem" 1504 | } 1505 | }, 1506 | "pt-BR" : { 1507 | "stringUnit" : { 1508 | "state" : "translated", 1509 | "value" : "Siga o desenvolvedor" 1510 | } 1511 | }, 1512 | "pt-PT" : { 1513 | "stringUnit" : { 1514 | "state" : "translated", 1515 | "value" : "Segue o programador" 1516 | } 1517 | }, 1518 | "ro" : { 1519 | "stringUnit" : { 1520 | "state" : "translated", 1521 | "value" : "Urmăriți dezvoltatorul" 1522 | } 1523 | }, 1524 | "ru" : { 1525 | "stringUnit" : { 1526 | "state" : "translated", 1527 | "value" : "Следуй за разработчиком" 1528 | } 1529 | }, 1530 | "sk" : { 1531 | "stringUnit" : { 1532 | "state" : "translated", 1533 | "value" : "Sledujte vývojára" 1534 | } 1535 | }, 1536 | "sv" : { 1537 | "stringUnit" : { 1538 | "state" : "translated", 1539 | "value" : "Följ utvecklaren" 1540 | } 1541 | }, 1542 | "th" : { 1543 | "stringUnit" : { 1544 | "state" : "translated", 1545 | "value" : "ติดตามผู้พัฒนา" 1546 | } 1547 | }, 1548 | "tr" : { 1549 | "stringUnit" : { 1550 | "state" : "translated", 1551 | "value" : "Geliştiriciyi Takip Edin" 1552 | } 1553 | }, 1554 | "uk" : { 1555 | "stringUnit" : { 1556 | "state" : "translated", 1557 | "value" : "Слідкуйте за розробником" 1558 | } 1559 | }, 1560 | "vi" : { 1561 | "stringUnit" : { 1562 | "state" : "translated", 1563 | "value" : "Theo dõi nhà phát triển" 1564 | } 1565 | }, 1566 | "zh-Hans" : { 1567 | "stringUnit" : { 1568 | "state" : "translated", 1569 | "value" : "关注开发者" 1570 | } 1571 | }, 1572 | "zh-Hant" : { 1573 | "stringUnit" : { 1574 | "state" : "translated", 1575 | "value" : "關注開發者" 1576 | } 1577 | }, 1578 | "zh-HK" : { 1579 | "stringUnit" : { 1580 | "state" : "translated", 1581 | "value" : "關注開發者" 1582 | } 1583 | } 1584 | } 1585 | }, 1586 | "Follow us on %@" : { 1587 | "localizations" : { 1588 | "ar" : { 1589 | "stringUnit" : { 1590 | "state" : "translated", 1591 | "value" : "تابعنا على %@" 1592 | } 1593 | }, 1594 | "bg" : { 1595 | "stringUnit" : { 1596 | "state" : "translated", 1597 | "value" : "Следвайте ни в %@" 1598 | } 1599 | }, 1600 | "ca" : { 1601 | "stringUnit" : { 1602 | "state" : "translated", 1603 | "value" : "Segueix-nos a %@" 1604 | } 1605 | }, 1606 | "cs" : { 1607 | "stringUnit" : { 1608 | "state" : "translated", 1609 | "value" : "Sledujte nás na %@" 1610 | } 1611 | }, 1612 | "da" : { 1613 | "stringUnit" : { 1614 | "state" : "translated", 1615 | "value" : "Følg os på %@" 1616 | } 1617 | }, 1618 | "de" : { 1619 | "stringUnit" : { 1620 | "state" : "translated", 1621 | "value" : "Folge uns auf %@" 1622 | } 1623 | }, 1624 | "el" : { 1625 | "stringUnit" : { 1626 | "state" : "translated", 1627 | "value" : "Ακολουθήστε μας στο %@" 1628 | } 1629 | }, 1630 | "en-GB" : { 1631 | "stringUnit" : { 1632 | "state" : "translated", 1633 | "value" : "Follow us on %@" 1634 | } 1635 | }, 1636 | "es" : { 1637 | "stringUnit" : { 1638 | "state" : "translated", 1639 | "value" : "Síguenos en %@" 1640 | } 1641 | }, 1642 | "fi" : { 1643 | "stringUnit" : { 1644 | "state" : "translated", 1645 | "value" : "Seuraa meitä osoitteessa %@" 1646 | } 1647 | }, 1648 | "fr" : { 1649 | "stringUnit" : { 1650 | "state" : "translated", 1651 | "value" : "Suis-nous sur %@" 1652 | } 1653 | }, 1654 | "fr-CA" : { 1655 | "stringUnit" : { 1656 | "state" : "translated", 1657 | "value" : "Suivez-nous sur %@" 1658 | } 1659 | }, 1660 | "he" : { 1661 | "stringUnit" : { 1662 | "state" : "translated", 1663 | "value" : "עקבו אחרינו ב %@" 1664 | } 1665 | }, 1666 | "hi" : { 1667 | "stringUnit" : { 1668 | "state" : "translated", 1669 | "value" : "%@ पर हमारा अनुसरण करें" 1670 | } 1671 | }, 1672 | "hr" : { 1673 | "stringUnit" : { 1674 | "state" : "translated", 1675 | "value" : "Pratite nas na %@" 1676 | } 1677 | }, 1678 | "hu" : { 1679 | "stringUnit" : { 1680 | "state" : "translated", 1681 | "value" : "Kövessen minket a %@" 1682 | } 1683 | }, 1684 | "id" : { 1685 | "stringUnit" : { 1686 | "state" : "translated", 1687 | "value" : "Ikuti kami di %@" 1688 | } 1689 | }, 1690 | "it" : { 1691 | "stringUnit" : { 1692 | "state" : "translated", 1693 | "value" : "Seguici su %@" 1694 | } 1695 | }, 1696 | "ja" : { 1697 | "stringUnit" : { 1698 | "state" : "translated", 1699 | "value" : "%@でフォローする" 1700 | } 1701 | }, 1702 | "kk" : { 1703 | "stringUnit" : { 1704 | "state" : "translated", 1705 | "value" : "%@ сайтында бізді бақылаңыз" 1706 | } 1707 | }, 1708 | "ko" : { 1709 | "stringUnit" : { 1710 | "state" : "translated", 1711 | "value" : "%@에서 팔로우하세요" 1712 | } 1713 | }, 1714 | "ms" : { 1715 | "stringUnit" : { 1716 | "state" : "translated", 1717 | "value" : "Ikuti kami di %@" 1718 | } 1719 | }, 1720 | "nl" : { 1721 | "stringUnit" : { 1722 | "state" : "translated", 1723 | "value" : "Volg ons op %@" 1724 | } 1725 | }, 1726 | "pl" : { 1727 | "stringUnit" : { 1728 | "state" : "translated", 1729 | "value" : "Śledź nas na %@" 1730 | } 1731 | }, 1732 | "pt-BR" : { 1733 | "stringUnit" : { 1734 | "state" : "translated", 1735 | "value" : "Siga-nos em %@" 1736 | } 1737 | }, 1738 | "pt-PT" : { 1739 | "stringUnit" : { 1740 | "state" : "translated", 1741 | "value" : "Segue-nos em %@" 1742 | } 1743 | }, 1744 | "ro" : { 1745 | "stringUnit" : { 1746 | "state" : "translated", 1747 | "value" : "Urmăriți-ne pe %@" 1748 | } 1749 | }, 1750 | "ru" : { 1751 | "stringUnit" : { 1752 | "state" : "translated", 1753 | "value" : "Следи за нами на %@" 1754 | } 1755 | }, 1756 | "sk" : { 1757 | "stringUnit" : { 1758 | "state" : "translated", 1759 | "value" : "Sledujte nás na %@" 1760 | } 1761 | }, 1762 | "sv" : { 1763 | "stringUnit" : { 1764 | "state" : "translated", 1765 | "value" : "Följ oss på %@" 1766 | } 1767 | }, 1768 | "th" : { 1769 | "stringUnit" : { 1770 | "state" : "translated", 1771 | "value" : "ติดตามเราได้ที่ %@" 1772 | } 1773 | }, 1774 | "tr" : { 1775 | "stringUnit" : { 1776 | "state" : "translated", 1777 | "value" : "Bizi %@ adresinden takip edin" 1778 | } 1779 | }, 1780 | "uk" : { 1781 | "stringUnit" : { 1782 | "state" : "translated", 1783 | "value" : "Слідкуйте за нами на %@" 1784 | } 1785 | }, 1786 | "vi" : { 1787 | "stringUnit" : { 1788 | "state" : "translated", 1789 | "value" : "Theo dõi chúng tôi trên %@" 1790 | } 1791 | }, 1792 | "zh-Hans" : { 1793 | "stringUnit" : { 1794 | "state" : "translated", 1795 | "value" : "在 %@ 上关注我们" 1796 | } 1797 | }, 1798 | "zh-Hant" : { 1799 | "stringUnit" : { 1800 | "state" : "translated", 1801 | "value" : "在 %@ 上關注我們" 1802 | } 1803 | }, 1804 | "zh-HK" : { 1805 | "stringUnit" : { 1806 | "state" : "translated", 1807 | "value" : "在%@上關注我哋" 1808 | } 1809 | } 1810 | } 1811 | }, 1812 | "Frequently Asked Questions (FAQ)" : { 1813 | "localizations" : { 1814 | "ar" : { 1815 | "stringUnit" : { 1816 | "state" : "translated", 1817 | "value" : "الأسئلة المتكررة (FAQ)" 1818 | } 1819 | }, 1820 | "bg" : { 1821 | "stringUnit" : { 1822 | "state" : "translated", 1823 | "value" : "Често задавани въпроси (ЧЗВ)" 1824 | } 1825 | }, 1826 | "ca" : { 1827 | "stringUnit" : { 1828 | "state" : "translated", 1829 | "value" : "Preguntes freqüents (FAQ)" 1830 | } 1831 | }, 1832 | "cs" : { 1833 | "stringUnit" : { 1834 | "state" : "translated", 1835 | "value" : "Často kladené otázky (FAQ)" 1836 | } 1837 | }, 1838 | "da" : { 1839 | "stringUnit" : { 1840 | "state" : "translated", 1841 | "value" : "Ofte stillede spørgsmål (FAQ)" 1842 | } 1843 | }, 1844 | "de" : { 1845 | "stringUnit" : { 1846 | "state" : "translated", 1847 | "value" : "Häufig gestellte Fragen (FAQ)" 1848 | } 1849 | }, 1850 | "el" : { 1851 | "stringUnit" : { 1852 | "state" : "translated", 1853 | "value" : "Συχνές ερωτήσεις (FAQ)" 1854 | } 1855 | }, 1856 | "en-GB" : { 1857 | "stringUnit" : { 1858 | "state" : "translated", 1859 | "value" : "Frequently Asked Questions (FAQ)" 1860 | } 1861 | }, 1862 | "es" : { 1863 | "stringUnit" : { 1864 | "state" : "translated", 1865 | "value" : "Preguntas más frecuentes (FAQ)" 1866 | } 1867 | }, 1868 | "fi" : { 1869 | "stringUnit" : { 1870 | "state" : "translated", 1871 | "value" : "Usein kysytyt kysymykset (FAQ)" 1872 | } 1873 | }, 1874 | "fr" : { 1875 | "stringUnit" : { 1876 | "state" : "translated", 1877 | "value" : "Foire aux questions (FAQ)" 1878 | } 1879 | }, 1880 | "fr-CA" : { 1881 | "stringUnit" : { 1882 | "state" : "translated", 1883 | "value" : "Foire aux questions (FAQ)" 1884 | } 1885 | }, 1886 | "he" : { 1887 | "stringUnit" : { 1888 | "state" : "translated", 1889 | "value" : "שאלות נפוצות (FAQ)" 1890 | } 1891 | }, 1892 | "hi" : { 1893 | "stringUnit" : { 1894 | "state" : "translated", 1895 | "value" : "अक्सर पूछे जाने वाले प्रश्न (एफएक्यू)" 1896 | } 1897 | }, 1898 | "hr" : { 1899 | "stringUnit" : { 1900 | "state" : "translated", 1901 | "value" : "Često postavljana pitanja (FAQ)" 1902 | } 1903 | }, 1904 | "hu" : { 1905 | "stringUnit" : { 1906 | "state" : "translated", 1907 | "value" : "Gyakran ismételt kérdések (GYIK)" 1908 | } 1909 | }, 1910 | "id" : { 1911 | "stringUnit" : { 1912 | "state" : "translated", 1913 | "value" : "Pertanyaan yang Sering Diajukan (FAQ)" 1914 | } 1915 | }, 1916 | "it" : { 1917 | "stringUnit" : { 1918 | "state" : "translated", 1919 | "value" : "Domande frequenti (FAQ)" 1920 | } 1921 | }, 1922 | "ja" : { 1923 | "stringUnit" : { 1924 | "state" : "translated", 1925 | "value" : "よくある質問(FAQ)" 1926 | } 1927 | }, 1928 | "kk" : { 1929 | "stringUnit" : { 1930 | "state" : "translated", 1931 | "value" : "Жиі қойылатын сұрақтар (жиі қойылатын сұрақтар)" 1932 | } 1933 | }, 1934 | "ko" : { 1935 | "stringUnit" : { 1936 | "state" : "translated", 1937 | "value" : "자주 묻는 질문(FAQ)" 1938 | } 1939 | }, 1940 | "ms" : { 1941 | "stringUnit" : { 1942 | "state" : "translated", 1943 | "value" : "Soalan Lazim (FAQ)" 1944 | } 1945 | }, 1946 | "nl" : { 1947 | "stringUnit" : { 1948 | "state" : "translated", 1949 | "value" : "Veelgestelde vragen (FAQ)" 1950 | } 1951 | }, 1952 | "pl" : { 1953 | "stringUnit" : { 1954 | "state" : "translated", 1955 | "value" : "Często zadawane pytania (FAQ)" 1956 | } 1957 | }, 1958 | "pt-BR" : { 1959 | "stringUnit" : { 1960 | "state" : "translated", 1961 | "value" : "Perguntas frequentes (FAQ)" 1962 | } 1963 | }, 1964 | "pt-PT" : { 1965 | "stringUnit" : { 1966 | "state" : "translated", 1967 | "value" : "Perguntas frequentes (FAQ)" 1968 | } 1969 | }, 1970 | "ro" : { 1971 | "stringUnit" : { 1972 | "state" : "translated", 1973 | "value" : "Întrebări frecvente (FAQ)" 1974 | } 1975 | }, 1976 | "ru" : { 1977 | "stringUnit" : { 1978 | "state" : "translated", 1979 | "value" : "Часто задаваемые вопросы (FAQ)" 1980 | } 1981 | }, 1982 | "sk" : { 1983 | "stringUnit" : { 1984 | "state" : "translated", 1985 | "value" : "Často kladené otázky (FAQ)" 1986 | } 1987 | }, 1988 | "sv" : { 1989 | "stringUnit" : { 1990 | "state" : "translated", 1991 | "value" : "Vanliga frågor och svar (FAQ)" 1992 | } 1993 | }, 1994 | "th" : { 1995 | "stringUnit" : { 1996 | "state" : "translated", 1997 | "value" : "คําถามที่พบบ่อย (FAQ)" 1998 | } 1999 | }, 2000 | "tr" : { 2001 | "stringUnit" : { 2002 | "state" : "translated", 2003 | "value" : "Sıkça Sorulan Sorular (SSS)" 2004 | } 2005 | }, 2006 | "uk" : { 2007 | "stringUnit" : { 2008 | "state" : "translated", 2009 | "value" : "Часті запитання (FAQ)" 2010 | } 2011 | }, 2012 | "vi" : { 2013 | "stringUnit" : { 2014 | "state" : "translated", 2015 | "value" : "Câu hỏi thường gặp (FAQ)" 2016 | } 2017 | }, 2018 | "zh-Hans" : { 2019 | "stringUnit" : { 2020 | "state" : "translated", 2021 | "value" : "常见问题(FAQ)" 2022 | } 2023 | }, 2024 | "zh-Hant" : { 2025 | "stringUnit" : { 2026 | "state" : "translated", 2027 | "value" : "常見問題 (FAQ)" 2028 | } 2029 | }, 2030 | "zh-HK" : { 2031 | "stringUnit" : { 2032 | "state" : "translated", 2033 | "value" : "常見問題(FAQ)" 2034 | } 2035 | } 2036 | } 2037 | }, 2038 | "Help" : { 2039 | "localizations" : { 2040 | "ar" : { 2041 | "stringUnit" : { 2042 | "state" : "translated", 2043 | "value" : "مساعدة" 2044 | } 2045 | }, 2046 | "bg" : { 2047 | "stringUnit" : { 2048 | "state" : "translated", 2049 | "value" : "Помощ" 2050 | } 2051 | }, 2052 | "ca" : { 2053 | "stringUnit" : { 2054 | "state" : "translated", 2055 | "value" : "Ajuda" 2056 | } 2057 | }, 2058 | "cs" : { 2059 | "stringUnit" : { 2060 | "state" : "translated", 2061 | "value" : "Nápověda" 2062 | } 2063 | }, 2064 | "da" : { 2065 | "stringUnit" : { 2066 | "state" : "translated", 2067 | "value" : "Hjælp" 2068 | } 2069 | }, 2070 | "de" : { 2071 | "stringUnit" : { 2072 | "state" : "translated", 2073 | "value" : "Hilfe" 2074 | } 2075 | }, 2076 | "el" : { 2077 | "stringUnit" : { 2078 | "state" : "translated", 2079 | "value" : "Βοήθεια" 2080 | } 2081 | }, 2082 | "en-GB" : { 2083 | "stringUnit" : { 2084 | "state" : "translated", 2085 | "value" : "Help" 2086 | } 2087 | }, 2088 | "es" : { 2089 | "stringUnit" : { 2090 | "state" : "translated", 2091 | "value" : "Ayuda" 2092 | } 2093 | }, 2094 | "fi" : { 2095 | "stringUnit" : { 2096 | "state" : "translated", 2097 | "value" : "Ohje" 2098 | } 2099 | }, 2100 | "fr" : { 2101 | "stringUnit" : { 2102 | "state" : "translated", 2103 | "value" : "Aide" 2104 | } 2105 | }, 2106 | "fr-CA" : { 2107 | "stringUnit" : { 2108 | "state" : "translated", 2109 | "value" : "Aide" 2110 | } 2111 | }, 2112 | "he" : { 2113 | "stringUnit" : { 2114 | "state" : "translated", 2115 | "value" : "עזרה" 2116 | } 2117 | }, 2118 | "hi" : { 2119 | "stringUnit" : { 2120 | "state" : "translated", 2121 | "value" : "सहायता" 2122 | } 2123 | }, 2124 | "hr" : { 2125 | "stringUnit" : { 2126 | "state" : "translated", 2127 | "value" : "Pomoć" 2128 | } 2129 | }, 2130 | "hu" : { 2131 | "stringUnit" : { 2132 | "state" : "translated", 2133 | "value" : "Súgó" 2134 | } 2135 | }, 2136 | "id" : { 2137 | "stringUnit" : { 2138 | "state" : "translated", 2139 | "value" : "Bantuan" 2140 | } 2141 | }, 2142 | "it" : { 2143 | "stringUnit" : { 2144 | "state" : "translated", 2145 | "value" : "Aiuto" 2146 | } 2147 | }, 2148 | "ja" : { 2149 | "stringUnit" : { 2150 | "state" : "translated", 2151 | "value" : "ヘルプ" 2152 | } 2153 | }, 2154 | "kk" : { 2155 | "stringUnit" : { 2156 | "state" : "translated", 2157 | "value" : "Анықтама" 2158 | } 2159 | }, 2160 | "ko" : { 2161 | "stringUnit" : { 2162 | "state" : "translated", 2163 | "value" : "도움말" 2164 | } 2165 | }, 2166 | "ms" : { 2167 | "stringUnit" : { 2168 | "state" : "translated", 2169 | "value" : "Bantuan" 2170 | } 2171 | }, 2172 | "nl" : { 2173 | "stringUnit" : { 2174 | "state" : "translated", 2175 | "value" : "Help" 2176 | } 2177 | }, 2178 | "pl" : { 2179 | "stringUnit" : { 2180 | "state" : "translated", 2181 | "value" : "Pomoc" 2182 | } 2183 | }, 2184 | "pt-BR" : { 2185 | "stringUnit" : { 2186 | "state" : "translated", 2187 | "value" : "Ajuda" 2188 | } 2189 | }, 2190 | "pt-PT" : { 2191 | "stringUnit" : { 2192 | "state" : "translated", 2193 | "value" : "Ajuda" 2194 | } 2195 | }, 2196 | "ro" : { 2197 | "stringUnit" : { 2198 | "state" : "translated", 2199 | "value" : "Ajutor" 2200 | } 2201 | }, 2202 | "ru" : { 2203 | "stringUnit" : { 2204 | "state" : "translated", 2205 | "value" : "Справка" 2206 | } 2207 | }, 2208 | "sk" : { 2209 | "stringUnit" : { 2210 | "state" : "translated", 2211 | "value" : "Pomocník" 2212 | } 2213 | }, 2214 | "sv" : { 2215 | "stringUnit" : { 2216 | "state" : "translated", 2217 | "value" : "Hjälp" 2218 | } 2219 | }, 2220 | "th" : { 2221 | "stringUnit" : { 2222 | "state" : "translated", 2223 | "value" : "วิธีใช้" 2224 | } 2225 | }, 2226 | "tr" : { 2227 | "stringUnit" : { 2228 | "state" : "translated", 2229 | "value" : "Yardım" 2230 | } 2231 | }, 2232 | "uk" : { 2233 | "stringUnit" : { 2234 | "state" : "translated", 2235 | "value" : "Довідка" 2236 | } 2237 | }, 2238 | "vi" : { 2239 | "stringUnit" : { 2240 | "state" : "translated", 2241 | "value" : "Trợ giúp" 2242 | } 2243 | }, 2244 | "zh-Hans" : { 2245 | "stringUnit" : { 2246 | "state" : "translated", 2247 | "value" : "帮助" 2248 | } 2249 | }, 2250 | "zh-Hant" : { 2251 | "stringUnit" : { 2252 | "state" : "translated", 2253 | "value" : "輔助說明" 2254 | } 2255 | }, 2256 | "zh-HK" : { 2257 | "stringUnit" : { 2258 | "state" : "translated", 2259 | "value" : "輔助説明" 2260 | } 2261 | } 2262 | } 2263 | }, 2264 | "Legal" : { 2265 | "localizations" : { 2266 | "ar" : { 2267 | "stringUnit" : { 2268 | "state" : "translated", 2269 | "value" : "قانوني" 2270 | } 2271 | }, 2272 | "bg" : { 2273 | "stringUnit" : { 2274 | "state" : "translated", 2275 | "value" : "Юридически" 2276 | } 2277 | }, 2278 | "ca" : { 2279 | "stringUnit" : { 2280 | "state" : "translated", 2281 | "value" : "Legal" 2282 | } 2283 | }, 2284 | "cs" : { 2285 | "stringUnit" : { 2286 | "state" : "translated", 2287 | "value" : "Právní" 2288 | } 2289 | }, 2290 | "da" : { 2291 | "stringUnit" : { 2292 | "state" : "translated", 2293 | "value" : "Juridisk" 2294 | } 2295 | }, 2296 | "de" : { 2297 | "stringUnit" : { 2298 | "state" : "translated", 2299 | "value" : "Rechtliches" 2300 | } 2301 | }, 2302 | "el" : { 2303 | "stringUnit" : { 2304 | "state" : "translated", 2305 | "value" : "Νομικό" 2306 | } 2307 | }, 2308 | "en-GB" : { 2309 | "stringUnit" : { 2310 | "state" : "translated", 2311 | "value" : "Legal" 2312 | } 2313 | }, 2314 | "es" : { 2315 | "stringUnit" : { 2316 | "state" : "translated", 2317 | "value" : "Legal" 2318 | } 2319 | }, 2320 | "fi" : { 2321 | "stringUnit" : { 2322 | "state" : "translated", 2323 | "value" : "Oikeudellinen" 2324 | } 2325 | }, 2326 | "fr" : { 2327 | "stringUnit" : { 2328 | "state" : "translated", 2329 | "value" : "Juridique" 2330 | } 2331 | }, 2332 | "fr-CA" : { 2333 | "stringUnit" : { 2334 | "state" : "translated", 2335 | "value" : "Mentions légales" 2336 | } 2337 | }, 2338 | "he" : { 2339 | "stringUnit" : { 2340 | "state" : "translated", 2341 | "value" : "משפטי" 2342 | } 2343 | }, 2344 | "hi" : { 2345 | "stringUnit" : { 2346 | "state" : "translated", 2347 | "value" : "विधि-सम्‍मत" 2348 | } 2349 | }, 2350 | "hr" : { 2351 | "stringUnit" : { 2352 | "state" : "translated", 2353 | "value" : "Pravni" 2354 | } 2355 | }, 2356 | "hu" : { 2357 | "stringUnit" : { 2358 | "state" : "translated", 2359 | "value" : "Jogi" 2360 | } 2361 | }, 2362 | "id" : { 2363 | "stringUnit" : { 2364 | "state" : "translated", 2365 | "value" : "Hukum" 2366 | } 2367 | }, 2368 | "it" : { 2369 | "stringUnit" : { 2370 | "state" : "translated", 2371 | "value" : "Legale" 2372 | } 2373 | }, 2374 | "ja" : { 2375 | "stringUnit" : { 2376 | "state" : "translated", 2377 | "value" : "リーガル" 2378 | } 2379 | }, 2380 | "kk" : { 2381 | "stringUnit" : { 2382 | "state" : "translated", 2383 | "value" : "Заңды" 2384 | } 2385 | }, 2386 | "ko" : { 2387 | "stringUnit" : { 2388 | "state" : "translated", 2389 | "value" : "법률" 2390 | } 2391 | }, 2392 | "ms" : { 2393 | "stringUnit" : { 2394 | "state" : "translated", 2395 | "value" : "Undang" 2396 | } 2397 | }, 2398 | "nl" : { 2399 | "stringUnit" : { 2400 | "state" : "translated", 2401 | "value" : "Juridisch" 2402 | } 2403 | }, 2404 | "pl" : { 2405 | "stringUnit" : { 2406 | "state" : "translated", 2407 | "value" : "Prawny" 2408 | } 2409 | }, 2410 | "pt-BR" : { 2411 | "stringUnit" : { 2412 | "state" : "translated", 2413 | "value" : "Legal" 2414 | } 2415 | }, 2416 | "pt-PT" : { 2417 | "stringUnit" : { 2418 | "state" : "translated", 2419 | "value" : "Legal" 2420 | } 2421 | }, 2422 | "ro" : { 2423 | "stringUnit" : { 2424 | "state" : "translated", 2425 | "value" : "Legal" 2426 | } 2427 | }, 2428 | "ru" : { 2429 | "stringUnit" : { 2430 | "state" : "translated", 2431 | "value" : "Юридическая" 2432 | } 2433 | }, 2434 | "sk" : { 2435 | "stringUnit" : { 2436 | "state" : "translated", 2437 | "value" : "Právna stránka" 2438 | } 2439 | }, 2440 | "sv" : { 2441 | "stringUnit" : { 2442 | "state" : "translated", 2443 | "value" : "Juridisk" 2444 | } 2445 | }, 2446 | "th" : { 2447 | "stringUnit" : { 2448 | "state" : "translated", 2449 | "value" : "ชอบด้วยกฎหมาย" 2450 | } 2451 | }, 2452 | "tr" : { 2453 | "stringUnit" : { 2454 | "state" : "translated", 2455 | "value" : "Yasal" 2456 | } 2457 | }, 2458 | "uk" : { 2459 | "stringUnit" : { 2460 | "state" : "translated", 2461 | "value" : "Юридичний" 2462 | } 2463 | }, 2464 | "vi" : { 2465 | "stringUnit" : { 2466 | "state" : "translated", 2467 | "value" : "Hợp pháp" 2468 | } 2469 | }, 2470 | "zh-Hans" : { 2471 | "stringUnit" : { 2472 | "state" : "translated", 2473 | "value" : "法律" 2474 | } 2475 | }, 2476 | "zh-Hant" : { 2477 | "stringUnit" : { 2478 | "state" : "translated", 2479 | "value" : "法律" 2480 | } 2481 | }, 2482 | "zh-HK" : { 2483 | "stringUnit" : { 2484 | "state" : "translated", 2485 | "value" : "法律" 2486 | } 2487 | } 2488 | } 2489 | }, 2490 | "More apps from Developer" : { 2491 | "localizations" : { 2492 | "ar" : { 2493 | "stringUnit" : { 2494 | "state" : "translated", 2495 | "value" : "المزيد من التطبيقات من المطور" 2496 | } 2497 | }, 2498 | "bg" : { 2499 | "stringUnit" : { 2500 | "state" : "translated", 2501 | "value" : "Още приложения от Разработчик" 2502 | } 2503 | }, 2504 | "ca" : { 2505 | "stringUnit" : { 2506 | "state" : "translated", 2507 | "value" : "Més aplicacions de Developer" 2508 | } 2509 | }, 2510 | "cs" : { 2511 | "stringUnit" : { 2512 | "state" : "translated", 2513 | "value" : "Další aplikace od vývojáře" 2514 | } 2515 | }, 2516 | "da" : { 2517 | "stringUnit" : { 2518 | "state" : "translated", 2519 | "value" : "Flere apps fra Developer" 2520 | } 2521 | }, 2522 | "de" : { 2523 | "stringUnit" : { 2524 | "state" : "translated", 2525 | "value" : "Mehr Apps vom Entwickler" 2526 | } 2527 | }, 2528 | "el" : { 2529 | "stringUnit" : { 2530 | "state" : "translated", 2531 | "value" : "Περισσότερες εφαρμογές από Developer" 2532 | } 2533 | }, 2534 | "en-GB" : { 2535 | "stringUnit" : { 2536 | "state" : "translated", 2537 | "value" : "More apps from Developer" 2538 | } 2539 | }, 2540 | "es" : { 2541 | "stringUnit" : { 2542 | "state" : "translated", 2543 | "value" : "Más apps de Desarrollador" 2544 | } 2545 | }, 2546 | "fi" : { 2547 | "stringUnit" : { 2548 | "state" : "translated", 2549 | "value" : "Lisää sovelluksia kehittäjältä Developer" 2550 | } 2551 | }, 2552 | "fr" : { 2553 | "stringUnit" : { 2554 | "state" : "translated", 2555 | "value" : "Plus d'applications de Developer" 2556 | } 2557 | }, 2558 | "fr-CA" : { 2559 | "stringUnit" : { 2560 | "state" : "translated", 2561 | "value" : "Plus d’applications de Développeur" 2562 | } 2563 | }, 2564 | "he" : { 2565 | "stringUnit" : { 2566 | "state" : "translated", 2567 | "value" : "אפליקציות נוספות מאת Developer" 2568 | } 2569 | }, 2570 | "hi" : { 2571 | "stringUnit" : { 2572 | "state" : "translated", 2573 | "value" : "डेवलपर से अधिक ऐप्लिकेशन" 2574 | } 2575 | }, 2576 | "hr" : { 2577 | "stringUnit" : { 2578 | "state" : "translated", 2579 | "value" : "Više aplikacija od programera" 2580 | } 2581 | }, 2582 | "hu" : { 2583 | "stringUnit" : { 2584 | "state" : "translated", 2585 | "value" : "További alkalmazások a fejlesztőtől Developer" 2586 | } 2587 | }, 2588 | "id" : { 2589 | "stringUnit" : { 2590 | "state" : "translated", 2591 | "value" : "Lebih banyak aplikasi dari Pengembang" 2592 | } 2593 | }, 2594 | "it" : { 2595 | "stringUnit" : { 2596 | "state" : "translated", 2597 | "value" : "Altre app dello sviluppatore" 2598 | } 2599 | }, 2600 | "ja" : { 2601 | "stringUnit" : { 2602 | "state" : "translated", 2603 | "value" : "開発者のその他のアプリ" 2604 | } 2605 | }, 2606 | "kk" : { 2607 | "stringUnit" : { 2608 | "state" : "translated", 2609 | "value" : "Әзірлеушіден қосымша бағдарламалар" 2610 | } 2611 | }, 2612 | "ko" : { 2613 | "stringUnit" : { 2614 | "state" : "translated", 2615 | "value" : "개발자의 더 많은 앱" 2616 | } 2617 | }, 2618 | "ms" : { 2619 | "stringUnit" : { 2620 | "state" : "translated", 2621 | "value" : "Lebih banyak apl daripada Pembangun" 2622 | } 2623 | }, 2624 | "nl" : { 2625 | "stringUnit" : { 2626 | "state" : "translated", 2627 | "value" : "Meer apps van Ontwikkelaar" 2628 | } 2629 | }, 2630 | "pl" : { 2631 | "stringUnit" : { 2632 | "state" : "translated", 2633 | "value" : "Więcej aplikacji od dewelopera" 2634 | } 2635 | }, 2636 | "pt-BR" : { 2637 | "stringUnit" : { 2638 | "state" : "translated", 2639 | "value" : "Mais aplicativos do desenvolvedor" 2640 | } 2641 | }, 2642 | "pt-PT" : { 2643 | "stringUnit" : { 2644 | "state" : "translated", 2645 | "value" : "Mais aplicações do Programador" 2646 | } 2647 | }, 2648 | "ro" : { 2649 | "stringUnit" : { 2650 | "state" : "translated", 2651 | "value" : "Mai multe aplicații de la Developer" 2652 | } 2653 | }, 2654 | "ru" : { 2655 | "stringUnit" : { 2656 | "state" : "translated", 2657 | "value" : "Другие приложения от разработчика" 2658 | } 2659 | }, 2660 | "sk" : { 2661 | "stringUnit" : { 2662 | "state" : "translated", 2663 | "value" : "Ďalšie aplikácie od vývojára" 2664 | } 2665 | }, 2666 | "sv" : { 2667 | "stringUnit" : { 2668 | "state" : "translated", 2669 | "value" : "Fler appar från Utvecklare" 2670 | } 2671 | }, 2672 | "th" : { 2673 | "stringUnit" : { 2674 | "state" : "translated", 2675 | "value" : "แอพเพิ่มเติมจาก Developer" 2676 | } 2677 | }, 2678 | "tr" : { 2679 | "stringUnit" : { 2680 | "state" : "translated", 2681 | "value" : "Developer'dan diğer uygulamalar" 2682 | } 2683 | }, 2684 | "uk" : { 2685 | "stringUnit" : { 2686 | "state" : "translated", 2687 | "value" : "Більше додатків від розробника" 2688 | } 2689 | }, 2690 | "vi" : { 2691 | "stringUnit" : { 2692 | "state" : "translated", 2693 | "value" : "Xem thêm từ Nhà phát triển" 2694 | } 2695 | }, 2696 | "zh-Hans" : { 2697 | "stringUnit" : { 2698 | "state" : "translated", 2699 | "value" : "开发者的更多应用程序" 2700 | } 2701 | }, 2702 | "zh-Hant" : { 2703 | "stringUnit" : { 2704 | "state" : "translated", 2705 | "value" : "Developer 的其他應用" 2706 | } 2707 | }, 2708 | "zh-HK" : { 2709 | "stringUnit" : { 2710 | "state" : "translated", 2711 | "value" : "Developer嘅其他應用" 2712 | } 2713 | } 2714 | } 2715 | }, 2716 | "More Apps from Developer" : { 2717 | "localizations" : { 2718 | "ar" : { 2719 | "stringUnit" : { 2720 | "state" : "translated", 2721 | "value" : "المزيد من التطبيقات من المطور" 2722 | } 2723 | }, 2724 | "bg" : { 2725 | "stringUnit" : { 2726 | "state" : "translated", 2727 | "value" : "Повече приложения от Developer" 2728 | } 2729 | }, 2730 | "ca" : { 2731 | "stringUnit" : { 2732 | "state" : "translated", 2733 | "value" : "Més aplicacions del desenvolupador" 2734 | } 2735 | }, 2736 | "cs" : { 2737 | "stringUnit" : { 2738 | "state" : "translated", 2739 | "value" : "Další aplikace od vývojáře" 2740 | } 2741 | }, 2742 | "da" : { 2743 | "stringUnit" : { 2744 | "state" : "translated", 2745 | "value" : "Flere apps fra udvikler" 2746 | } 2747 | }, 2748 | "de" : { 2749 | "stringUnit" : { 2750 | "state" : "translated", 2751 | "value" : "Mehr Apps vom Entwickler" 2752 | } 2753 | }, 2754 | "el" : { 2755 | "stringUnit" : { 2756 | "state" : "translated", 2757 | "value" : "Περισσότερες εφαρμογές από Developer" 2758 | } 2759 | }, 2760 | "en-GB" : { 2761 | "stringUnit" : { 2762 | "state" : "translated", 2763 | "value" : "More Apps from Developer" 2764 | } 2765 | }, 2766 | "es" : { 2767 | "stringUnit" : { 2768 | "state" : "translated", 2769 | "value" : "Más aplicaciones del desarrollador" 2770 | } 2771 | }, 2772 | "fi" : { 2773 | "stringUnit" : { 2774 | "state" : "translated", 2775 | "value" : "Lisää sovelluksia kehittäjältä Developer" 2776 | } 2777 | }, 2778 | "fr" : { 2779 | "stringUnit" : { 2780 | "state" : "translated", 2781 | "value" : "Plus d'applications du développeur" 2782 | } 2783 | }, 2784 | "fr-CA" : { 2785 | "stringUnit" : { 2786 | "state" : "translated", 2787 | "value" : "Plus d’applications du développeur" 2788 | } 2789 | }, 2790 | "he" : { 2791 | "stringUnit" : { 2792 | "state" : "translated", 2793 | "value" : "יישומים נוספים ממפתחים" 2794 | } 2795 | }, 2796 | "hi" : { 2797 | "stringUnit" : { 2798 | "state" : "translated", 2799 | "value" : "डेवलपर से अधिक ऐप्स" 2800 | } 2801 | }, 2802 | "hr" : { 2803 | "stringUnit" : { 2804 | "state" : "translated", 2805 | "value" : "Više aplikacija od programera" 2806 | } 2807 | }, 2808 | "hu" : { 2809 | "stringUnit" : { 2810 | "state" : "translated", 2811 | "value" : "További alkalmazások a fejlesztőtől" 2812 | } 2813 | }, 2814 | "id" : { 2815 | "stringUnit" : { 2816 | "state" : "translated", 2817 | "value" : "Lebih Banyak Aplikasi dari Pengembang" 2818 | } 2819 | }, 2820 | "it" : { 2821 | "stringUnit" : { 2822 | "state" : "translated", 2823 | "value" : "Altre applicazioni dallo sviluppatore" 2824 | } 2825 | }, 2826 | "ja" : { 2827 | "stringUnit" : { 2828 | "state" : "translated", 2829 | "value" : "その他のアプリ 開発者" 2830 | } 2831 | }, 2832 | "kk" : { 2833 | "stringUnit" : { 2834 | "state" : "translated", 2835 | "value" : "Әзірлеушіден қосымша бағдарламалар" 2836 | } 2837 | }, 2838 | "ko" : { 2839 | "stringUnit" : { 2840 | "state" : "translated", 2841 | "value" : "개발자의 더 많은 앱" 2842 | } 2843 | }, 2844 | "ms" : { 2845 | "stringUnit" : { 2846 | "state" : "translated", 2847 | "value" : "Lebih Banyak Apl daripada Pembangun" 2848 | } 2849 | }, 2850 | "nl" : { 2851 | "stringUnit" : { 2852 | "state" : "translated", 2853 | "value" : "Meer Apps van Ontwikkelaar" 2854 | } 2855 | }, 2856 | "pl" : { 2857 | "stringUnit" : { 2858 | "state" : "translated", 2859 | "value" : "Więcej aplikacji od dewelopera" 2860 | } 2861 | }, 2862 | "pt-BR" : { 2863 | "stringUnit" : { 2864 | "state" : "translated", 2865 | "value" : "Mais aplicativos do desenvolvedor" 2866 | } 2867 | }, 2868 | "pt-PT" : { 2869 | "stringUnit" : { 2870 | "state" : "translated", 2871 | "value" : "Mais aplicações do Programador" 2872 | } 2873 | }, 2874 | "ro" : { 2875 | "stringUnit" : { 2876 | "state" : "translated", 2877 | "value" : "Mai multe aplicații de la Developer" 2878 | } 2879 | }, 2880 | "ru" : { 2881 | "stringUnit" : { 2882 | "state" : "translated", 2883 | "value" : "Другие приложения от разработчика" 2884 | } 2885 | }, 2886 | "sk" : { 2887 | "stringUnit" : { 2888 | "state" : "translated", 2889 | "value" : "Ďalšie aplikácie od vývojára" 2890 | } 2891 | }, 2892 | "sv" : { 2893 | "stringUnit" : { 2894 | "state" : "translated", 2895 | "value" : "Fler appar från utvecklaren" 2896 | } 2897 | }, 2898 | "th" : { 2899 | "stringUnit" : { 2900 | "state" : "translated", 2901 | "value" : "แอพเพิ่มเติมจาก Developer" 2902 | } 2903 | }, 2904 | "tr" : { 2905 | "stringUnit" : { 2906 | "state" : "translated", 2907 | "value" : "Developer'dan diğer uygulamalar" 2908 | } 2909 | }, 2910 | "uk" : { 2911 | "stringUnit" : { 2912 | "state" : "translated", 2913 | "value" : "Більше додатків від розробника" 2914 | } 2915 | }, 2916 | "vi" : { 2917 | "stringUnit" : { 2918 | "state" : "translated", 2919 | "value" : "Xem thêm từ Nhà phát triển" 2920 | } 2921 | }, 2922 | "zh-Hans" : { 2923 | "stringUnit" : { 2924 | "state" : "translated", 2925 | "value" : "开发者的更多应用程序" 2926 | } 2927 | }, 2928 | "zh-Hant" : { 2929 | "stringUnit" : { 2930 | "state" : "translated", 2931 | "value" : "Developer 的其他應用" 2932 | } 2933 | }, 2934 | "zh-HK" : { 2935 | "stringUnit" : { 2936 | "state" : "translated", 2937 | "value" : "Developer嘅其他應用" 2938 | } 2939 | } 2940 | } 2941 | }, 2942 | "Privacy Policy" : { 2943 | "localizations" : { 2944 | "ar" : { 2945 | "stringUnit" : { 2946 | "state" : "translated", 2947 | "value" : "سياسة الخصوصية" 2948 | } 2949 | }, 2950 | "bg" : { 2951 | "stringUnit" : { 2952 | "state" : "translated", 2953 | "value" : "Политика за поверителност" 2954 | } 2955 | }, 2956 | "ca" : { 2957 | "stringUnit" : { 2958 | "state" : "translated", 2959 | "value" : "Política de privacitat" 2960 | } 2961 | }, 2962 | "cs" : { 2963 | "stringUnit" : { 2964 | "state" : "translated", 2965 | "value" : "Zásady ochrany osobních údajů" 2966 | } 2967 | }, 2968 | "da" : { 2969 | "stringUnit" : { 2970 | "state" : "translated", 2971 | "value" : "Politik for beskyttelse af personlige oplysninger" 2972 | } 2973 | }, 2974 | "de" : { 2975 | "stringUnit" : { 2976 | "state" : "translated", 2977 | "value" : "Datenschutzrichtlinie" 2978 | } 2979 | }, 2980 | "el" : { 2981 | "stringUnit" : { 2982 | "state" : "translated", 2983 | "value" : "Πολιτική απορρήτου" 2984 | } 2985 | }, 2986 | "en-GB" : { 2987 | "stringUnit" : { 2988 | "state" : "translated", 2989 | "value" : "Privacy Policy" 2990 | } 2991 | }, 2992 | "es" : { 2993 | "stringUnit" : { 2994 | "state" : "translated", 2995 | "value" : "Política de privacidad" 2996 | } 2997 | }, 2998 | "fi" : { 2999 | "stringUnit" : { 3000 | "state" : "translated", 3001 | "value" : "Tietosuojakäytäntö" 3002 | } 3003 | }, 3004 | "fr" : { 3005 | "stringUnit" : { 3006 | "state" : "translated", 3007 | "value" : "Politique de confidentialité" 3008 | } 3009 | }, 3010 | "fr-CA" : { 3011 | "stringUnit" : { 3012 | "state" : "translated", 3013 | "value" : "Politique de confidentialité" 3014 | } 3015 | }, 3016 | "he" : { 3017 | "stringUnit" : { 3018 | "state" : "translated", 3019 | "value" : "מדיניות פרטיות" 3020 | } 3021 | }, 3022 | "hi" : { 3023 | "stringUnit" : { 3024 | "state" : "translated", 3025 | "value" : "गोपनीयता नीति" 3026 | } 3027 | }, 3028 | "hr" : { 3029 | "stringUnit" : { 3030 | "state" : "translated", 3031 | "value" : "Privatnosti" 3032 | } 3033 | }, 3034 | "hu" : { 3035 | "stringUnit" : { 3036 | "state" : "translated", 3037 | "value" : "Adatvédelmi irányelvek" 3038 | } 3039 | }, 3040 | "id" : { 3041 | "stringUnit" : { 3042 | "state" : "translated", 3043 | "value" : "Kebijakan Privasi" 3044 | } 3045 | }, 3046 | "it" : { 3047 | "stringUnit" : { 3048 | "state" : "translated", 3049 | "value" : "Informativa sulla privacy" 3050 | } 3051 | }, 3052 | "ja" : { 3053 | "stringUnit" : { 3054 | "state" : "translated", 3055 | "value" : "プライバシーポリシー" 3056 | } 3057 | }, 3058 | "kk" : { 3059 | "stringUnit" : { 3060 | "state" : "translated", 3061 | "value" : "Құпиялылық саясаты" 3062 | } 3063 | }, 3064 | "ko" : { 3065 | "stringUnit" : { 3066 | "state" : "translated", 3067 | "value" : "개인정보 보호정책" 3068 | } 3069 | }, 3070 | "ms" : { 3071 | "stringUnit" : { 3072 | "state" : "translated", 3073 | "value" : "Dasar Privasi" 3074 | } 3075 | }, 3076 | "nl" : { 3077 | "stringUnit" : { 3078 | "state" : "translated", 3079 | "value" : "Privacybeleid" 3080 | } 3081 | }, 3082 | "pl" : { 3083 | "stringUnit" : { 3084 | "state" : "translated", 3085 | "value" : "Polityka prywatności" 3086 | } 3087 | }, 3088 | "pt-BR" : { 3089 | "stringUnit" : { 3090 | "state" : "translated", 3091 | "value" : "Política de privacidade" 3092 | } 3093 | }, 3094 | "pt-PT" : { 3095 | "stringUnit" : { 3096 | "state" : "translated", 3097 | "value" : "Política de privacidade" 3098 | } 3099 | }, 3100 | "ro" : { 3101 | "stringUnit" : { 3102 | "state" : "translated", 3103 | "value" : "Politica de confidențialitate" 3104 | } 3105 | }, 3106 | "ru" : { 3107 | "stringUnit" : { 3108 | "state" : "translated", 3109 | "value" : "Политика конфиденциальности" 3110 | } 3111 | }, 3112 | "sk" : { 3113 | "stringUnit" : { 3114 | "state" : "translated", 3115 | "value" : "Zásady ochrany osobných údajov" 3116 | } 3117 | }, 3118 | "sv" : { 3119 | "stringUnit" : { 3120 | "state" : "translated", 3121 | "value" : "Integritetspolicy" 3122 | } 3123 | }, 3124 | "th" : { 3125 | "stringUnit" : { 3126 | "state" : "translated", 3127 | "value" : "นโยบายความเป็นส่วนตัว" 3128 | } 3129 | }, 3130 | "tr" : { 3131 | "stringUnit" : { 3132 | "state" : "translated", 3133 | "value" : "Gizlilik Politikası" 3134 | } 3135 | }, 3136 | "uk" : { 3137 | "stringUnit" : { 3138 | "state" : "translated", 3139 | "value" : "Політика конфіденційності" 3140 | } 3141 | }, 3142 | "vi" : { 3143 | "stringUnit" : { 3144 | "state" : "translated", 3145 | "value" : "Chính sách bảo mật" 3146 | } 3147 | }, 3148 | "zh-Hans" : { 3149 | "stringUnit" : { 3150 | "state" : "translated", 3151 | "value" : "隐私政策" 3152 | } 3153 | }, 3154 | "zh-Hant" : { 3155 | "stringUnit" : { 3156 | "state" : "translated", 3157 | "value" : "隱私策略" 3158 | } 3159 | }, 3160 | "zh-HK" : { 3161 | "stringUnit" : { 3162 | "state" : "translated", 3163 | "value" : "私隱策略" 3164 | } 3165 | } 3166 | } 3167 | }, 3168 | "Rate the App" : { 3169 | "localizations" : { 3170 | "ar" : { 3171 | "stringUnit" : { 3172 | "state" : "translated", 3173 | "value" : "قيم التطبيق" 3174 | } 3175 | }, 3176 | "bg" : { 3177 | "stringUnit" : { 3178 | "state" : "translated", 3179 | "value" : "Оценка на приложението" 3180 | } 3181 | }, 3182 | "ca" : { 3183 | "stringUnit" : { 3184 | "state" : "translated", 3185 | "value" : "Valora l'app" 3186 | } 3187 | }, 3188 | "cs" : { 3189 | "stringUnit" : { 3190 | "state" : "translated", 3191 | "value" : "Hodnocení aplikace" 3192 | } 3193 | }, 3194 | "da" : { 3195 | "stringUnit" : { 3196 | "state" : "translated", 3197 | "value" : "Bedøm appen" 3198 | } 3199 | }, 3200 | "de" : { 3201 | "stringUnit" : { 3202 | "state" : "translated", 3203 | "value" : "Die App bewerten" 3204 | } 3205 | }, 3206 | "el" : { 3207 | "stringUnit" : { 3208 | "state" : "translated", 3209 | "value" : "Βαθμολογήστε την εφαρμογή" 3210 | } 3211 | }, 3212 | "en-GB" : { 3213 | "stringUnit" : { 3214 | "state" : "translated", 3215 | "value" : "Rate the App" 3216 | } 3217 | }, 3218 | "es" : { 3219 | "stringUnit" : { 3220 | "state" : "translated", 3221 | "value" : "Valora la App" 3222 | } 3223 | }, 3224 | "fi" : { 3225 | "stringUnit" : { 3226 | "state" : "translated", 3227 | "value" : "Arvioi sovellus" 3228 | } 3229 | }, 3230 | "fr" : { 3231 | "stringUnit" : { 3232 | "state" : "translated", 3233 | "value" : "Note l'application" 3234 | } 3235 | }, 3236 | "fr-CA" : { 3237 | "stringUnit" : { 3238 | "state" : "translated", 3239 | "value" : "Évaluez l’application" 3240 | } 3241 | }, 3242 | "he" : { 3243 | "stringUnit" : { 3244 | "state" : "translated", 3245 | "value" : "דרג את האפליקציה" 3246 | } 3247 | }, 3248 | "hi" : { 3249 | "stringUnit" : { 3250 | "state" : "translated", 3251 | "value" : "ऐप को रेट करें" 3252 | } 3253 | }, 3254 | "hr" : { 3255 | "stringUnit" : { 3256 | "state" : "translated", 3257 | "value" : "Ocijenite aplikaciju" 3258 | } 3259 | }, 3260 | "hu" : { 3261 | "stringUnit" : { 3262 | "state" : "translated", 3263 | "value" : "Értékelje az alkalmazást" 3264 | } 3265 | }, 3266 | "id" : { 3267 | "stringUnit" : { 3268 | "state" : "translated", 3269 | "value" : "Beri Nilai Aplikasi" 3270 | } 3271 | }, 3272 | "it" : { 3273 | "stringUnit" : { 3274 | "state" : "translated", 3275 | "value" : "Valuta l'applicazione" 3276 | } 3277 | }, 3278 | "ja" : { 3279 | "stringUnit" : { 3280 | "state" : "translated", 3281 | "value" : "アプリを評価する" 3282 | } 3283 | }, 3284 | "kk" : { 3285 | "stringUnit" : { 3286 | "state" : "translated", 3287 | "value" : "Бағдарламаны бағалау" 3288 | } 3289 | }, 3290 | "ko" : { 3291 | "stringUnit" : { 3292 | "state" : "translated", 3293 | "value" : "앱 평가하기" 3294 | } 3295 | }, 3296 | "ms" : { 3297 | "stringUnit" : { 3298 | "state" : "translated", 3299 | "value" : "Nilai Apl" 3300 | } 3301 | }, 3302 | "nl" : { 3303 | "stringUnit" : { 3304 | "state" : "translated", 3305 | "value" : "Beoordeel de app" 3306 | } 3307 | }, 3308 | "pl" : { 3309 | "stringUnit" : { 3310 | "state" : "translated", 3311 | "value" : "Oceń aplikację" 3312 | } 3313 | }, 3314 | "pt-BR" : { 3315 | "stringUnit" : { 3316 | "state" : "translated", 3317 | "value" : "Avalie o aplicativo" 3318 | } 3319 | }, 3320 | "pt-PT" : { 3321 | "stringUnit" : { 3322 | "state" : "translated", 3323 | "value" : "Avalia a aplicação" 3324 | } 3325 | }, 3326 | "ro" : { 3327 | "stringUnit" : { 3328 | "state" : "translated", 3329 | "value" : "Evaluați aplicația" 3330 | } 3331 | }, 3332 | "ru" : { 3333 | "stringUnit" : { 3334 | "state" : "translated", 3335 | "value" : "Оцените приложение" 3336 | } 3337 | }, 3338 | "sk" : { 3339 | "stringUnit" : { 3340 | "state" : "translated", 3341 | "value" : "Hodnotenie aplikácie" 3342 | } 3343 | }, 3344 | "sv" : { 3345 | "stringUnit" : { 3346 | "state" : "translated", 3347 | "value" : "Betygsätt appen" 3348 | } 3349 | }, 3350 | "th" : { 3351 | "stringUnit" : { 3352 | "state" : "translated", 3353 | "value" : "ให้คะแนนแอป" 3354 | } 3355 | }, 3356 | "tr" : { 3357 | "stringUnit" : { 3358 | "state" : "translated", 3359 | "value" : "Uygulamayı Değerlendirin" 3360 | } 3361 | }, 3362 | "uk" : { 3363 | "stringUnit" : { 3364 | "state" : "translated", 3365 | "value" : "Оцініть додаток" 3366 | } 3367 | }, 3368 | "vi" : { 3369 | "stringUnit" : { 3370 | "state" : "translated", 3371 | "value" : "Xếp hạng ứng dụng" 3372 | } 3373 | }, 3374 | "zh-Hans" : { 3375 | "stringUnit" : { 3376 | "state" : "translated", 3377 | "value" : "为应用程序评分" 3378 | } 3379 | }, 3380 | "zh-Hant" : { 3381 | "stringUnit" : { 3382 | "state" : "translated", 3383 | "value" : "為應用程式評分" 3384 | } 3385 | }, 3386 | "zh-HK" : { 3387 | "stringUnit" : { 3388 | "state" : "translated", 3389 | "value" : "為應用程序評分" 3390 | } 3391 | } 3392 | } 3393 | }, 3394 | "Related apps you might Like" : { 3395 | "localizations" : { 3396 | "ar" : { 3397 | "stringUnit" : { 3398 | "state" : "translated", 3399 | "value" : "التطبيقات ذات الصلة التي قد تعجبك" 3400 | } 3401 | }, 3402 | "bg" : { 3403 | "stringUnit" : { 3404 | "state" : "translated", 3405 | "value" : "Свързани приложения, които може да ви харесат" 3406 | } 3407 | }, 3408 | "ca" : { 3409 | "stringUnit" : { 3410 | "state" : "translated", 3411 | "value" : "Aplicacions relacionades que et poden agradar" 3412 | } 3413 | }, 3414 | "cs" : { 3415 | "stringUnit" : { 3416 | "state" : "translated", 3417 | "value" : "Související aplikace, které by se vám mohly líbit" 3418 | } 3419 | }, 3420 | "da" : { 3421 | "stringUnit" : { 3422 | "state" : "translated", 3423 | "value" : "Relaterede apps, du måske kan lide" 3424 | } 3425 | }, 3426 | "de" : { 3427 | "stringUnit" : { 3428 | "state" : "translated", 3429 | "value" : "Verwandte Apps, die dir gefallen könnten" 3430 | } 3431 | }, 3432 | "el" : { 3433 | "stringUnit" : { 3434 | "state" : "translated", 3435 | "value" : "Σχετικές εφαρμογές που μπορεί να σας αρέσουν" 3436 | } 3437 | }, 3438 | "en-GB" : { 3439 | "stringUnit" : { 3440 | "state" : "translated", 3441 | "value" : "Related apps you might Like" 3442 | } 3443 | }, 3444 | "es" : { 3445 | "stringUnit" : { 3446 | "state" : "translated", 3447 | "value" : "Aplicaciones relacionadas que te pueden gustar" 3448 | } 3449 | }, 3450 | "fi" : { 3451 | "stringUnit" : { 3452 | "state" : "translated", 3453 | "value" : "Aiheeseen liittyvät sovellukset, joista saatat pitää" 3454 | } 3455 | }, 3456 | "fr" : { 3457 | "stringUnit" : { 3458 | "state" : "translated", 3459 | "value" : "Applications connexes que tu pourrais aimer" 3460 | } 3461 | }, 3462 | "fr-CA" : { 3463 | "stringUnit" : { 3464 | "state" : "translated", 3465 | "value" : "Applications connexes que vous pourriez aimer" 3466 | } 3467 | }, 3468 | "he" : { 3469 | "stringUnit" : { 3470 | "state" : "translated", 3471 | "value" : "אפליקציות קשורות שעשויות למצוא חן בעיניך" 3472 | } 3473 | }, 3474 | "hi" : { 3475 | "stringUnit" : { 3476 | "state" : "translated", 3477 | "value" : "संबंधित ऐप्स जो आपको पसंद आ सकते हैं" 3478 | } 3479 | }, 3480 | "hr" : { 3481 | "stringUnit" : { 3482 | "state" : "translated", 3483 | "value" : "Povezane aplikacije koje bi vam se mogle svidjeti" 3484 | } 3485 | }, 3486 | "hu" : { 3487 | "stringUnit" : { 3488 | "state" : "translated", 3489 | "value" : "Kapcsolódó alkalmazások, amelyeket szerethet" 3490 | } 3491 | }, 3492 | "id" : { 3493 | "stringUnit" : { 3494 | "state" : "translated", 3495 | "value" : "Aplikasi terkait yang mungkin Anda sukai" 3496 | } 3497 | }, 3498 | "it" : { 3499 | "stringUnit" : { 3500 | "state" : "translated", 3501 | "value" : "Applicazioni correlate che potrebbero piacerti" 3502 | } 3503 | }, 3504 | "ja" : { 3505 | "stringUnit" : { 3506 | "state" : "translated", 3507 | "value" : "関連アプリはこちら" 3508 | } 3509 | }, 3510 | "kk" : { 3511 | "stringUnit" : { 3512 | "state" : "translated", 3513 | "value" : "Ұнатуыңыз мүмкін қатысты бағдарламалар" 3514 | } 3515 | }, 3516 | "ko" : { 3517 | "stringUnit" : { 3518 | "state" : "translated", 3519 | "value" : "좋아할 만한 관련 앱" 3520 | } 3521 | }, 3522 | "ms" : { 3523 | "stringUnit" : { 3524 | "state" : "translated", 3525 | "value" : "Aplikasi berkaitan yang mungkin anda suka" 3526 | } 3527 | }, 3528 | "nl" : { 3529 | "stringUnit" : { 3530 | "state" : "translated", 3531 | "value" : "Gerelateerde apps die je misschien leuk vindt" 3532 | } 3533 | }, 3534 | "pl" : { 3535 | "stringUnit" : { 3536 | "state" : "translated", 3537 | "value" : "Powiązane aplikacje, które mogą Ci się spodobać" 3538 | } 3539 | }, 3540 | "pt-BR" : { 3541 | "stringUnit" : { 3542 | "state" : "translated", 3543 | "value" : "Aplicativos relacionados que você pode gostar" 3544 | } 3545 | }, 3546 | "pt-PT" : { 3547 | "stringUnit" : { 3548 | "state" : "translated", 3549 | "value" : "Aplicações relacionadas de que poderás gostar" 3550 | } 3551 | }, 3552 | "ro" : { 3553 | "stringUnit" : { 3554 | "state" : "translated", 3555 | "value" : "Aplicații conexe care ar putea să vă placă" 3556 | } 3557 | }, 3558 | "ru" : { 3559 | "stringUnit" : { 3560 | "state" : "translated", 3561 | "value" : "Похожие приложения, которые могут тебе понравиться" 3562 | } 3563 | }, 3564 | "sk" : { 3565 | "stringUnit" : { 3566 | "state" : "translated", 3567 | "value" : "Súvisiace aplikácie, ktoré by sa vám mohli páčiť" 3568 | } 3569 | }, 3570 | "sv" : { 3571 | "stringUnit" : { 3572 | "state" : "translated", 3573 | "value" : "Relaterade appar som du kanske gillar" 3574 | } 3575 | }, 3576 | "th" : { 3577 | "stringUnit" : { 3578 | "state" : "translated", 3579 | "value" : "แอพที่เกี่ยวข้องที่คุณอาจชอบ" 3580 | } 3581 | }, 3582 | "tr" : { 3583 | "stringUnit" : { 3584 | "state" : "translated", 3585 | "value" : "Beğenebileceğiniz ilgili uygulamalar" 3586 | } 3587 | }, 3588 | "uk" : { 3589 | "stringUnit" : { 3590 | "state" : "translated", 3591 | "value" : "Схожі програми, які можуть вам сподобатися" 3592 | } 3593 | }, 3594 | "vi" : { 3595 | "stringUnit" : { 3596 | "state" : "translated", 3597 | "value" : "Các ứng dụng có liên quan mà bạn có thể thích" 3598 | } 3599 | }, 3600 | "zh-Hans" : { 3601 | "stringUnit" : { 3602 | "state" : "translated", 3603 | "value" : "您可能喜欢的相关应用程序" 3604 | } 3605 | }, 3606 | "zh-Hant" : { 3607 | "stringUnit" : { 3608 | "state" : "translated", 3609 | "value" : "您可能喜歡的相關應用" 3610 | } 3611 | }, 3612 | "zh-HK" : { 3613 | "stringUnit" : { 3614 | "state" : "translated", 3615 | "value" : "你可能鍾意嘅相關應用" 3616 | } 3617 | } 3618 | } 3619 | }, 3620 | "Social Links" : { 3621 | "localizations" : { 3622 | "ar" : { 3623 | "stringUnit" : { 3624 | "state" : "translated", 3625 | "value" : "الروابط الاجتماعية" 3626 | } 3627 | }, 3628 | "bg" : { 3629 | "stringUnit" : { 3630 | "state" : "translated", 3631 | "value" : "Социални връзки" 3632 | } 3633 | }, 3634 | "ca" : { 3635 | "stringUnit" : { 3636 | "state" : "translated", 3637 | "value" : "Enllaços socials" 3638 | } 3639 | }, 3640 | "cs" : { 3641 | "stringUnit" : { 3642 | "state" : "translated", 3643 | "value" : "Sociální odkazy" 3644 | } 3645 | }, 3646 | "da" : { 3647 | "stringUnit" : { 3648 | "state" : "translated", 3649 | "value" : "Sociale links" 3650 | } 3651 | }, 3652 | "de" : { 3653 | "stringUnit" : { 3654 | "state" : "translated", 3655 | "value" : "Soziale Links" 3656 | } 3657 | }, 3658 | "el" : { 3659 | "stringUnit" : { 3660 | "state" : "translated", 3661 | "value" : "Κοινωνικοί σύνδεσμοι" 3662 | } 3663 | }, 3664 | "en-GB" : { 3665 | "stringUnit" : { 3666 | "state" : "translated", 3667 | "value" : "Social Links" 3668 | } 3669 | }, 3670 | "es" : { 3671 | "stringUnit" : { 3672 | "state" : "translated", 3673 | "value" : "Enlaces sociales" 3674 | } 3675 | }, 3676 | "fi" : { 3677 | "stringUnit" : { 3678 | "state" : "translated", 3679 | "value" : "Sosiaaliset linkit" 3680 | } 3681 | }, 3682 | "fr" : { 3683 | "stringUnit" : { 3684 | "state" : "translated", 3685 | "value" : "Liens sociaux" 3686 | } 3687 | }, 3688 | "fr-CA" : { 3689 | "stringUnit" : { 3690 | "state" : "translated", 3691 | "value" : "Liens sociaux" 3692 | } 3693 | }, 3694 | "he" : { 3695 | "stringUnit" : { 3696 | "state" : "translated", 3697 | "value" : "קישורים חברתיים" 3698 | } 3699 | }, 3700 | "hi" : { 3701 | "stringUnit" : { 3702 | "state" : "translated", 3703 | "value" : "सामाजिक लिंक" 3704 | } 3705 | }, 3706 | "hr" : { 3707 | "stringUnit" : { 3708 | "state" : "translated", 3709 | "value" : "Društvene veze" 3710 | } 3711 | }, 3712 | "hu" : { 3713 | "stringUnit" : { 3714 | "state" : "translated", 3715 | "value" : "Társadalmi linkek" 3716 | } 3717 | }, 3718 | "id" : { 3719 | "stringUnit" : { 3720 | "state" : "translated", 3721 | "value" : "Hubungan Sosial" 3722 | } 3723 | }, 3724 | "it" : { 3725 | "stringUnit" : { 3726 | "state" : "translated", 3727 | "value" : "Link sociali" 3728 | } 3729 | }, 3730 | "ja" : { 3731 | "stringUnit" : { 3732 | "state" : "translated", 3733 | "value" : "ソーシャル・リンク" 3734 | } 3735 | }, 3736 | "kk" : { 3737 | "stringUnit" : { 3738 | "state" : "translated", 3739 | "value" : "Әлеуметтік сілтемелер" 3740 | } 3741 | }, 3742 | "ko" : { 3743 | "stringUnit" : { 3744 | "state" : "translated", 3745 | "value" : "소셜 링크" 3746 | } 3747 | }, 3748 | "ms" : { 3749 | "stringUnit" : { 3750 | "state" : "translated", 3751 | "value" : "Pautan Sosial" 3752 | } 3753 | }, 3754 | "nl" : { 3755 | "stringUnit" : { 3756 | "state" : "translated", 3757 | "value" : "Sociale links" 3758 | } 3759 | }, 3760 | "pl" : { 3761 | "stringUnit" : { 3762 | "state" : "translated", 3763 | "value" : "Linki społecznościowe" 3764 | } 3765 | }, 3766 | "pt-BR" : { 3767 | "stringUnit" : { 3768 | "state" : "translated", 3769 | "value" : "Links sociais" 3770 | } 3771 | }, 3772 | "pt-PT" : { 3773 | "stringUnit" : { 3774 | "state" : "translated", 3775 | "value" : "Ligações sociais" 3776 | } 3777 | }, 3778 | "ro" : { 3779 | "stringUnit" : { 3780 | "state" : "translated", 3781 | "value" : "Legături sociale" 3782 | } 3783 | }, 3784 | "ru" : { 3785 | "stringUnit" : { 3786 | "state" : "translated", 3787 | "value" : "Социальные ссылки" 3788 | } 3789 | }, 3790 | "sk" : { 3791 | "stringUnit" : { 3792 | "state" : "translated", 3793 | "value" : "Sociálne odkazy" 3794 | } 3795 | }, 3796 | "sv" : { 3797 | "stringUnit" : { 3798 | "state" : "translated", 3799 | "value" : "Sociala länkar" 3800 | } 3801 | }, 3802 | "th" : { 3803 | "stringUnit" : { 3804 | "state" : "translated", 3805 | "value" : "ลิงก์โซเชียล" 3806 | } 3807 | }, 3808 | "tr" : { 3809 | "stringUnit" : { 3810 | "state" : "translated", 3811 | "value" : "Sosyal Bağlantılar" 3812 | } 3813 | }, 3814 | "uk" : { 3815 | "stringUnit" : { 3816 | "state" : "translated", 3817 | "value" : "Соціальні посилання" 3818 | } 3819 | }, 3820 | "vi" : { 3821 | "stringUnit" : { 3822 | "state" : "translated", 3823 | "value" : "Liên kết xã hội" 3824 | } 3825 | }, 3826 | "zh-Hans" : { 3827 | "stringUnit" : { 3828 | "state" : "translated", 3829 | "value" : "社会链接" 3830 | } 3831 | }, 3832 | "zh-Hant" : { 3833 | "stringUnit" : { 3834 | "state" : "translated", 3835 | "value" : "社交連結" 3836 | } 3837 | }, 3838 | "zh-HK" : { 3839 | "stringUnit" : { 3840 | "state" : "translated", 3841 | "value" : "社交連結" 3842 | } 3843 | } 3844 | } 3845 | }, 3846 | "Terms and Conditions" : { 3847 | "localizations" : { 3848 | "ar" : { 3849 | "stringUnit" : { 3850 | "state" : "translated", 3851 | "value" : "الشروط والأحكام" 3852 | } 3853 | }, 3854 | "bg" : { 3855 | "stringUnit" : { 3856 | "state" : "translated", 3857 | "value" : "Правила и условия за употреба" 3858 | } 3859 | }, 3860 | "ca" : { 3861 | "stringUnit" : { 3862 | "state" : "translated", 3863 | "value" : "Termes i condicions" 3864 | } 3865 | }, 3866 | "cs" : { 3867 | "stringUnit" : { 3868 | "state" : "translated", 3869 | "value" : "Podmínky a ujednání" 3870 | } 3871 | }, 3872 | "da" : { 3873 | "stringUnit" : { 3874 | "state" : "translated", 3875 | "value" : "Vilkår og betingelser" 3876 | } 3877 | }, 3878 | "de" : { 3879 | "stringUnit" : { 3880 | "state" : "translated", 3881 | "value" : "Nutzungsbedingungen" 3882 | } 3883 | }, 3884 | "el" : { 3885 | "stringUnit" : { 3886 | "state" : "translated", 3887 | "value" : "Όροι και προϋποθέσεις" 3888 | } 3889 | }, 3890 | "en-GB" : { 3891 | "stringUnit" : { 3892 | "state" : "translated", 3893 | "value" : "Terms and Conditions" 3894 | } 3895 | }, 3896 | "es" : { 3897 | "stringUnit" : { 3898 | "state" : "translated", 3899 | "value" : "Términos y condiciones" 3900 | } 3901 | }, 3902 | "fi" : { 3903 | "stringUnit" : { 3904 | "state" : "translated", 3905 | "value" : "Käyttöehdot" 3906 | } 3907 | }, 3908 | "fr" : { 3909 | "stringUnit" : { 3910 | "state" : "translated", 3911 | "value" : "Conditions générales" 3912 | } 3913 | }, 3914 | "fr-CA" : { 3915 | "stringUnit" : { 3916 | "state" : "translated", 3917 | "value" : "Modalités" 3918 | } 3919 | }, 3920 | "he" : { 3921 | "stringUnit" : { 3922 | "state" : "translated", 3923 | "value" : "תקנון" 3924 | } 3925 | }, 3926 | "hi" : { 3927 | "stringUnit" : { 3928 | "state" : "translated", 3929 | "value" : "नियम व शर्तें" 3930 | } 3931 | }, 3932 | "hr" : { 3933 | "stringUnit" : { 3934 | "state" : "translated", 3935 | "value" : "Odredbe i uvjeti" 3936 | } 3937 | }, 3938 | "hu" : { 3939 | "stringUnit" : { 3940 | "state" : "translated", 3941 | "value" : "Használati feltételek" 3942 | } 3943 | }, 3944 | "id" : { 3945 | "stringUnit" : { 3946 | "state" : "translated", 3947 | "value" : "Syarat dan Ketentuan" 3948 | } 3949 | }, 3950 | "it" : { 3951 | "stringUnit" : { 3952 | "state" : "translated", 3953 | "value" : "Termini e condizioni" 3954 | } 3955 | }, 3956 | "ja" : { 3957 | "stringUnit" : { 3958 | "state" : "translated", 3959 | "value" : "利用規約" 3960 | } 3961 | }, 3962 | "kk" : { 3963 | "stringUnit" : { 3964 | "state" : "translated", 3965 | "value" : "Шарттар мен талаптар" 3966 | } 3967 | }, 3968 | "ko" : { 3969 | "stringUnit" : { 3970 | "state" : "translated", 3971 | "value" : "이용 약관" 3972 | } 3973 | }, 3974 | "ms" : { 3975 | "stringUnit" : { 3976 | "state" : "translated", 3977 | "value" : "Terma dan Syarat" 3978 | } 3979 | }, 3980 | "nl" : { 3981 | "stringUnit" : { 3982 | "state" : "translated", 3983 | "value" : "Voorwaarden" 3984 | } 3985 | }, 3986 | "pl" : { 3987 | "stringUnit" : { 3988 | "state" : "translated", 3989 | "value" : "Warunki i zasady" 3990 | } 3991 | }, 3992 | "pt-BR" : { 3993 | "stringUnit" : { 3994 | "state" : "translated", 3995 | "value" : "Termos e Condições" 3996 | } 3997 | }, 3998 | "pt-PT" : { 3999 | "stringUnit" : { 4000 | "state" : "translated", 4001 | "value" : "Termos e Condições" 4002 | } 4003 | }, 4004 | "ro" : { 4005 | "stringUnit" : { 4006 | "state" : "translated", 4007 | "value" : "Termene și condiții" 4008 | } 4009 | }, 4010 | "ru" : { 4011 | "stringUnit" : { 4012 | "state" : "translated", 4013 | "value" : "Положения и условия" 4014 | } 4015 | }, 4016 | "sk" : { 4017 | "stringUnit" : { 4018 | "state" : "translated", 4019 | "value" : "Zmluvné podmienky" 4020 | } 4021 | }, 4022 | "sv" : { 4023 | "stringUnit" : { 4024 | "state" : "translated", 4025 | "value" : "Användarvillkor" 4026 | } 4027 | }, 4028 | "th" : { 4029 | "stringUnit" : { 4030 | "state" : "translated", 4031 | "value" : "ข้อกำหนดและเงื่อนไข" 4032 | } 4033 | }, 4034 | "tr" : { 4035 | "stringUnit" : { 4036 | "state" : "translated", 4037 | "value" : "Hüküm ve Koşullar" 4038 | } 4039 | }, 4040 | "uk" : { 4041 | "stringUnit" : { 4042 | "state" : "translated", 4043 | "value" : "Умови та положення" 4044 | } 4045 | }, 4046 | "vi" : { 4047 | "stringUnit" : { 4048 | "state" : "translated", 4049 | "value" : "Điều khoản và điều kiện" 4050 | } 4051 | }, 4052 | "zh-Hans" : { 4053 | "stringUnit" : { 4054 | "state" : "translated", 4055 | "value" : "条款与条件" 4056 | } 4057 | }, 4058 | "zh-Hant" : { 4059 | "stringUnit" : { 4060 | "state" : "translated", 4061 | "value" : "條款與約定" 4062 | } 4063 | }, 4064 | "zh-HK" : { 4065 | "stringUnit" : { 4066 | "state" : "translated", 4067 | "value" : "條款及細則" 4068 | } 4069 | } 4070 | } 4071 | } 4072 | }, 4073 | "version" : "1.0" 4074 | } -------------------------------------------------------------------------------- /Sources/LinksKit/Model/Link.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | /// Represents a link with a title, system image, and URL. 4 | /// 5 | /// Use this struct to create custom links or use the provided static methods for common link types. 6 | public struct Link: Identifiable { 7 | public let id: UUID = UUID() 8 | let title: String 9 | let systemImage: String 10 | let url: URL 11 | 12 | /// Creates a new Link instance. 13 | /// 14 | /// - Parameters: 15 | /// - title: The display title for the link. 16 | /// - systemImage: The name of the system image to use as an icon. 17 | /// - url: The URL the link should open. 18 | /// 19 | /// Example usage: 20 | /// ```swift 21 | /// let customLink = Link( 22 | /// title: "Visit Our Website", 23 | /// systemImage: "globe", 24 | /// url: URL(string: "https://www.example.com")! 25 | /// ) 26 | /// ``` 27 | public init(title: String, systemImage: String, url: URL) { 28 | self.title = title 29 | self.systemImage = systemImage 30 | self.url = url 31 | } 32 | } 33 | 34 | extension Link { 35 | /// Creates a link to rate the app on the App Store. 36 | /// 37 | /// - Parameter id: The App Store ID of your app. 38 | /// - Returns: A Link instance for rating the app. 39 | /// 40 | /// Example usage: 41 | /// ```swift 42 | /// let rateLink = Link.rateTheApp(id: "1234567890") 43 | /// ``` 44 | public static func rateTheApp(id: String) -> Self { 45 | Link( 46 | title: String(localized: "Rate the App", bundle: .module), 47 | systemImage: "star", 48 | url: URL(string: "https://apps.apple.com/app/apple-store/id\(id)?action=write-review")! 49 | ) 50 | } 51 | 52 | /// Creates a link to a Frequently Asked Questions (FAQ) page. 53 | /// 54 | /// - Parameter url: The URL of your FAQ page. 55 | /// - Returns: A Link instance for the FAQ. 56 | /// 57 | /// Example usage: 58 | /// ```swift 59 | /// let faqLink = Link.frequentlyAskedQuestions(url: URL(string: "https://www.example.com/faq")!) 60 | /// ``` 61 | public static func frequentlyAskedQuestions(url: URL) -> Self { 62 | Link(title: String(localized: "Frequently Asked Questions (FAQ)", bundle: .module), systemImage: "questionmark.bubble", url: url) 63 | } 64 | 65 | /// Creates a link to contact support via email. 66 | /// 67 | /// - Parameter email: The support email address. 68 | /// - Returns: A Link instance for contacting support. 69 | /// 70 | /// Example usage: 71 | /// ```swift 72 | /// let supportLink = Link.contactSupport(email: "support@example.com") 73 | /// ``` 74 | public static func contactSupport(email: String) -> Self { 75 | Link(title: String(localized: "Contact Support", bundle: .module), systemImage: "envelope", url: URL(string: "mailto:\(email)")!) 76 | } 77 | 78 | /// Creates a link to the privacy policy. 79 | /// 80 | /// - Parameter url: The URL of your privacy policy. 81 | /// - Returns: A Link instance for the privacy policy. 82 | /// 83 | /// Example usage: 84 | /// ```swift 85 | /// let privacyLink = Link.privacyPolicy(url: URL(string: "https://www.example.com/privacy")!) 86 | /// ``` 87 | public static func privacyPolicy(url: URL) -> Self { 88 | Link(title: String(localized: "Privacy Policy", bundle: .module), systemImage: "lock.shield", url: url) 89 | } 90 | 91 | /// Creates a link to the standard App Store Terms and Conditions. 92 | /// 93 | /// - Returns: A Link instance for the App Store Terms and Conditions. 94 | /// 95 | /// Example usage: 96 | /// ```swift 97 | /// let termsLink = Link.appStoreTermsAndConditions() 98 | /// ``` 99 | public static func appStoreTermsAndConditions() -> Self { 100 | .termsAndConditions(url: URL(string: "https://www.apple.com/legal/internet-services/itunes/dev/stdeula/")!) 101 | } 102 | 103 | /// Creates a link to custom Terms and Conditions. 104 | /// 105 | /// - Parameter url: The URL of your Terms and Conditions. 106 | /// - Returns: A Link instance for the Terms and Conditions. 107 | /// 108 | /// Example usage: 109 | /// ```swift 110 | /// let customTermsLink = Link.termsAndConditions(url: URL(string: "https://www.example.com/terms")!) 111 | /// ``` 112 | public static func termsAndConditions(url: URL) -> Self { 113 | Link(title: String(localized: "Terms and Conditions", bundle: .module), systemImage: "text.book.closed", url: url) 114 | } 115 | 116 | /// Creates a link to follow the app on a social media platform. 117 | /// 118 | /// - Parameters: 119 | /// - socialPlatform: The social media platform. 120 | /// - handle: The app's handle or username on the platform. 121 | /// - Returns: A Link instance for following the app on social media. 122 | /// 123 | /// Example usage: 124 | /// ```swift 125 | /// let twitterFollowLink = Link.followUsOn(socialPlatform: .twitter, handle: "YourAppHandle") 126 | /// ``` 127 | public static func followUsOn(socialPlatform: SocialPlatform, handle: String) -> Self { 128 | Link( 129 | title: String(localized: "Follow us on \(socialPlatform.description)"), 130 | systemImage: socialPlatform.systemImage, 131 | url: socialPlatform.url(handle: handle) 132 | ) 133 | } 134 | 135 | /// Creates a link to the developer's profile on a social media platform. 136 | /// 137 | /// - Parameters: 138 | /// - socialPlatform: The social media platform. 139 | /// - handle: The developer's handle or username on the platform. 140 | /// - Returns: A Link instance for the developer's social media profile. 141 | /// 142 | /// Example usage: 143 | /// ```swift 144 | /// let devTwitterLink = Link.developerOn(socialPlatform: .twitter, handle: "YourDevHandle") 145 | /// ``` 146 | public static func developerOn(socialPlatform: SocialPlatform, handle: String) -> Self { 147 | Link( 148 | title: String(localized: "Developer on \(socialPlatform.description)", bundle: .module), 149 | systemImage: socialPlatform.systemImage, 150 | url: socialPlatform.url(handle: handle) 151 | ) 152 | } 153 | 154 | /// Creates a link to the app's profile on a social media platform. 155 | /// 156 | /// - Parameters: 157 | /// - socialPlatform: The social media platform. 158 | /// - handle: The app's handle or username on the platform. 159 | /// - Returns: A Link instance for the app's social media profile. 160 | /// 161 | /// Example usage: 162 | /// ```swift 163 | /// let appInstagramLink = Link.appOn(socialPlatform: .instagram, handle: "YourAppHandle") 164 | /// ``` 165 | public static func appOn(socialPlatform: SocialPlatform, handle: String) -> Self { 166 | Link( 167 | title: String(localized: "App on \(socialPlatform.description)", bundle: .module), 168 | systemImage: socialPlatform.systemImage, 169 | url: socialPlatform.url(handle: handle) 170 | ) 171 | } 172 | 173 | /// Creates a link to one of your own apps on the App Store. 174 | /// 175 | /// - Parameters: 176 | /// - id: The App Store ID of the app. 177 | /// - name: The name of the app. 178 | /// - systemImage: The system image name to use as an icon. 179 | /// - campaignToken: An optional campaign token for tracking. Defaults to the main bundle identifier. 180 | /// - Returns: A Link instance for your own app. 181 | /// 182 | /// Example usage: 183 | /// ```swift 184 | /// let myOtherAppLink = Link.ownApp( 185 | /// id: "1234567890", 186 | /// name: "My Other App", 187 | /// systemImage: "star.circle", 188 | /// campaignToken: "myOtherApp" 189 | /// ) 190 | /// ``` 191 | public static func ownApp( 192 | id: String, 193 | name: String, 194 | systemImage: String, 195 | campaignToken: String = Bundle.main.bundleIdentifier ?? "com.default.identifier" 196 | ) -> Self { 197 | Link( 198 | title: name, 199 | systemImage: systemImage, 200 | url: URL(string: "https://apps.apple.com/app/id\(id)?pt=\(LinksKit.providerToken)&ct=\(campaignToken)&mt=8")! 201 | ) 202 | } 203 | 204 | /// Creates a link to a friend's app on the App Store. 205 | /// 206 | /// - Parameters: 207 | /// - id: The App Store ID of the app. 208 | /// - name: The name of the app. 209 | /// - systemImage: The system image name to use as an icon. 210 | /// - providerToken: An optional provider token for the app's developer. 211 | /// - campaignToken: An optional campaign token for tracking. Defaults to the main bundle identifier. 212 | /// - Returns: A Link instance for a friend's app. 213 | /// 214 | /// Example usage: 215 | /// ```swift 216 | /// let friendAppLink = Link.friendsApp( 217 | /// id: "0987654321", 218 | /// name: "Friend's Cool App", 219 | /// systemImage: "paintbrush", 220 | /// providerToken: "123456", 221 | /// campaignToken: "friendCoolApp" 222 | /// ) 223 | /// ``` 224 | public static func friendsApp( 225 | id: String, 226 | name: String, 227 | systemImage: String, 228 | providerToken: String? = nil, 229 | campaignToken: String = Bundle.main.bundleIdentifier ?? "com.default.identifier" 230 | ) -> Self { 231 | if let providerToken { 232 | Link( 233 | title: name, 234 | systemImage: systemImage, 235 | url: URL(string: "https://apps.apple.com/app/id\(id)?pt=\(providerToken)&ct=\(campaignToken)&mt=8")! 236 | ) 237 | } else { 238 | Link( 239 | title: name, 240 | systemImage: systemImage, 241 | url: URL(string: "https://apps.apple.com/app/id\(id)?ct=\(campaignToken)&mt=8")! 242 | ) 243 | } 244 | } 245 | } 246 | -------------------------------------------------------------------------------- /Sources/LinksKit/Model/LinkMenu.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// Represents a menu containing multiple link sections. 4 | /// 5 | /// Use this struct to create grouped links that can be displayed in a submenu. 6 | public struct LinkMenu: Identifiable { 7 | public let id: UUID = UUID() 8 | let title: String 9 | let systemImage: String 10 | let linkSections: [LinkSection] 11 | 12 | /// Creates a new LinkMenu instance. 13 | /// 14 | /// - Parameters: 15 | /// - title: The display title for the menu. 16 | /// - systemImage: The name of the system image to use as an icon. 17 | /// - linkSections: An array of LinkSection instances to include in the menu. 18 | /// 19 | /// Example usage: 20 | /// ```swift 21 | /// let customMenu = LinkMenu( 22 | /// title: "Social Media", 23 | /// systemImage: "network", 24 | /// linkSections: [ 25 | /// LinkSection(entries: [ 26 | /// .link(Link.followUsOn(socialPlatform: .twitter, handle: "YourAppHandle")), 27 | /// .link(Link.followUsOn(socialPlatform: .instagram, handle: "YourAppHandle")) 28 | /// ]) 29 | /// ] 30 | /// ) 31 | /// ``` 32 | public init(title: String, systemImage: String, linkSections: [LinkSection]) { 33 | self.title = title 34 | self.systemImage = systemImage 35 | self.linkSections = linkSections 36 | } 37 | } 38 | 39 | extension LinkMenu { 40 | /// Creates a menu for following the app on various social media platforms. 41 | /// 42 | /// - Parameter links: An array of Link instances for different social media platforms. 43 | /// - Returns: A LinkMenu instance for following the app. 44 | /// 45 | /// Example usage: 46 | /// ```swift 47 | /// let followAppMenu = LinkMenu.followTheApp(links: [ 48 | /// Link.followUsOn(socialPlatform: .twitter, handle: "YourAppHandle"), 49 | /// Link.followUsOn(socialPlatform: .instagram, handle: "YourAppHandle") 50 | /// ]) 51 | /// ``` 52 | public static func followTheApp(links: [Link]) -> Self { 53 | LinkMenu( 54 | title: String(localized: "Follow the App", bundle: .module), 55 | systemImage: "app.badge", 56 | linkSections: [LinkSection(entries: links.map(LinkSection.Entry.link))] 57 | ) 58 | } 59 | 60 | /// Creates a menu for following the developer on various social media platforms. 61 | /// 62 | /// - Parameter links: An array of Link instances for different social media platforms. 63 | /// - Returns: A LinkMenu instance for following the developer. 64 | /// 65 | /// Example usage: 66 | /// ```swift 67 | /// let followDevMenu = LinkMenu.followTheDeveloper(links: [ 68 | /// Link.developerOn(socialPlatform: .twitter, handle: "YourDevHandle"), 69 | /// Link.developerOn(socialPlatform: .github, handle: "YourDevHandle") 70 | /// ]) 71 | /// ``` 72 | public static func followTheDeveloper(links: [Link]) -> Self { 73 | LinkMenu( 74 | title: String(localized: "Follow the Developer", bundle: .module), 75 | systemImage: "person", 76 | linkSections: [LinkSection(entries: links.map(LinkSection.Entry.link))] 77 | ) 78 | } 79 | 80 | /// Creates a menu for showcasing more apps from the developer. 81 | /// 82 | /// - Parameter linkSections: An array of LinkSection instances, each potentially representing a category of apps. 83 | /// - Returns: A LinkMenu instance for more apps from the developer. 84 | /// 85 | /// Example usage: 86 | /// ```swift 87 | /// let moreAppsMenu = LinkMenu.moreAppsFromDeveloper(linkSections: [ 88 | /// LinkSection(title: "Productivity Apps", entries: [ 89 | /// .link(Link.ownApp(id: "1234567890", name: "Todo Master", systemImage: "checklist")), 90 | /// .link(Link.ownApp(id: "0987654321", name: "Focus Timer", systemImage: "timer")) 91 | /// ]), 92 | /// LinkSection(title: "Entertainment Apps", entries: [ 93 | /// .link(Link.ownApp(id: "1122334455", name: "Puzzle Quest", systemImage: "puzzle")) 94 | /// ]) 95 | /// ]) 96 | /// ``` 97 | public static func moreAppsFromDeveloper(linkSections: [LinkSection]) -> Self { 98 | LinkMenu( 99 | title: String(localized: "More apps from Developer", bundle: .module), 100 | systemImage: "plus.square.on.square", 101 | linkSections: linkSections 102 | ) 103 | } 104 | 105 | /// Creates a menu for showcasing related apps that users might like. 106 | /// 107 | /// - Parameter linkSections: An array of LinkSection instances, each potentially representing a category of related apps. 108 | /// - Returns: A LinkMenu instance for related apps. 109 | /// 110 | /// Example usage: 111 | /// ```swift 112 | /// let relatedAppsMenu = LinkMenu.relatedAppsYouMightLike(linkSections: [ 113 | /// LinkSection(title: "Similar Productivity Apps", entries: [ 114 | /// .link(Link.friendsApp(id: "2233445566", name: "Task Pro", systemImage: "list.bullet", providerToken: "654321")), 115 | /// .link(Link.friendsApp(id: "3344556677", name: "Time Tracker", systemImage: "stopwatch", providerToken: "765432")) 116 | /// ]) 117 | /// ]) 118 | /// ``` 119 | public static func relatedAppsYouMightLike(linkSections: [LinkSection]) -> Self { 120 | LinkMenu( 121 | title: String(localized: "Related apps you might Like", bundle: .module), 122 | systemImage: "star.square.on.square", 123 | linkSections: linkSections 124 | ) 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /Sources/LinksKit/Model/LinkSection.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | /// Represents a section of links or submenus. 4 | public struct LinkSection: Identifiable { 5 | /// Represents an entry in a LinkSection, which can be either a Link or a LinkMenu. 6 | public enum Entry: Identifiable { 7 | case link(Link) 8 | case menu(LinkMenu) 9 | 10 | public var id: UUID { 11 | switch self { 12 | case .link(let link): link.id 13 | case .menu(let linkMenu): linkMenu.id 14 | } 15 | } 16 | } 17 | 18 | public let id: UUID = UUID() 19 | let title: String? 20 | let entries: [Entry] 21 | 22 | /// Creates a new LinkSection instance. 23 | /// 24 | /// - Parameters: 25 | /// - title: An optional title for the section. 26 | /// - entries: An array of Entry instances (links or menus) to include in the section. 27 | /// 28 | /// Example usage: 29 | /// ```swift 30 | /// let customSection = LinkSection( 31 | /// title: "Custom Links", 32 | /// entries: [ 33 | /// .link(Link(title: "Our Website", systemImage: "globe", url: URL(string: "https://www.example.com")!)), 34 | /// .menu(LinkMenu.followTheApp(links: [ 35 | /// Link.followUsOn(socialPlatform: .twitter, handle: "YourAppHandle") 36 | /// ])) 37 | /// ] 38 | /// ) 39 | /// ``` 40 | public init(title: String? = nil, entries: [Entry]) { 41 | self.title = title 42 | self.entries = entries 43 | } 44 | } 45 | 46 | extension LinkSection { 47 | /// Creates a section with help-related links. 48 | /// 49 | /// - Parameters: 50 | /// - appID: The App Store ID of your app. 51 | /// - faqURL: An optional URL to your FAQ page. 52 | /// - supportEmail: The email address for support inquiries. 53 | /// - Returns: A LinkSection instance with help links. 54 | /// 55 | /// Example usage: 56 | /// ```swift 57 | /// let helpSection = LinkSection.helpLinks( 58 | /// appID: "1234567890", 59 | /// faqURL: URL(string: "https://www.example.com/faq"), 60 | /// supportEmail: "support@example.com" 61 | /// ) 62 | /// ``` 63 | public static func helpLinks(appID: String, faqURL: URL? = nil, supportEmail: String) -> Self { 64 | if let faqURL { 65 | LinkSection( 66 | title: String(localized: "Help", bundle: .module), 67 | entries: [ 68 | .link(.rateTheApp(id: appID)), 69 | .link(.frequentlyAskedQuestions(url: faqURL)), 70 | .link(.contactSupport(email: supportEmail)), 71 | ] 72 | ) 73 | } else { 74 | LinkSection( 75 | title: String(localized: "Help", bundle: .module), 76 | entries: [ 77 | .link(.rateTheApp(id: appID)), 78 | .link(.contactSupport(email: supportEmail)), 79 | ] 80 | ) 81 | } 82 | } 83 | 84 | /// Creates a section with social media links for the app. 85 | /// 86 | /// - Parameters: 87 | /// - platforms: An array of SocialPlatform instances to include. 88 | /// - handle: The default handle or username for the app on these platforms. 89 | /// - handleOverrides: A dictionary to specify different handles for specific platforms. 90 | /// - Returns: A LinkSection instance with app social media links. 91 | /// 92 | /// Example usage: 93 | /// ```swift 94 | /// let appSocialSection = LinkSection.appSocialLinks( 95 | /// platforms: [.twitter, .instagram, .facebook], 96 | /// handle: "YourAppHandle", 97 | /// handleOverrides: [.twitter: "YourAppTwitter"] 98 | /// ) 99 | /// ``` 100 | public static func appSocialLinks( 101 | title: String? = nil, 102 | platforms: [SocialPlatform], 103 | handle: String, 104 | handleOverrides: [SocialPlatform: String] = [:] 105 | ) -> Self { 106 | LinkSection(title: title, entries: platforms.map { .link(.appOn(socialPlatform: $0, handle: handleOverrides[$0] ?? handle)) }) 107 | } 108 | 109 | /// Creates a section with social media links for the developer. 110 | /// 111 | /// - Parameters: 112 | /// - platforms: An array of SocialPlatform instances to include. 113 | /// - handle: The default handle or username for the developer on these platforms. 114 | /// - handleOverrides: A dictionary to specify different handles for specific platforms. 115 | /// - Returns: A LinkSection instance with developer social media links. 116 | /// 117 | /// Example usage: 118 | /// ```swift 119 | /// let devSocialSection = LinkSection.developerSocialLinks( 120 | /// platforms: [.twitter, .github, .linkedin], 121 | /// handle: "YourDevHandle", 122 | /// handleOverrides: [.github: "YourGitHubUsername"] 123 | /// ) 124 | /// ``` 125 | public static func developerSocialLinks( 126 | title: String? = nil, 127 | platforms: [SocialPlatform], 128 | handle: String, 129 | handleOverrides: [SocialPlatform: String] = [:] 130 | ) -> Self { 131 | LinkSection(title: title, entries: platforms.map { .link(.developerOn(socialPlatform: $0, handle: handleOverrides[$0] ?? handle)) }) 132 | } 133 | 134 | /// Creates a section with social media menus for both the app and the developer. 135 | /// 136 | /// - Parameters: 137 | /// - appLinks: A LinkSection containing app social media links. 138 | /// - developerLinks: A LinkSection containing developer social media links. 139 | /// - Returns: A LinkSection instance with social media menus. 140 | /// 141 | /// Example usage: 142 | /// ```swift 143 | /// let socialMenusSection = LinkSection.socialMenus( 144 | /// appLinks: LinkSection.appSocialLinks(platforms: [.twitter, .instagram], handle: "YourAppHandle"), 145 | /// developerLinks: LinkSection.developerSocialLinks(platforms: [.twitter, .github], handle: "YourDevHandle") 146 | /// ) 147 | /// ``` 148 | public static func socialMenus(appLinks: LinkSection, developerLinks: LinkSection) -> Self { 149 | LinkSection( 150 | title: String(localized: "Social Links", bundle: .module), 151 | entries: [ 152 | .menu(LinkMenu(title: String(localized: "Follow the App", bundle: .module), systemImage: "app.badge", linkSections: [appLinks])), 153 | .menu(LinkMenu(title: String(localized: "Follow the Developer", bundle: .module), systemImage: "person", linkSections: [developerLinks])), 154 | ] 155 | ) 156 | } 157 | 158 | /// Creates a section with menus for the developer's own apps and friends' apps. 159 | /// 160 | /// - Parameters: 161 | /// - ownAppLinks: An array of LinkSection instances for the developer's own apps. 162 | /// - friendsAppLinks: An array of LinkSection instances for friends' apps. 163 | /// - Returns: A LinkSection instance with app menus. 164 | /// 165 | /// Example usage: 166 | /// ```swift 167 | /// let appMenusSection = LinkSection.appMenus( 168 | /// ownAppLinks: [ 169 | /// LinkSection(title: "Productivity", entries: [ 170 | /// .link(Link.ownApp(id: "1234567890", name: "Todo Master", systemImage: "checklist")) 171 | /// ]) 172 | /// ], 173 | /// friendsAppLinks: [ 174 | /// LinkSection(title: "Games", entries: [ 175 | /// .link(Link.friendsApp(id: "0987654321", name: "Puzzle Quest", systemImage: "puzzle", providerToken: "123456")) 176 | /// ]) 177 | /// ] 178 | /// ) 179 | /// ``` 180 | public static func appMenus(ownAppLinks: [LinkSection], friendsAppLinks: [LinkSection]) -> Self { 181 | LinkSection( 182 | title: String(localized: "App Links", bundle: .module), 183 | entries: [ 184 | .menu( 185 | LinkMenu(title: String(localized: "More Apps from Developer", bundle: .module), systemImage: "plus.square.on.square", linkSections: ownAppLinks) 186 | ), 187 | .menu(LinkMenu(title: String(localized: "Apps from Friends", bundle: .module), systemImage: "hand.thumbsup", linkSections: friendsAppLinks)), 188 | ] 189 | ) 190 | } 191 | 192 | /// Creates a section with legal links, including App Store Terms and Conditions and Privacy Policy. 193 | /// 194 | /// - Parameter privacyURL: The URL to your privacy policy. 195 | /// - Returns: A LinkSection instance with legal links. 196 | /// 197 | /// Example usage: 198 | /// ```swift 199 | /// let legalSection = LinkSection.legalLinks(privacyURL: URL(string: "https://www.example.com/privacy")!) 200 | /// ``` 201 | public static func legalLinks(privacyURL: URL) -> Self { 202 | LinkSection( 203 | title: String(localized: "Legal", bundle: .module), 204 | entries: [ 205 | .link(.appStoreTermsAndConditions()), 206 | .link(.privacyPolicy(url: privacyURL)), 207 | ] 208 | ) 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /Sources/LinksKit/Model/SocialPlatform.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// Represents various social media platforms. 4 | /// 5 | /// Use this enum to specify social media platforms when configuring social links in LinksKit. 6 | public enum SocialPlatform: Hashable { 7 | case bluesky 8 | case facebook 9 | case github 10 | case instagram 11 | case linkedin 12 | case mastodon(instance: String) 13 | case pinterest 14 | case reddit 15 | case threads 16 | case tiktok 17 | case twitter 18 | case youtube 19 | 20 | var systemImage: String { 21 | switch self { 22 | case .bluesky: "b.circle.fill" 23 | case .facebook: "hand.thumbsup" 24 | case .github: "cat.circle.fill" 25 | case .instagram: "camera.circle" 26 | case .linkedin: "point.topleft.down.to.point.bottomright.curvepath" 27 | case .mastodon: "square.split.1x2" 28 | case .pinterest: "pin.circle" 29 | case .reddit: "antenna.radiowaves.left.and.right.circle" 30 | case .threads: "at.circle" 31 | case .tiktok: "music.note" 32 | case .twitter: "bird" 33 | case .youtube: "play.rectangle.fill" 34 | } 35 | } 36 | 37 | func url(handle: String) -> URL { 38 | switch self { 39 | case .bluesky: URL(string: "https://bsky.app/profile/\(handle)")! 40 | case .facebook: URL(string: "https://facebook.com/\(handle)")! 41 | case .github: URL(string: "https://github.com/\(handle)")! 42 | case .instagram: URL(string: "https://instagram.com/\(handle)")! 43 | case .linkedin: URL(string: "https://www.linkedin.com/in/\(handle)")! 44 | case .mastodon(let instance): URL(string: "https://\(instance)/@\(handle)")! 45 | case .pinterest: URL(string: "https://pinterest.com/\(handle)")! 46 | case .reddit: URL(string: "https://reddit.com/user/\(handle)")! 47 | case .threads: URL(string: "https://www.threads.net/@\(handle)")! 48 | case .tiktok: URL(string: "https://www.tiktok.com/@\(handle)")! 49 | case .twitter: URL(string: "https://twitter.com/\(handle)")! 50 | case .youtube: URL(string: "https://www.youtube.com/\(handle)")! 51 | } 52 | } 53 | } 54 | 55 | extension SocialPlatform: CustomStringConvertible { 56 | /// A human-readable description of the social platform. 57 | /// 58 | /// This property is useful for displaying the name of the social platform in your UI. 59 | /// 60 | /// Example usage: 61 | /// ```swift 62 | /// let platformName = SocialPlatform.twitter.description // Returns "X/Twitter" 63 | /// ``` 64 | public var description: String { 65 | switch self { 66 | case .bluesky: "Bluesky" 67 | case .facebook: "Facebook" 68 | case .github: "GitHub" 69 | case .instagram: "Instagram" 70 | case .linkedin: "LinkedIn" 71 | case .mastodon: "Mastodon" 72 | case .pinterest: "Pinterest" 73 | case .reddit: "Reddit" 74 | case .threads: "Threads" 75 | case .tiktok: "TikTok" 76 | case .twitter: "X/Twitter" 77 | case .youtube: "YouTube" 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Sources/LinksKit/Styles/TitleAndIconBadgeLabelStyle.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | /// A custom `LabelStyle` that displays the icon as a colored badge with the title next to it. This resembles the same look as Apple uses in the Settings app. 4 | /// 5 | /// This style is useful for creating visually appealing labels with a colored icon badge, commonly used in list items or navigation elements. 6 | public struct TitleAndIconBadgeLabelStyle: LabelStyle { 7 | /// The color of the icon badge. 8 | let color: Color 9 | 10 | /// Creates a view representing the body of a label. 11 | /// 12 | /// - Parameter configuration: The properties of the label. 13 | /// - Returns: A view that represents the label with the custom style applied. 14 | /// 15 | /// This method creates a horizontal stack with a colored badge containing the icon, followed by the title. The badge size adjusts to match the height of the label. 16 | public func makeBody(configuration: Configuration) -> some View { 17 | GeometryReader { proxy in 18 | HStack { 19 | Group { 20 | RoundedRectangle(cornerRadius: 8) 21 | .fill(self.color) 22 | .overlay(configuration.icon.foregroundStyle(.white).font(.body)) 23 | .padding(4) 24 | } 25 | .frame(width: proxy.size.height, height: proxy.size.height) 26 | .padding(.leading, -8) 27 | 28 | configuration.title 29 | } 30 | } 31 | } 32 | } 33 | 34 | extension LabelStyle where Self == TitleAndIconBadgeLabelStyle { 35 | /// Creates a `TitleAndIconBadgeLabelStyle` with the specified badge color. This resembles the same look as Apple uses in the Settings app. 36 | /// 37 | /// This static method provides a convenient way to create and apply the custom label style. 38 | /// 39 | /// - Parameter color: The color to be used for the icon badge. 40 | /// - Returns: A `TitleAndIconBadgeLabelStyle` instance with the specified color. 41 | /// 42 | /// Example usage: 43 | /// ``` 44 | /// VStack { 45 | /// Label("Profile", systemImage: "person") 46 | /// .labelStyle(.titleAndIconBadge(color: .green)) 47 | /// Label("Messages", systemImage: "message") 48 | /// .labelStyle(.titleAndIconBadge(color: .blue)) 49 | /// } 50 | /// ``` 51 | public static func titleAndIconBadge(color: Color) -> TitleAndIconBadgeLabelStyle { 52 | TitleAndIconBadgeLabelStyle(color: color) 53 | } 54 | } 55 | 56 | #if DEBUG 57 | #Preview { 58 | Form { 59 | Section("Label Styles: .labelStyle(...)") { 60 | Label(String(".titleAndIcon (SwiftUI Default)"), systemImage: "magnifyingglass") 61 | .labelStyle(.titleAndIcon) 62 | 63 | Label(String(".titleAndTrailingIcon"), systemImage: "magnifyingglass") 64 | .labelStyle(.titleAndTrailingIcon) 65 | 66 | Label(String(".titleAndIconBadge(color: .red)"), systemImage: "magnifyingglass") 67 | .labelStyle(.titleAndIconBadge(color: .red)) 68 | 69 | Label(String(".titleAndTrailingIconBadge(color: .red)"), systemImage: "magnifyingglass") 70 | .labelStyle(.titleAndTrailingIconBadge(color: .red)) 71 | } 72 | .textCase(.none) 73 | } 74 | } 75 | #endif 76 | -------------------------------------------------------------------------------- /Sources/LinksKit/Styles/TitleAndTrailingIconBadgeLabelStyle.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | /// A custom `LabelStyle` that displays the title with a colored icon badge trailing at the end. 4 | /// 5 | /// This style is useful for creating labels with a trailing colored icon badge, 6 | /// commonly used in list items or settings menus where you want to emphasize the trailing icon. 7 | public struct TitleAndTrailingIconBadgeLabelStyle: LabelStyle { 8 | /// The color of the icon badge. 9 | let color: Color 10 | 11 | /// Creates a view representing the body of a label. 12 | /// 13 | /// - Parameter configuration: The properties of the label. 14 | /// - Returns: A view that represents the label with the custom style applied. 15 | /// 16 | /// This method creates a horizontal stack with the title, followed by a spacer, 17 | /// and then a colored badge containing the icon. The badge size adjusts to match the height of the label. 18 | public func makeBody(configuration: Configuration) -> some View { 19 | GeometryReader { proxy in 20 | HStack { 21 | configuration.title 22 | 23 | Spacer() 24 | 25 | Group { 26 | RoundedRectangle(cornerRadius: 8) 27 | .fill(self.color) 28 | .overlay(configuration.icon.foregroundStyle(.white).font(.body)) 29 | .padding(4) 30 | } 31 | .frame(width: proxy.size.height, height: proxy.size.height) 32 | .padding(.trailing, -8) 33 | } 34 | } 35 | } 36 | } 37 | 38 | extension LabelStyle where Self == TitleAndTrailingIconBadgeLabelStyle { 39 | /// Creates a `TitleAndTrailingIconBadgeLabelStyle` with the specified badge color. 40 | /// 41 | /// This static method provides a convenient way to create and apply the custom label style. 42 | /// 43 | /// - Parameter color: The color to be used for the icon badge. 44 | /// - Returns: A `TitleAndTrailingIconBadgeLabelStyle` instance with the specified color. 45 | /// 46 | /// Example usage: 47 | /// ``` 48 | /// VStack { 49 | /// Label("Wi-Fi", systemImage: "wifi") 50 | /// .labelStyle(.titleAndTrailingIconBadge(color: .blue)) 51 | /// Label("Bluetooth", systemImage: "bluetooth") 52 | /// .labelStyle(.titleAndTrailingIconBadge(color: .green)) 53 | /// Label("Airplane Mode", systemImage: "airplane") 54 | /// .labelStyle(.titleAndTrailingIconBadge(color: .orange)) 55 | /// } 56 | /// ``` 57 | public static func titleAndTrailingIconBadge(color: Color) -> TitleAndTrailingIconBadgeLabelStyle { 58 | TitleAndTrailingIconBadgeLabelStyle(color: color) 59 | } 60 | } 61 | 62 | #if DEBUG 63 | #Preview { 64 | Form { 65 | Section("Label Styles: .labelStyle(...)") { 66 | Label(String(".titleAndIcon (SwiftUI Default)"), systemImage: "magnifyingglass") 67 | .labelStyle(.titleAndIcon) 68 | 69 | Label(String(".titleAndTrailingIcon"), systemImage: "magnifyingglass") 70 | .labelStyle(.titleAndTrailingIcon) 71 | 72 | Label(String(".titleAndIconBadge(color: .red)"), systemImage: "magnifyingglass") 73 | .labelStyle(.titleAndIconBadge(color: .red)) 74 | 75 | Label(String(".titleAndTrailingIconBadge(color: .red)"), systemImage: "magnifyingglass") 76 | .labelStyle(.titleAndTrailingIconBadge(color: .red)) 77 | } 78 | .textCase(.none) } 79 | } 80 | #endif 81 | -------------------------------------------------------------------------------- /Sources/LinksKit/Styles/TitleAndTrailingIconLabelStyle.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | /// A custom `LabelStyle` that displays the title with an icon trailing at the end. 4 | /// 5 | /// This style is useful for creating labels with a trailing icon, 6 | /// commonly used in list items or menu entries where you want to emphasize the trailing icon. 7 | public struct TitleAndTrailingIconLabelStyle: LabelStyle { 8 | /// Creates a view representing the body of a label. 9 | /// 10 | /// - Parameter configuration: The properties of the label. 11 | /// - Returns: A view that represents the label with the custom style applied. 12 | /// 13 | /// This method creates a horizontal stack with the title, followed by a spacer, 14 | /// and then the icon at the trailing edge. 15 | public func makeBody(configuration: Configuration) -> some View { 16 | HStack { 17 | configuration.title 18 | 19 | Spacer() 20 | 21 | configuration.icon 22 | } 23 | } 24 | } 25 | 26 | extension LabelStyle where Self == TitleAndTrailingIconLabelStyle { 27 | /// A static property that returns a `TitleAndTrailingIconLabelStyle` instance. 28 | /// 29 | /// This property provides a convenient way to apply the custom label style. 30 | /// 31 | /// Example usage: 32 | /// ``` 33 | /// List { 34 | /// Label("Profile", systemImage: "person.circle") 35 | /// .labelStyle(.titleAndTrailingIcon) 36 | /// Label("Settings", systemImage: "gear") 37 | /// .labelStyle(.titleAndTrailingIcon) 38 | /// Label("Logout", systemImage: "arrow.right.square") 39 | /// .labelStyle(.titleAndTrailingIcon) 40 | /// } 41 | /// ``` 42 | public static var titleAndTrailingIcon: TitleAndTrailingIconLabelStyle { TitleAndTrailingIconLabelStyle() } 43 | } 44 | 45 | #if DEBUG 46 | #Preview { 47 | Form { 48 | Section("Label Styles: .labelStyle(...)") { 49 | Label(String(".titleAndIcon (SwiftUI Default)"), systemImage: "magnifyingglass") 50 | .labelStyle(.titleAndIcon) 51 | 52 | Label(String(".titleAndTrailingIcon"), systemImage: "magnifyingglass") 53 | .labelStyle(.titleAndTrailingIcon) 54 | 55 | Label(String(".titleAndIconBadge(color: .red)"), systemImage: "magnifyingglass") 56 | .labelStyle(.titleAndIconBadge(color: .red)) 57 | 58 | Label(String(".titleAndTrailingIconBadge(color: .red)"), systemImage: "magnifyingglass") 59 | .labelStyle(.titleAndTrailingIconBadge(color: .red)) 60 | } 61 | .textCase(.none) 62 | } 63 | } 64 | #endif 65 | -------------------------------------------------------------------------------- /Sources/LinksKit/Views/LinkSectionsView.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | struct LinkSectionsView: View { 4 | @Environment(\.openURL) private var openURL 5 | 6 | let linkSections: [LinkSection] 7 | 8 | var body: some View { 9 | ForEach(self.linkSections) { linkSection in 10 | Section { 11 | ForEach(linkSection.entries) { entry in 12 | switch entry { 13 | case .link(let link): 14 | Button(link.title, systemImage: link.systemImage) { 15 | self.openURL(link.url) 16 | } 17 | 18 | case .menu(let menu): 19 | Menu(menu.title, systemImage: menu.systemImage) { 20 | LinkSectionsView(linkSections: menu.linkSections) 21 | } 22 | } 23 | } 24 | } header: { 25 | if let title = linkSection.title { 26 | Text(title) 27 | } 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Sources/LinksKit/Views/LinksView.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | /// Renders the configured links and menus in-place. Designed for use inside a `List`, `Form`, or `CommandsGroup` (macOS only). 4 | /// 5 | /// - NOTE: Make sure to call ``LinksKit.configure(providerToken:linkSections)`` upon app start or this view will not work. 6 | public struct LinksView: View { 7 | public init() {} 8 | 9 | public var body: some View { 10 | LinkSectionsView(linkSections: LinksKit.linkSections) 11 | } 12 | } 13 | 14 | #if DEBUG 15 | #Preview { 16 | struct Preview: View { 17 | init() { 18 | // App Links 19 | let ownDeveloperApps = LinkSection(entries: [ 20 | .link(.ownApp(id: "6502914189", name: "FreemiumKit: In-App Purchases", systemImage: "cart")), 21 | .link(.ownApp(id: "6480134993", name: "FreelanceKit: Time Tracking", systemImage: "timer")), 22 | ]) 23 | 24 | let ownConsumerApps = LinkSection(entries: [ 25 | .link(.ownApp(id: "6472669260", name: "CrossCraft: Crossword Tests", systemImage: "puzzlepiece")), 26 | .link(.ownApp(id: "6477829138", name: "FocusBeats: Study Music Timer", systemImage: "music.note")), 27 | .link(.ownApp(id: "6587583340", name: "Pleydia Organizer: Media Renamer", systemImage: "popcorn")), 28 | ]) 29 | 30 | let ownVisionApps = LinkSection(entries: [ 31 | .link(.ownApp(id: "6479207869", name: "Guided Guest Mode: Device Demo", systemImage: "questionmark.circle")), 32 | .link(.ownApp(id: "6478062053", name: "Posters: Discover Movies at Home", systemImage: "movieclapper")), 33 | ]) 34 | 35 | let nicosApps = LinkSection(entries: [ 36 | .link(.friendsApp(id: "1249686798", name: "NFC.cool Tools: Tag Reader", systemImage: "tag", providerToken: "106913804")), 37 | .link(.friendsApp(id: "6443995212", name: "Metadata for Fastlane Tools", systemImage: "hammer", providerToken: "106913804")), 38 | ]) 39 | 40 | let jansApps = LinkSection(entries: [ 41 | .link(.friendsApp(id: "6503256642", name: "App Exhibit: Your App Showcase", systemImage: "square.grid.3x3.fill.square")), 42 | ]) 43 | 44 | // Web Links 45 | let faqURL = URL(string: "https://example.com")! 46 | let privacyURL = URL(string: "https://example.com")! 47 | 48 | // Configure LinksKit 49 | LinksKit.configure( 50 | providerToken: "549314", 51 | linkSections: [ 52 | .helpLinks(appID: "6476773066", faqURL: faqURL, supportEmail: "translatekit@fline.dev"), 53 | .socialMenus( 54 | appLinks: .appSocialLinks( 55 | platforms: [.twitter, .mastodon(instance: "mastodon.social"), .threads], 56 | handle: "TranslateKit", 57 | handleOverrides: [.twitter: "TranslateKitApp"] 58 | ), 59 | developerLinks: .developerSocialLinks( 60 | platforms: [.twitter, .mastodon(instance: "iosdev.space"), .threads], 61 | handle: "Jeehut" 62 | ) 63 | ), 64 | .appMenus( 65 | ownAppLinks: [ownDeveloperApps, ownConsumerApps, ownVisionApps], 66 | friendsAppLinks: [nicosApps, jansApps] 67 | ), 68 | .legalLinks(privacyURL: privacyURL) 69 | ] 70 | ) 71 | } 72 | 73 | var body: some View { 74 | List { 75 | LinksView() 76 | .labelStyle(.titleAndIconBadge(color: .accentColor)) 77 | } 78 | } 79 | } 80 | 81 | return Preview() 82 | } 83 | #endif 84 | --------------------------------------------------------------------------------