Google binds its session cookies to the device (Device Bound Session Credentials) and signs out sessions whose cookies look stolen, which can sign the owner out of their real Chrome. The default is now storebound's own profile per store; storebound starts Chrome itself (--user-data-dir, --remote-debugging-port=0, no --enable-automation, navigator.webdriver false) and attaches over CDP. --use-chrome-session google|apple is an explicit opt-in that warns. /signin/rejected is said plainly.
1325 lines
67 KiB
TypeScript
1325 lines
67 KiB
TypeScript
// English UI strings (the source catalog). Placeholders: {name}. Plural: a "<key>_one" entry for a count of 1.
|
|
export const en = {
|
|
'a11y.skip': 'Skip to content',
|
|
'a11y.breadcrumbs': 'You are here',
|
|
|
|
'nav.sections': 'Sections',
|
|
'nav.portfolio': 'Portfolio',
|
|
'nav.appsLabel': 'Apps',
|
|
'nav.workspace': 'Workspace',
|
|
'nav.apps': 'App folders',
|
|
'nav.accounts': 'Studios & accounts',
|
|
'nav.dependencies': 'Dependencies',
|
|
'nav.settings': 'Settings',
|
|
'nav.noApps': 'No apps yet',
|
|
'nav.problems': '{count} problems',
|
|
'nav.problems_one': '1 problem',
|
|
|
|
'tab.releases': 'Releases',
|
|
'tab.catalog': 'Catalog',
|
|
'tab.listings': 'Listings',
|
|
'tab.health': 'Health',
|
|
'tab.reviews': 'Reviews',
|
|
'tab.testflight': 'TestFlight',
|
|
'tab.checks': 'Checks',
|
|
|
|
'profile.app': 'App',
|
|
'profile.game': 'Game',
|
|
'profile.subscription-app': 'Subscription app',
|
|
|
|
'foot.cli': 'CLI {version} running',
|
|
'foot.cliDown': 'CLI not running',
|
|
'foot.cliStarting': 'Starting the CLI',
|
|
'foot.lastRead': 'Stores read {when}',
|
|
'foot.neverRead': 'Stores not read yet',
|
|
|
|
'top.storesRead': 'Stores read {when}',
|
|
'top.storesNotRead': 'Stores not read',
|
|
'dev.fixtures': 'DEV FIXTURES',
|
|
'dev.fixturesHint': 'Development build on fixture data: nothing here comes from a store. Release builds have no fixture mode.',
|
|
|
|
'action.readStores': 'Read the stores',
|
|
'action.reading': 'Reading',
|
|
'action.readStoresHint': 'Read-only: App Store Connect and Google Play status of every app, with each app\'s own accounts',
|
|
'action.checkConfigs': 'Check configs',
|
|
'action.addFolder': 'Add app folder',
|
|
'action.addAccount': 'Add a store account',
|
|
'action.toggleTheme': 'Switch light / dark',
|
|
'action.welcome': 'Open the welcome guide',
|
|
'action.refresh': 'Refresh',
|
|
|
|
'palette.title': 'Command palette',
|
|
'palette.button': 'Search or jump to',
|
|
'palette.placeholder': 'Jump to an app, a tab or a screen, or run an action',
|
|
'palette.results': 'Results',
|
|
'palette.none': 'Nothing matches "{q}"',
|
|
'palette.move': 'move',
|
|
'palette.open': 'open',
|
|
'palette.toggle': 'open / close',
|
|
'palette.gApps': 'Apps',
|
|
'palette.gGo': 'Go to',
|
|
'palette.gTabs': 'App tabs',
|
|
'palette.gActions': 'Actions',
|
|
'palette.openApp': 'Open',
|
|
|
|
'common.loading': 'Loading',
|
|
'common.unknown': 'Unknown',
|
|
'common.cancel': 'Cancel',
|
|
'common.close': 'Close',
|
|
'common.exit': 'Exit code {code}',
|
|
'common.cachedFrom': 'Last read {when} (saved copy)',
|
|
'common.readWhen': 'Read {when}',
|
|
'common.readFailedKeep': 'The last read failed, so this shows the previous one: {error}',
|
|
|
|
'time.justNow': 'just now',
|
|
'time.never': 'never',
|
|
|
|
'toast.readingStores': 'Reading the stores',
|
|
'toast.readingStoresDetail': 'App Store Connect and Google Play, read-only',
|
|
'toast.readDone': 'Stores read',
|
|
'toast.readDoneDetail': '{count} apps up to date',
|
|
'toast.readDoneDetail_one': '1 app up to date',
|
|
'toast.readDonePartial': 'Stores read, with gaps',
|
|
'toast.readDonePartialDetail': '{count} apps could not be read on a store; they show as unknown',
|
|
'toast.readDonePartialDetail_one': '1 app could not be read on a store; it shows as unknown',
|
|
'toast.readFailed': 'Reading the stores failed',
|
|
'toast.cancelled': 'Cancelled',
|
|
'toast.reading': 'Reading',
|
|
'toast.readingDetail': 'Read-only',
|
|
'toast.readOk': '{what} read',
|
|
'toast.readFailedWhat': 'Reading {what} failed',
|
|
|
|
'write.dryFailed': 'The dry run failed, nothing was written',
|
|
'write.failed': 'Not applied',
|
|
|
|
'phase.none': 'Not on this store',
|
|
'phase.live': 'Live',
|
|
'phase.rollout': 'Rollout',
|
|
'phase.phased': 'Phased',
|
|
'phase.halted': 'Halted',
|
|
'phase.paused': 'Paused',
|
|
'phase.approved': 'Approved',
|
|
'phase.review': 'In review',
|
|
'phase.rejected': 'Rejected',
|
|
'phase.testing': 'Testing',
|
|
'phase.draft': 'Draft',
|
|
'phase.other': 'Other',
|
|
|
|
'stage.build': 'Build',
|
|
'stage.testing': 'Testing',
|
|
'stage.review': 'Review',
|
|
'stage.live': 'Live',
|
|
'stage.rollout': 'Rollout',
|
|
|
|
'check.notChecked': 'Not checked',
|
|
'check.notLoaded': 'Config not loaded',
|
|
'check.problems': '{count} problems',
|
|
'check.problems_one': '1 problem',
|
|
'check.warnings': '{count} warnings',
|
|
'check.warnings_one': '1 warning',
|
|
'check.ok': 'Config OK',
|
|
|
|
'app.notSetUp': 'not set up',
|
|
'app.notOnStore': 'Not on this store',
|
|
'app.sections': '{name} sections',
|
|
'app.consoleHint': 'Submit, release and publish happen in the store console',
|
|
|
|
'portfolio.lead': 'Every app in this workspace on the App Store and Google Play.',
|
|
'portfolio.sub': '{count} apps · {stores} store listings',
|
|
'portfolio.sub_one': '1 app · {stores} store listings',
|
|
'portfolio.emptyTitle': 'Add your first app',
|
|
'portfolio.emptyText': 'storebound works on app folders: one storebound.config.ts per app, for iOS and Android. Add a folder that has one, or start a new one from the templates.',
|
|
'portfolio.notReadNotice': 'Releases, rollouts and catalog parity need one read of the stores. It is read-only and uses each app\'s own accounts.',
|
|
'portfolio.apps': 'Apps',
|
|
'portfolio.appsSub': 'Release state from the stores, read {when}',
|
|
'portfolio.appsSubOffline': 'Config only: read the stores for releases',
|
|
'portfolio.unreadable': 'Unreadable',
|
|
'portfolio.noVersion': 'No version yet',
|
|
'portfolio.noNext': 'Nothing in flight',
|
|
'portfolio.thenNext': 'next {version} · {phase}',
|
|
'portfolio.products': '{count} products',
|
|
'portfolio.products_one': '1 product',
|
|
'portfolio.subs': '{count} subs',
|
|
'portfolio.subs_one': '1 sub',
|
|
'portfolio.inParity': 'In parity',
|
|
'portfolio.differs': '{count} differ',
|
|
'portfolio.differs_one': '1 differs',
|
|
'portfolio.configOnly': 'Not compared yet',
|
|
'portfolio.attention': 'Needs attention',
|
|
'portfolio.attentionSub': 'Problems first, then warnings',
|
|
'portfolio.allClear': 'Nothing needs attention',
|
|
'portfolio.allClearText': 'Configs check out and no store reported a problem in the last read.',
|
|
'portfolio.workspace': 'Workspace',
|
|
'portfolio.healthNotRead': 'Not read',
|
|
'portfolio.healthNoPlay': 'iOS only',
|
|
'portfolio.healthTitle': 'Last 14 days, user-perceived, read {when}',
|
|
'portfolio.accounts': '{play} Google Play · {apple} App Store Connect',
|
|
'portfolio.storesRead': 'Stores read',
|
|
'portfolio.tools': 'Local tools',
|
|
'portfolio.toolsFound': '{found} of {total} found',
|
|
|
|
'kpi.apps': 'Apps',
|
|
'kpi.appsSub': '{ios} on iOS · {android} on Android',
|
|
'kpi.live': 'Live versions',
|
|
'kpi.liveSub': 'across {count} store listings',
|
|
'kpi.rolling': 'Rolling out',
|
|
'kpi.review': 'In review',
|
|
'kpi.attention': 'Needs attention',
|
|
'kpi.blockers': '{count} blockers',
|
|
'kpi.blockers_one': '1 blocker',
|
|
'kpi.noBlockers': 'No blockers',
|
|
'kpi.none': 'None',
|
|
'kpi.notRead': 'Read the stores to see this',
|
|
|
|
'legend.done': 'done',
|
|
'legend.stages': 'Build · Testing · Review · Live · Rollout',
|
|
|
|
'col.app': 'App',
|
|
'col.next': 'Next version',
|
|
'col.catalog': 'Catalog',
|
|
'col.crash': 'Crash rate',
|
|
'col.config': 'Config',
|
|
'col.version': 'Version',
|
|
'col.build': 'Build',
|
|
'col.versionCode': 'Version code',
|
|
'col.track': 'Track',
|
|
'col.item': 'Item',
|
|
'col.type': 'Type',
|
|
'col.priceGap': 'Price gap',
|
|
'col.region': 'Region',
|
|
'col.diff': 'Difference',
|
|
'col.language': 'Language',
|
|
'col.issue': 'Issue',
|
|
'col.reports': 'Reports',
|
|
'col.users': 'Users',
|
|
'col.metric': 'Metric',
|
|
'col.value': 'Value',
|
|
'col.goal': 'Goal',
|
|
'col.name': 'Name',
|
|
'col.store': 'Store',
|
|
'col.usedBy': 'Used by',
|
|
'col.added': 'Added',
|
|
'col.actions': 'Actions',
|
|
|
|
'att.storeError': '{store} could not be read: {error}',
|
|
'att.rejected': '{store} {version} was rejected',
|
|
'att.halted': '{store} {version}: rollout halted',
|
|
'att.catalog': '{count} catalog items differ between the stores',
|
|
'att.catalog_one': '1 catalog item differs between the stores',
|
|
'att.crash': 'Crash rate near or over the Google Play threshold',
|
|
'att.anr': 'ANR rate near or over the Google Play threshold',
|
|
|
|
'tl.next': 'Next',
|
|
'tl.live': 'Live',
|
|
'tl.store': 'Store',
|
|
'tl.created': 'Created {date}',
|
|
'tl.notOnStore': 'Not on this store',
|
|
'tl.noVersion': '{version} is not on {store} yet',
|
|
'tl.everyone': 'Everyone',
|
|
'tl.day': 'day {day} of 7',
|
|
'tl.rolloutAria': 'Share of users with this version',
|
|
|
|
'releases.notReadTitle': 'Release state is not read yet',
|
|
'releases.notReadText': 'The timeline shows each version on both stores: build, TestFlight or internal testing, review, live and the rollout share. Read the stores once to fill it.',
|
|
'releases.noAccounts': 'Tip: map store accounts to this app in App folders first.',
|
|
'releases.storeUnreadable': '{store} could not be read, so its lane shows as unknown: {error}',
|
|
'releases.noVersions': 'No versions on the stores yet',
|
|
'releases.noVersionsText': 'When the first build is uploaded it shows here.',
|
|
'releases.history': 'Versions on the stores',
|
|
'releases.historySub': 'Read {when}',
|
|
'releases.consoleNote': 'storebound never submits for review and never releases an approved version: do those in the store console. Rollout and phased release changes are your decision, each confirmed in a system dialog.',
|
|
|
|
'cat.products': 'One-time products',
|
|
'cat.productsSub': 'In the config',
|
|
'cat.subscriptions': 'Subscriptions',
|
|
'cat.subsSub': 'All groups',
|
|
'cat.parity': 'In parity',
|
|
'cat.parityRead': 'Compared {when}',
|
|
'cat.gaps': 'Price gaps',
|
|
'cat.gapsSub': 'Same currency, over 10 %',
|
|
'cat.matrix': 'Parity matrix',
|
|
'cat.configOnly': 'From the config only: compare with both stores to fill the store columns',
|
|
'cat.compare': 'Compare with the stores',
|
|
'cat.ok': 'Matches',
|
|
'cat.warn': 'Differs',
|
|
'cat.error': 'Missing or wrong',
|
|
'cat.na': 'Not sold here',
|
|
'cat.unknown': 'Not compared',
|
|
'cat.extra': 'Store only',
|
|
'cat.sub': 'Subscription',
|
|
'cat.product': 'Product',
|
|
'cat.notInConfig': 'Not in the config',
|
|
'cat.noGap': 'None',
|
|
'cat.gapsTitle': 'Price gaps between the stores',
|
|
'cat.gapsTitleSub': 'Stores round to their own price tiers, so small gaps are normal',
|
|
'cat.emptyTitle': 'No in-app products or subscriptions',
|
|
'cat.emptyText': 'Products and subscriptions are defined once in storebound.config.ts and created on both stores. This app has none in its config.',
|
|
|
|
'lst.languages': 'Languages',
|
|
'lst.completeKpi': 'Complete',
|
|
'lst.completeSub': 'Required fields, both stores',
|
|
'lst.toFix': 'To fix',
|
|
'lst.toFixSub': 'Missing or over the limit',
|
|
'lst.screenshots': 'Screenshots',
|
|
'lst.screenshotsSub': 'Rendered, all languages',
|
|
'lst.noRenders': 'No renders folder yet',
|
|
'lst.playSub': 'store/listing.md',
|
|
'lst.appleSub': 'store/appstore.md',
|
|
'lst.complete': 'Complete',
|
|
'lst.completeAria': '{pct} % complete',
|
|
'lst.missing': 'Missing',
|
|
'lst.optional': 'Optional',
|
|
'lst.over': '{n} over',
|
|
'lst.title': 'Title',
|
|
'lst.short': 'Short',
|
|
'lst.full': 'Full',
|
|
'lst.whatsNew': 'What\'s new',
|
|
'lst.name': 'Name',
|
|
'lst.subtitle': 'Subtitle',
|
|
'lst.promo': 'Promo text',
|
|
'lst.keywords': 'Keywords',
|
|
'lst.description': 'Description',
|
|
'lst.noFilesTitle': 'No listing files yet',
|
|
'lst.noFilesText': 'Listing text lives in store/listing.md (Google Play) and store/appstore.md (App Store) in the app folder, one section per language.',
|
|
'lst.noFilesHint': 'writes both templates into the app folder',
|
|
'lst.foot': 'From the app folder\'s files, read {when}. Nothing is uploaded from here.',
|
|
|
|
'health.read': 'Read health',
|
|
'health.emptyTitle': 'Health is not read yet',
|
|
'health.emptyText': 'Crash and ANR rates against the Google Play thresholds, worst devices and top issues, plus App Store diagnostics. Read-only.',
|
|
'health.crash': 'User-perceived crash rate',
|
|
'health.anr': 'User-perceived ANR rate',
|
|
'health.window': '{from} to {to}',
|
|
'health.over': 'Over threshold',
|
|
'health.near': 'Near threshold',
|
|
'health.under': 'Under threshold',
|
|
'health.current28': '28-day average, as Google Play counts it',
|
|
'health.daily': 'Daily',
|
|
'health.threshold': 'Bad behavior threshold {value}',
|
|
'health.chartAria': '{metric}: {value}',
|
|
'health.devices': 'Worst devices',
|
|
'health.devicesSub': 'Per-device threshold {value}',
|
|
'health.noDevices': 'No device has enough users to compare.',
|
|
'health.issues': 'Top issues',
|
|
'health.issuesSub': 'Most reports first',
|
|
'health.noIssues': 'No issues reported',
|
|
'health.crashShort': 'Crash',
|
|
'health.appleMetrics': 'Performance metrics',
|
|
'health.appleMetricsSub': 'Latest values per metric',
|
|
'health.noMetrics': 'No metrics yet',
|
|
'health.signatures': 'Diagnostic signatures',
|
|
'health.signaturesSub': 'Heaviest first, latest builds',
|
|
'health.noSignatures': 'No diagnostic signatures',
|
|
'health.betaCrashes': 'TestFlight crashes',
|
|
'health.noBetaCrashes': 'No TestFlight crash reports in the window.',
|
|
'health.build': 'build {build}',
|
|
'health.noPlay': 'This app is not on Google Play.',
|
|
'health.noApple': 'This app is not on the App Store.',
|
|
'health.unreadable': '{store} could not be read, shown as unknown: {error}',
|
|
|
|
'reviews.read': 'Read reviews',
|
|
'reviews.emptyTitle': 'Reviews are not read yet',
|
|
'reviews.emptyText': 'The last 30 days on the App Store, the last 7 on Google Play (its API keeps no more), with your local reply drafts. Read-only.',
|
|
'reviews.ratings': 'Ratings',
|
|
'reviews.count': '{count} reviews',
|
|
'reviews.count_one': '1 review',
|
|
'reviews.unansweredN': '{count} without a reply',
|
|
'reviews.unansweredN_one': '1 without a reply',
|
|
'reviews.filter': 'Filter',
|
|
'reviews.store': 'Store',
|
|
'reviews.all': 'All',
|
|
'reviews.onlyUnanswered': 'Only without a reply',
|
|
'reviews.search': 'Search reviews',
|
|
'reviews.inbox': 'Inbox',
|
|
'reviews.shown': '{count} shown',
|
|
'reviews.noMatch': 'No review matches the filter',
|
|
'reviews.pick': 'Pick a review',
|
|
'reviews.answered': 'Answered',
|
|
'reviews.drafted': 'Draft',
|
|
'reviews.approved': 'Approved',
|
|
'reviews.notApproved': 'Not approved',
|
|
'reviews.noTitle': 'No title',
|
|
'reviews.noText': 'No text',
|
|
'reviews.version': 'version {v}',
|
|
'reviews.currentReply': 'Reply on the store',
|
|
'reviews.draft': 'Your reply draft',
|
|
'reviews.noDraft': 'No draft for this review. "Make drafts" writes one file per unanswered review into .storebound/replies.',
|
|
'reviews.emptyDraft': 'The draft {file} has no reply yet: write it under "## Reply".',
|
|
'reviews.chars': '{n} of {limit} characters',
|
|
'reviews.approve': 'Approve',
|
|
'reviews.unapprove': 'Remove approval',
|
|
'reviews.approveHint': 'Marks the draft approved (local file, confirmed in a dialog). Nothing is sent.',
|
|
'reviews.fixFirst': 'Fix the errors first',
|
|
'reviews.sentOn': 'Sent {date}',
|
|
'reviews.sendNote': 'Replies are public, so they go out from a terminal:',
|
|
'reviews.makeDrafts': 'Make drafts',
|
|
'reviews.makeDraftsHint': 'One local draft per unanswered review (dry run first, then a confirmation)',
|
|
'reviews.draftsMade': 'Reply drafts written',
|
|
'reviews.approvedToast': 'Draft approved',
|
|
'reviews.unapproved': 'Approval removed',
|
|
'reviews.starsAria': '{count} of 5 stars',
|
|
'reviews.starsAria_one': '1 of 5 stars',
|
|
|
|
'tf.read': 'Read TestFlight',
|
|
'tf.emptyTitle': 'TestFlight is not read yet',
|
|
'tf.emptyText': 'Beta groups, testers and recent builds with their processing and beta review states. Read-only.',
|
|
'tf.noIos': 'This app is not on iOS',
|
|
'tf.noIosText': 'TestFlight is for apps with an App Store record. Add the apple section to the config to use it.',
|
|
'tf.internal': 'Internal',
|
|
'tf.external': 'External',
|
|
'tf.testers': 'testers',
|
|
'tf.builds': 'builds',
|
|
'tf.all': 'All',
|
|
'tf.publicOn': 'Public link on',
|
|
'tf.publicOff': 'Invite only',
|
|
'tf.noGroups': 'No beta groups',
|
|
'tf.buildsTitle': 'Recent builds',
|
|
'tf.buildsSub': 'Newest first',
|
|
'tf.processing': 'Processing',
|
|
'tf.internalTesting': 'Internal testing',
|
|
'tf.externalTesting': 'External testing',
|
|
'tf.uploaded': 'Uploaded',
|
|
'tf.noBuilds': 'No builds uploaded yet',
|
|
'tf.missingGroups': 'In the config but not on App Store Connect: {groups}',
|
|
|
|
'checks.offline': 'Config check',
|
|
'checks.offlineSub': 'Offline: config, listing files, copy, declarations, products',
|
|
'checks.again': 'Check again',
|
|
'checks.clean': 'The config checks out',
|
|
'checks.cleanText': 'No problems or warnings in the app folder.',
|
|
'checks.problem': 'Problem',
|
|
'checks.warning': 'Warning',
|
|
'checks.validate': 'Store readiness',
|
|
'checks.validateSub': 'Read-only report from both stores, blockers in order',
|
|
'checks.run': 'Run the report',
|
|
'checks.validateEmpty': 'Readiness not checked yet',
|
|
'checks.validateEmptyText': 'What is still missing on the App Store and Google Play before a submission, in the order to fix it.',
|
|
'checks.ready': 'No blockers',
|
|
'checks.readyText': 'Both stores have what a submission needs.',
|
|
'checks.scan': 'Rejection risks',
|
|
'checks.scanSub': 'Offline scan of the project files: guideline, evidence, fix',
|
|
'checks.scanAgain': 'Scan again',
|
|
'checks.scanClean': 'No rejection risks found',
|
|
'checks.scanCleanText': 'Nothing in the project files, config or listings matches a known App Store rejection or Google Play policy issue.',
|
|
'checks.scanSdks': 'SDKs: {list}',
|
|
'checks.scanAsk': '{count} declaration answers only you can give',
|
|
'checks.scanAsk_one': '1 declaration answer only you can give',
|
|
'checks.scanWrite': 'Detected Data safety / App Privacy answers differ from the config: storebound scan --write adds them',
|
|
'checks.accepted': 'Accepted: {reason}',
|
|
'checks.sev.blocker': 'Blocker',
|
|
'checks.sev.high': 'High',
|
|
'checks.sev.medium': 'Medium',
|
|
'checks.sev.accepted': 'Accepted',
|
|
'checks.sev.low': 'Low',
|
|
|
|
'folders.lead': 'One folder per app with its storebound.config.ts (iOS and Android in one config). Pick the store accounts each app uses; the keys stay in the keychain.',
|
|
'folders.list': 'App folders',
|
|
'folders.listSub': '{count} folders',
|
|
'folders.listSub_one': '1 folder',
|
|
'folders.emptyTitle': 'No app folders yet',
|
|
'folders.emptyText': 'Add a folder that has a storebound.config.ts, or start a new one below.',
|
|
'folders.added': '{name} added',
|
|
'folders.started': '{name} started',
|
|
'folders.startedDetail': 'Templates written. Edit storebound.config.ts and the store files next.',
|
|
'folders.playFor': 'Google Play account for {name}',
|
|
'folders.appleFor': 'App Store Connect account for {name}',
|
|
'folders.noPlay': 'No Google Play account',
|
|
'folders.noApple': 'No App Store account',
|
|
'folders.check': 'Check',
|
|
'folders.gallery': 'Gallery',
|
|
'folders.galleryHint': 'Writes the local screenshot review page (dry run first, then a confirmation)',
|
|
'folders.remove': 'Remove {name} from the list (the folder stays)',
|
|
'folders.checkTitle': 'Config check',
|
|
'folders.galleryTitle': 'Screenshot review page',
|
|
'folders.newTitle': 'Start a new app folder',
|
|
'folders.newSub': 'storebound init: config, listing, screenshot copy, declarations and privacy policy templates',
|
|
'folders.profile': 'Profile',
|
|
'folders.profileHint.app': 'Utility or productivity app: optional account and analytics, no ads.',
|
|
'folders.profileHint.game': 'Free-to-play game with ads and in-app purchases.',
|
|
'folders.profileHint.subscription-app': 'App with accounts and auto-renewable subscriptions.',
|
|
'folders.chooseAndStart': 'Choose a folder and start',
|
|
|
|
'run.failed': 'Failed',
|
|
'run.running': 'Running',
|
|
'run.applied': 'Applied after your confirmation',
|
|
'run.cancelled': 'Cancelled in the dialog: nothing was written',
|
|
'run.dryFailed': 'The dry run failed: nothing was written',
|
|
'run.done': 'Done',
|
|
|
|
'accounts.lead': 'Store API keys live in the system keychain (Keychain on macOS, Credential Manager on Windows, Secret Service on Linux). They are never shown again, never written to your app folders, and reach storebound in memory for one call.',
|
|
'accounts.list': 'Store accounts',
|
|
'accounts.listSub': 'Labels only: the keys are in the keychain',
|
|
'accounts.emptyTitle': 'No store accounts yet',
|
|
'accounts.emptyText': 'Add a Google Play service account or an App Store Connect API key below. Store reads need them; app folders work without.',
|
|
'accounts.unused': 'Not used',
|
|
'accounts.remove': 'Remove',
|
|
'accounts.removeAria': 'Remove {label} and delete its key from the keychain',
|
|
'accounts.saved': '"{label}" saved',
|
|
'accounts.savedDetail': 'The key is in the system keychain.',
|
|
'accounts.playSub': 'Service account JSON key',
|
|
'accounts.appleSub': 'Team API key (.p8) from Users and Access, Integrations',
|
|
'accounts.label': 'Name',
|
|
'accounts.playPlaceholder': 'Studio Play account',
|
|
'accounts.applePlaceholder': 'Studio App Store key',
|
|
'accounts.playHow': 'A service account with access to your apps in Play Console (Users and permissions).',
|
|
'accounts.keyId': 'Key ID',
|
|
'accounts.issuerId': 'Issuer ID',
|
|
'accounts.choosePlay': 'Choose the JSON key',
|
|
'accounts.chooseApple': 'Choose the .p8 key',
|
|
'accounts.safety': 'Keys are picked in the system file dialog and go straight to the keychain. The window never sees them.',
|
|
|
|
'deps.lead': 'Local tools for screenshots, app previews, icons and simulator or emulator captures. Store work (listings, products, releases, reviews) needs none of them.',
|
|
'deps.checkAgain': 'Check again',
|
|
'deps.tools': 'Tools on this computer',
|
|
'deps.found': '{found} of {total} found',
|
|
'deps.missing': 'Missing',
|
|
'deps.appCopy': 'App copy',
|
|
'deps.installed': 'Installed',
|
|
'deps.download': 'Download',
|
|
'deps.remove': 'Remove',
|
|
'deps.getIt': 'Get it',
|
|
'deps.unavailable': 'Not for this platform',
|
|
'deps.downloading': 'Downloading {tool}',
|
|
'deps.installedToast': '{tool} installed',
|
|
'deps.failed': 'Download failed',
|
|
'deps.cancelledDetail': 'The partial download was deleted.',
|
|
'deps.removed': 'Removed from the app data folder',
|
|
'deps.inAppData': 'In the app data folder ({folder})',
|
|
'deps.notDownloaded': 'Not downloaded',
|
|
'deps.source': 'Source',
|
|
'deps.license': 'License',
|
|
'deps.verify': 'Verified by',
|
|
'deps.verifyFfmpeg': 'SHA-256 of the exact archive, pinned in this app version',
|
|
'deps.verifyChrome': 'Google\'s code signature (macOS, Windows) or the version banner (Linux)',
|
|
'deps.licenseLink': 'License and source',
|
|
'deps.terminal': 'From a terminal',
|
|
'deps.terminalSub': 'The same check, and the usual install commands',
|
|
'deps.copy': 'Copy "{cmd}"',
|
|
'deps.copied': 'Copied',
|
|
|
|
'dl.resolve': 'Finding the download',
|
|
'dl.download': 'Downloading',
|
|
'dl.verify': 'Verifying',
|
|
'dl.unpack': 'Unpacking',
|
|
'dl.install': 'Installing',
|
|
'dl.done': 'Done',
|
|
'dl.error': 'Failed',
|
|
'dl.cancelled': 'Cancelled',
|
|
|
|
'settings.lead': 'Appearance, language, shortcuts and what this app runs on.',
|
|
'settings.appearance': 'Appearance',
|
|
'settings.theme': 'Theme',
|
|
'settings.system': 'System',
|
|
'settings.light': 'Light',
|
|
'settings.dark': 'Dark',
|
|
'settings.motion': 'Motion',
|
|
'settings.followSystem': 'Follow the system',
|
|
'settings.reduce': 'Reduce',
|
|
'settings.language': 'Language',
|
|
'settings.shortcuts': 'Keyboard shortcuts',
|
|
'settings.scPalette': 'Command palette',
|
|
'settings.scWorkspace': 'App folders, Accounts, Dependencies, Settings',
|
|
'settings.scTabs': 'Previous / next app tab',
|
|
'settings.scTabArrows': 'Move between tabs (tab list focused)',
|
|
'settings.scClose': 'Close a dialog',
|
|
'settings.data': 'Saved reads',
|
|
'settings.dataText': 'The last store reads are kept in the app data folder so screens open with them offline, always marked with their time. No keys are kept there.',
|
|
'settings.clearCache': 'Clear saved reads',
|
|
'settings.cacheCleared': 'Saved reads cleared',
|
|
'settings.about': 'About',
|
|
'settings.app': 'App',
|
|
'settings.debug': 'debug build',
|
|
'settings.methods': '{count} methods',
|
|
'settings.tools': 'Local tools',
|
|
'settings.telemetry': 'Telemetry',
|
|
'settings.telemetryNone': 'None. The app only talks to the store APIs through storebound, with your keys.',
|
|
|
|
'wz.s1': 'Welcome',
|
|
'wz.s2': 'Your apps',
|
|
'wz.s3': 'Store keys',
|
|
'wz.s4': 'Local tools',
|
|
'wz.s5': 'First read',
|
|
'wz.footer': 'You can open this guide again from Settings or the command palette.',
|
|
'wz.footerSafe': 'Nothing is submitted or released from here.',
|
|
'wz.welcomeTitle': 'Every app, both stores, one window',
|
|
'wz.welcomeLead': 'storebound desktop shows where each of your apps stands on the App Store and Google Play, and runs the storebound CLI for you. Six short steps get you there.',
|
|
'wz.p1t': 'One portfolio',
|
|
'wz.p1s': 'Releases, rollouts, catalog parity, health and reviews of every app.',
|
|
'wz.p2t': 'Safe by design',
|
|
'wz.p2s': 'Reads are read-only. Every change shows a dry run and a native confirmation first.',
|
|
'wz.p3t': 'Your keys stay yours',
|
|
'wz.p3s': 'Store keys live in the system keychain. No account, no telemetry.',
|
|
'wz.appsTitle': 'Add your apps',
|
|
'wz.appsLead': 'Each app is a folder with a storebound.config.ts that describes it on both stores.',
|
|
'wz.addTitle': 'Add an existing folder',
|
|
'wz.addText': 'The folder already has a storebound.config.ts (from storebound init or the CLI).',
|
|
'wz.initTitle': 'Start a new app folder',
|
|
'wz.initText': 'Writes the templates for a profile into a folder you choose. Existing files are kept.',
|
|
'wz.added': 'Added',
|
|
'wz.ready': 'Ready',
|
|
'wz.keysTitle': 'Add your store keys',
|
|
'wz.keysLead': 'Store reads need an API key per store. You can skip this and add them later in Accounts.',
|
|
'wz.mapHint': 'Which accounts this app uses',
|
|
'wz.toolsTitle': 'Check the local tools',
|
|
'wz.toolsLead': 'Screenshots, previews and icons use ffmpeg and Chrome. The app can download its own copies; store work needs none of them.',
|
|
'wz.toolsNote': 'The same check in a terminal:',
|
|
'wz.readTitle': 'Read the stores',
|
|
'wz.readLead': 'One read-only pass over App Store Connect and Google Play fills the portfolio: versions, review state, rollouts and catalog parity.',
|
|
'wz.readNow': 'Read the stores now',
|
|
'wz.readDone': '{count} apps read {when}',
|
|
'wz.needApp': 'Add an app folder first (step 3).',
|
|
'wz.skip': 'Skip for now',
|
|
'wz.back': 'Back',
|
|
'wz.next': 'Next',
|
|
'wz.finish': 'Finish',
|
|
|
|
'nav.ignored': 'Ignored',
|
|
'nav.studios': 'Studios',
|
|
'nav.studiosLabel': 'Studios',
|
|
'palette.studio': 'Studio',
|
|
'action.importApps': 'Import apps',
|
|
'action.importAppsHint': 'Read-only: every app each store account can see, from App Store Connect and Google Play',
|
|
'apps.storeOnly': 'Store only',
|
|
'apps.storeOnlyHint': 'On a store account, no app folder yet: store data only (read-only)',
|
|
'common.save': 'Save',
|
|
'studio.studio': 'Studio',
|
|
'studio.none': 'No studio',
|
|
'studio.noneSub': 'Accounts not in a studio yet',
|
|
'studio.new': 'New studio',
|
|
'studio.newSub': 'A studio groups store accounts, and with them their apps',
|
|
'studio.name': 'Name',
|
|
'studio.namePlaceholder': 'Example Games',
|
|
'studio.color': 'Colour',
|
|
'studio.add': 'Add a studio',
|
|
'studio.added': 'Studio {name} added',
|
|
'studio.edit': 'Edit',
|
|
'studio.logo': 'Logo',
|
|
'studio.logoClear': 'Remove logo',
|
|
'studio.remove': 'Remove',
|
|
'studio.removeHint': 'Removes the studio only: its accounts and apps stay, without a studio',
|
|
'studio.counts': '{count} accounts · {apps} apps · {store} store only',
|
|
'studio.noAccounts': 'No store account in this studio yet: add one below and pick this studio.',
|
|
'studio.allAssigned': 'Every account is in a studio.',
|
|
'color.indigo': 'Indigo',
|
|
'color.violet': 'Violet',
|
|
'color.rose': 'Rose',
|
|
'color.amber': 'Amber',
|
|
'color.emerald': 'Emerald',
|
|
'color.teal': 'Teal',
|
|
'color.sky': 'Sky',
|
|
'color.slate': 'Slate',
|
|
'accounts.leadStudios': 'Studios group your store accounts: Google Play service accounts and App Store Connect team keys. Keys stay in the system keychain; apps come in with Import apps.',
|
|
'accounts.emptyTextStudios': 'Add a studio, then its Google Play service account and App Store Connect keys. Import apps then lists every app those keys can see.',
|
|
'accounts.playSubMany': 'Service account JSON key. One service account can be invited to several Play developer accounts: it sees all their apps.',
|
|
'accounts.appleSubMany': 'One API key per team (company or individual): key id, issuer id and the .p8 file.',
|
|
'accounts.safetyStudios': 'Keys are read once from the file you pick, stored in the system keychain and never shown again. storebound gets one account\'s key in memory for one call. Studio names, labels and app lists stay on this computer.',
|
|
'acct.ok': 'Works',
|
|
'acct.noApps': 'No apps',
|
|
'acct.permission': 'Permission missing',
|
|
'acct.revoked': 'Key revoked',
|
|
'acct.apiDisabled': 'API off',
|
|
'acct.error': 'Not reachable',
|
|
'acct.notTested': 'Not tested',
|
|
'acct.kindPlay': 'Google Play service account',
|
|
'acct.kindApple': 'App Store Connect team key',
|
|
'acct.appsRead': '{count} apps, read {when}',
|
|
'acct.appsRead_one': '1 app, read {when}',
|
|
'acct.notImported': 'apps not imported yet',
|
|
'acct.folders': 'used by {count} folders',
|
|
'acct.folders_one': 'used by 1 folder',
|
|
'acct.test': 'Test',
|
|
'acct.testAll': 'Test all accounts',
|
|
'acct.import': 'Import apps',
|
|
'acct.edit': 'Rename or move to a studio',
|
|
'acct.editAria': 'Edit {label}',
|
|
'acct.ignore': 'Ignore this account',
|
|
'acct.ignoreHint': 'Ignore: leave this account\'s apps out of the portfolio and store reads',
|
|
'acct.unignore': 'Show this account again',
|
|
'acct.ignored': 'Ignored',
|
|
'acct.openFix': 'Open',
|
|
'ignored.lead': 'Apps and accounts left out of the portfolio, the sidebar and store reads. Nothing on the stores changes.',
|
|
'ignored.restoreAll': 'Restore all',
|
|
'ignored.restore': 'Restore',
|
|
'ignored.emptyTitle': 'Nothing is ignored',
|
|
'ignored.emptyText': 'Ignore an app from its page (or a whole account in Studios & accounts) to keep test apps and old titles out of the way.',
|
|
'ignored.apps': 'Apps',
|
|
'ignored.appsSub': '{count} ignored',
|
|
'ignored.accounts': 'Accounts',
|
|
'ignored.accountsSub': 'Every app of these accounts is left out',
|
|
'ignored.accountApps': '{count} apps',
|
|
'ignored.accountApps_one': '1 app',
|
|
'ignored.noApps': 'No ignored app.',
|
|
'ignored.noAccounts': 'No ignored account.',
|
|
'ignored.howTo': 'Pairing and single-store apps:',
|
|
'ignored.toPairing': 'Settings > App pairing',
|
|
'pair.folder': 'From its app folder',
|
|
'pair.manual': 'Paired by hand',
|
|
'pair.id': 'Paired: same bundle id and package name',
|
|
'pair.close': 'Paired: close ids',
|
|
'pair.name': 'Paired: same name',
|
|
'pair.single': 'One store only',
|
|
'app.moveStudio': 'Move to a studio',
|
|
'app.pairWith': 'Pair with',
|
|
'app.pairWithName': 'Pair {name} with',
|
|
'app.pick': 'Pick an app',
|
|
'app.unpair': 'Unpair',
|
|
'app.ignore': 'Ignore',
|
|
'app.ignoreHint': 'Leave this app out of the portfolio and store reads (Ignored lists it to restore)',
|
|
'app.studioHint': 'Open the studio',
|
|
'app.storeOnlyTitle': 'Store only.',
|
|
'app.storeOnlyText': 'This app is on your store accounts but has no app folder: releases, reviews, health and TestFlight are shown read-only. Link its folder, or start one, to manage listings, products and checks.',
|
|
'app.linkFolder': 'Link a folder',
|
|
'app.initHere': 'Start an app folder here',
|
|
'app.linked': '{name} is linked',
|
|
'app.linkFailed': 'Could not link the folder',
|
|
'portfolio.subStudios': '{count} apps · {stores} store listings · {studios} studios',
|
|
'portfolio.emptyAccounts': 'Add a studio and its accounts',
|
|
'portfolio.notImported': 'Apps of {count} accounts are not imported yet: Import apps lists everything those keys can see.',
|
|
'portfolio.notImported_one': 'Apps of 1 account are not imported yet: Import apps lists everything its key can see.',
|
|
'portfolio.toolbar': 'Filter and sort the apps',
|
|
'portfolio.search': 'Search apps, bundle ids, packages',
|
|
'portfolio.studioFilter': 'Studio',
|
|
'portfolio.allStudios': 'All studios',
|
|
'portfolio.sort': 'Sort',
|
|
'portfolio.sortAttention': 'Needs attention',
|
|
'portfolio.sortRecent': 'Recently updated',
|
|
'portfolio.sortName': 'Name',
|
|
'portfolio.group': 'Group by studio',
|
|
'portfolio.groupCount': '{count} apps',
|
|
'portfolio.noConfig': 'No config',
|
|
'portfolio.storeOnlyCheck': 'Store only',
|
|
'portfolio.noMatch': 'No app matches',
|
|
'portfolio.noMatchText': 'Clear the search or pick another studio.',
|
|
'portfolio.studiosN': '{count} studios',
|
|
'portfolio.studiosN_one': '1 studio',
|
|
'portfolio.folders': 'App folders',
|
|
'portfolio.foldersN': '{count} folders · {store} store only',
|
|
'portfolio.ignoredN': '{count} apps',
|
|
'portfolio.ignoredN_one': '1 app',
|
|
'kpi.appsSubStore': 'iOS {ios} · Android {android} · {store} store only',
|
|
'toast.importing': 'Importing apps',
|
|
'toast.importingDetail': 'Every app each account can see (read-only)',
|
|
'toast.importDone': '{count} apps on your accounts',
|
|
'toast.importDone_one': '1 app on your accounts',
|
|
'toast.importDoneDetail': 'from {count} accounts',
|
|
'toast.importDoneDetail_one': 'from 1 account',
|
|
'toast.importPartial': '{count} accounts could not be read',
|
|
'toast.importPartial_one': '1 account could not be read',
|
|
'toast.saveFailed': 'Not saved',
|
|
'notify.releaseTitle': '{name}: store state changed',
|
|
'notify.releaseBody': '{store} {version}: {phase}',
|
|
'notify.lowTitle': '{name}: {count} new low ratings',
|
|
'notify.lowTitle_one': '{name}: a new low rating',
|
|
'notify.crashTitle': '{name}: over the Play threshold',
|
|
'set.lead': 'Studios, accounts, store reads, the offline cache, language, theme, notifications and more. Everything stays on this computer.',
|
|
'set.sections': 'Settings sections',
|
|
'set.studios': 'Studios & accounts',
|
|
'set.studiosSub': 'Which accounts belong to which studio',
|
|
'set.studioLine': 'Play {play} · App Store {apple} · {apps} apps',
|
|
'set.noStudios': 'No studio yet. Studios group accounts and their apps in the portfolio and the sidebar.',
|
|
'set.manage': 'Manage',
|
|
'set.pairing': 'App pairing & ignore list',
|
|
'set.pairingSub': 'An iOS and an Android app become one card when their ids or names match; pair or split them by hand here',
|
|
'set.pairedHow': 'Pairing',
|
|
'set.noCandidates': 'Nothing to pair with',
|
|
'set.noStoreOnly': 'Every app has its folder: pairing comes from the configs.',
|
|
'set.ignoredLine': 'Ignored: {count} apps, {accounts} accounts.',
|
|
'set.openIgnored': 'Open the list',
|
|
'set.refresh': 'Store reads',
|
|
'set.refreshSub': 'Reads use each account\'s API quota: they run when you ask, or on the schedule here',
|
|
'set.autoRefresh': 'Read the stores automatically',
|
|
'set.autoHint': 'While the app is open. Off by default.',
|
|
'set.off': 'Off',
|
|
'set.min': '{n} min',
|
|
'set.hour': '{n} h',
|
|
'set.onLaunch': 'Read when the app starts',
|
|
'set.onLaunchHint': 'Imports the apps of every account, then reads every app\'s store status',
|
|
'set.icons': 'Store icons on import',
|
|
'set.iconsHint': 'One extra request per app; folders use their own icon',
|
|
'set.parallel': 'Apps read at the same time',
|
|
'set.parallelHint': 'Fewer is gentler on rate limits',
|
|
'set.cache': 'Offline cache',
|
|
'set.cacheSub': 'The last store reads, shown with their time when you are offline',
|
|
'set.cacheSize': 'On disk',
|
|
'set.cacheRows': '{count} saved reads',
|
|
'set.cacheRows_one': '1 saved read',
|
|
'set.cacheOldest': 'Oldest',
|
|
'set.keep': 'Keep saved reads',
|
|
'set.days': '{n} days',
|
|
'set.year': '1 year',
|
|
'set.always': 'Always',
|
|
'set.notifications': 'Notifications',
|
|
'set.notificationsSub': 'After a read, when something changed since the previous one',
|
|
'set.nReview': 'Review and release state changes',
|
|
'set.nReviewHint': 'In review, approved, rejected, live, halted',
|
|
'set.nLow': 'New 1 or 2 star reviews',
|
|
'set.nLowHint': 'When the Reviews tab reads new ones',
|
|
'set.nCrash': 'Crash or ANR rate over the threshold',
|
|
'set.nCrashHint': 'Google Play bad behavior thresholds',
|
|
'set.testNotify': 'Send a test notification',
|
|
'set.testTitle': 'storebound',
|
|
'set.testBody': 'Notifications work.',
|
|
'set.appCopy': 'app copy',
|
|
'set.depsText': 'Store work needs no local tool. Screenshots, previews and icons use ffmpeg and Chrome: one click on the Dependencies screen.',
|
|
'set.cli': 'CLI sidecar',
|
|
'set.protocol': 'Protocol',
|
|
'set.state': 'State',
|
|
'set.running': 'Running',
|
|
'set.writes': 'Writes',
|
|
'set.writesText': 'Dry run first, then your Apply in a system dialog. Submit, release and publish stay in the consoles.',
|
|
'set.privacy': 'Privacy',
|
|
'set.p1': 'No telemetry, no analytics, no crash reports: the app talks only to the stores, with your keys, when you ask.',
|
|
'set.p2': 'Store keys live in the system keychain; the app data folder holds names, settings and saved reads, never keys.',
|
|
'set.p3': 'Nothing is written into your app folders unless you confirm it in a system dialog.',
|
|
'set.p4': 'Tester emails stay masked; review drafts stay in each app folder\'s .storebound/ (gitignored).',
|
|
'set.reveal': 'Show the data folder',
|
|
'set.scQuit': 'Quit',
|
|
'set.updates': 'Updates',
|
|
'set.channel': 'Channel',
|
|
'set.stable': 'Stable',
|
|
'set.beta': 'Beta',
|
|
'set.updatesText': 'Updates come from storebound.dev and are signed; the app checks the signature before it replaces anything, and installs only when you press Install. Nothing is checked in the background.',
|
|
'set.updateCheck': 'Check for updates',
|
|
'set.updateChecking': 'Checking…',
|
|
'set.updateNone': 'storebound {version} is the newest version on the {channel} channel.',
|
|
'set.updateAvailable': 'storebound {version} is available.',
|
|
'set.updateInstall': 'Install {version}…',
|
|
'set.updateInstalling': 'Downloading the update… {done}',
|
|
'set.reset': 'Reset',
|
|
'set.resetText': 'Forgets {accounts} accounts (their keys are removed from the keychain), {studios} studios, {folders} app folders (the folders stay on disk), pairing, the ignore list, settings and saved reads. A system dialog asks first.',
|
|
'set.resetButton': 'Reset the app',
|
|
'set.resetDone': 'storebound desktop was reset',
|
|
'set.footer': '{n} apps known to this computer',
|
|
|
|
'studio.counts_one': '1 account · {apps} apps · {store} store only',
|
|
'portfolio.groupCount_one': '1 app',
|
|
'portfolio.groupAccounts': '{count} accounts',
|
|
'portfolio.groupAccounts_one': '1 account',
|
|
|
|
'write.dryRunning': 'Dry run first: nothing changes yet',
|
|
'write.notApplied': 'Not applied',
|
|
'write.notAppliedDetail': 'You chose Cancel in the dialog: nothing changed.',
|
|
'act.storeTitle': 'Push to the stores',
|
|
'act.storeSub': 'Listing text, screenshots and previews from this folder, and the local renders',
|
|
'act.playListing': 'Listing text',
|
|
'act.playListingDone': 'Play listing updated',
|
|
'act.playImages': 'Graphics and screenshots',
|
|
'act.version': 'Version',
|
|
'act.appleListing': 'Version {version} and its text',
|
|
'act.appleListingDone': 'App Store version and text updated',
|
|
'act.appleShots': 'Screenshots',
|
|
'act.applePreviews': 'App previews',
|
|
'act.uploaded': 'Uploaded',
|
|
'act.slowHint': 'Can take minutes: progress shows in the toast, Cancel stops it',
|
|
'act.render': 'Render (local)',
|
|
'act.renderLang': 'Language to render',
|
|
'act.allLangs': 'All languages',
|
|
'act.renderShots': 'Render screenshots',
|
|
'act.renderVideo': 'Cut app previews',
|
|
'act.icons': 'Generate icons',
|
|
'act.gallery': 'Review gallery',
|
|
'act.galleryDone': 'Gallery written next to the renders',
|
|
'act.rendered': 'Done',
|
|
'act.localHint': 'Local files only; needs ffmpeg and Chrome (Dependencies)',
|
|
'act.note': 'Each action runs a dry run and shows it in a system dialog before anything changes. Nothing here submits for review or publishes: that stays in the consoles.',
|
|
'act.catalogTitle': 'Sync the catalog',
|
|
'act.catalogSub': 'Create and update products and subscriptions with their regional prices from the config',
|
|
'act.playProducts': 'One-time products',
|
|
'act.playSubs': 'Subscriptions',
|
|
'act.appleIap': 'In-app purchases',
|
|
'act.appleSubs': 'Subscriptions',
|
|
'act.synced': 'Catalog updated',
|
|
'act.prices': 'Prices',
|
|
'act.pricesExport': 'Export prices (CSV)',
|
|
'act.pricesExported': 'Prices exported into the folder',
|
|
'act.pricesImport': 'Changing live prices from a sheet stays a terminal step:',
|
|
'act.catalogNote': 'Never submits: new items wait in the consoles until you send them with a version.',
|
|
'roll.playNow': 'Rollout {pct} %',
|
|
'roll.share': 'New user share',
|
|
'roll.toShare': 'Raise to {pct} %',
|
|
'roll.halt': 'Halt',
|
|
'roll.haltHint': 'Stops new installs of the update; not a rollback',
|
|
'roll.halted': 'Rollout halted',
|
|
'roll.resume': 'Resume',
|
|
'roll.complete': 'Everyone (100 %)',
|
|
'roll.completeHint': 'Completes the staged rollout: every user gets the update',
|
|
'roll.done': 'Rollout updated',
|
|
'roll.iosNow': 'Phased release, day {day} of 7',
|
|
'roll.pause': 'Pause',
|
|
'roll.pauseHint': 'Holds the automatic updates (up to 30 days); not a rollback',
|
|
'roll.paused': 'Phased release paused',
|
|
'roll.everyone': 'Release to everyone',
|
|
'roll.everyoneHint': 'Ends the phased release: every user with automatic updates gets it now',
|
|
'roll.phasedOn': 'Turn on phased release',
|
|
'roll.phasedOnHint': 'When this version goes live, it reaches users with automatic updates over 7 days',
|
|
'roll.phasedOnDone': 'Phased release is on',
|
|
'tf.what': 'What to Test',
|
|
'tf.groupsBtn': 'Internal groups',
|
|
'tf.whatToTest': 'What to Test for build {build}',
|
|
'tf.whatPlaceholder': 'What changed and what to look at (every App Store locale gets this text)',
|
|
'tf.whatSave': 'Set this text',
|
|
'tf.whatFromFile': 'From the listing file',
|
|
'tf.whatFromFileHint': 'Each locale\'s whatToTest (or What\'s New) from the App Store listing file',
|
|
'tf.whatSaved': 'What to Test updated',
|
|
'tf.toInternal': 'Give build {build} to internal groups',
|
|
'tf.noInternal': 'No internal group: create one in App Store Connect or with apple.testflight.groups.',
|
|
'tf.distribute': 'Give to these groups',
|
|
'tf.distributed': 'Build added to the groups',
|
|
'tf.externalNote': 'External groups and Beta App Review stay in App Store Connect.',
|
|
'tf.testersTitle': 'Testers',
|
|
'tf.testersSub': 'From the testers CSV in this folder (.storebound/testers.csv, never committed)',
|
|
'tf.testersGroup': 'Group',
|
|
'tf.testersAll': 'Every group in the CSV',
|
|
'tf.testersAdd': 'Add new testers',
|
|
'tf.testersHint': 'Apple emails each new tester an invitation once the group has a build',
|
|
'tf.testersDone': 'Testers added',
|
|
'tf.testersNote': 'Emails stay masked in every line and dialog. Removing testers stays a terminal step.',
|
|
'reviews.replyEditor': 'Reply',
|
|
'reviews.replyPlaceholder': 'Plain text, in the reviewer\'s language. No incentives, no personal data.',
|
|
'reviews.unsaved': 'Not saved',
|
|
'reviews.save': 'Save draft',
|
|
'reviews.saved': 'Draft saved (approve it again)',
|
|
'reviews.send': 'Send reply',
|
|
'reviews.sendHint': 'Public: the reviewer is notified. A system dialog shows the reply first.',
|
|
'reviews.sent': 'Reply sent',
|
|
'reviews.incentive': 'Offers something for a rating or asks for stars: not allowed',
|
|
'reviews.tooLong': 'Longer than the store allows ({limit} characters)',
|
|
'reviews.sendNoteD3': 'Replies are public. Save, approve, then Send: each step shows a system dialog first.',
|
|
|
|
// ---- every CLI area in the window: prices, store art, growth, app info, exports, onboarding ----
|
|
'tab.prices': 'Prices',
|
|
'tab.art': 'Store art',
|
|
'tab.growth': 'Growth',
|
|
'tab.appinfo': 'App info',
|
|
'col.date': 'Date',
|
|
'common.yes': 'Yes',
|
|
'common.no': 'No',
|
|
|
|
'export.button': 'Export',
|
|
'export.hint': 'Save what this screen shows as a file (CSV or Markdown)',
|
|
'export.saved': 'Saved',
|
|
'export.failed': 'Export failed',
|
|
'export.readFirst': 'Read it first',
|
|
'export.personal': 'personal data',
|
|
'export.prices': 'Prices (CSV, price sheet format)',
|
|
'export.reviews': 'Reviews (CSV)',
|
|
'export.health': 'Health report (Markdown)',
|
|
'export.validate': 'Store readiness report (Markdown)',
|
|
'export.catalog': 'Catalog parity (Markdown)',
|
|
'export.listings': 'Listings (Markdown)',
|
|
'export.noListings': 'No listing files in this app folder',
|
|
'export.portfolio': 'Portfolio (CSV)',
|
|
'export.noApps': 'No apps yet',
|
|
'export.declarations': 'Store declarations (Markdown)',
|
|
'export.dataSafety': 'Data safety (Play CSV)',
|
|
'export.noDataSafety': 'The config has no Data safety answers',
|
|
'export.analytics': 'Analytics, daily (CSV)',
|
|
|
|
'palette.gExport': 'Export',
|
|
'palette.export': 'Export: {what}',
|
|
'palette.prices': '{name} · Prices and price sheet',
|
|
'palette.art': '{name} · Store art gallery',
|
|
|
|
'hint.keys': 'Map a store account to this app in App folders, or add the key in Studios & accounts.',
|
|
'hint.permission': 'The key works but lacks a permission: Studios & accounts > Test shows the fix.',
|
|
'hint.config': 'Set that value in storebound.config.ts (the Checks tab lists what is missing).',
|
|
'hint.renders': 'Render the screenshots first: Store art > Render.',
|
|
'hint.ffmpeg': 'Download ffmpeg on the Dependencies screen (one click, checked by hash).',
|
|
'hint.chrome': 'Download Chrome for Testing on the Dependencies screen.',
|
|
'hint.snapshot': 'Take a snapshot first: Growth > Take a snapshot.',
|
|
'hint.bucket': 'Set play.reportsBucket in the config (Play Console > Download reports > Statistics > Copy Cloud Storage URI).',
|
|
'hint.analyticsSetup': 'Start the App Store reports once: Growth > Start App Store reports (Admin key); data comes 1-2 days later.',
|
|
'hint.version': 'Create the version first: Listings > Push App Store version and text.',
|
|
'hint.fastlane': 'Pick the folder that contains fastlane/ (or ios/fastlane, android/fastlane).',
|
|
'hint.priceSheet': 'Write the sheet first: Prices > Write store/prices.csv, or pick a CSV.',
|
|
'hint.pricePoint': 'App Store prices must be one of Apple\'s price points: export with equalized prices to see them.',
|
|
'hint.network': 'Check the internet connection and try again.',
|
|
'hint.confirm': 'This step needs your confirmation in the dialog; run it again and press the button.',
|
|
'hint.git': 'The app folder must be a git repository with history (analytics compare reads git log).',
|
|
|
|
'prices.readTitle': 'Prices',
|
|
'prices.sheetTitle': 'Price sheet',
|
|
'prices.sheetSub': 'Every product x store x region in one CSV: export it, edit it, compare it, apply it',
|
|
'prices.exportCsv': 'Export prices CSV',
|
|
'prices.getSheet': 'Get the sheet',
|
|
'prices.readFirst': 'Read prices first',
|
|
'prices.writeProject': 'Write store/prices.csv',
|
|
'prices.writeHint': 'Writes the current prices into the app folder for `storebound prices import` (dry run first)',
|
|
'prices.compareHead': 'Compare and apply',
|
|
'prices.pickSheet': 'Compare a sheet…',
|
|
'prices.pickFailed': 'Could not open the sheet',
|
|
'prices.compareProject': 'Compare store/prices.csv',
|
|
'prices.showSheet': 'Show the sheet in the folder',
|
|
'prices.noSheetYet': 'No price sheet yet',
|
|
'prices.sheetNote': 'Reading changes nothing. Applying a sheet is your decision: storebound shows the dry run in a system dialog and writes only after you press its button. An App Store price increase cannot be undone once it starts.',
|
|
'prices.compareTitle': 'Compare the price sheet',
|
|
'prices.diffTitle': 'Sheet {file} against the stores',
|
|
'prices.diffSub': 'What would change on each store',
|
|
'prices.compareAgain': 'Compare again',
|
|
'prices.apply': 'Apply {count} changes',
|
|
'prices.apply_one': 'Apply 1 change',
|
|
'prices.applied': 'Prices written',
|
|
'prices.applyNote': 'Owner action: the stores apply new prices within hours, users see them then. Play regions without a price get Play\'s conversion of the US price.',
|
|
'prices.upToDate': 'Prices match the sheet',
|
|
'prices.upToDateText': 'Nothing to apply. Edit the sheet, then compare again.',
|
|
'prices.dChanged': '{count} changed',
|
|
'prices.dNew': '{count} new',
|
|
'prices.dUp': '{count} up',
|
|
'prices.dDown': '{count} down',
|
|
'prices.dProducts': 'Products: {list}',
|
|
'prices.colStarts': 'Starts',
|
|
'prices.colNow': 'Now',
|
|
'prices.colNew': 'New',
|
|
'prices.colKind': 'Set by',
|
|
'prices.now': 'now',
|
|
'prices.new': 'New',
|
|
'prices.more': '{count} more rows in the sheet',
|
|
'prices.emptyTitle': 'No in-app products in the config',
|
|
'prices.emptyText': 'Prices are read for the products of storebound.config.ts. Add them there (store-iap-setup skill), then create them on the stores from the Catalog tab.',
|
|
'prices.emptyHint': 'in storebound.config.ts',
|
|
'prices.notReadTitle': 'Prices not read yet',
|
|
'prices.notReadText': 'One read-only pass over App Store Connect and Google Play lists every product\'s price in every territory. It uses the accounts\' API quota.',
|
|
'prices.readNow': 'Read prices',
|
|
'prices.kProducts': 'Products',
|
|
'prices.kProductsSub': '{count} prices read',
|
|
'prices.kRegions': 'Territories',
|
|
'prices.kRegionsAuto': 'App Store equalized prices included',
|
|
'prices.kRegionsManual': 'App Store manual prices only',
|
|
'prices.kGaps': 'Price gaps',
|
|
'prices.kGapsSub': '≥ {pct} % apart in the same currency',
|
|
'prices.kMissing': 'Not on a store',
|
|
'prices.kMissingNone': 'Every product is on its stores',
|
|
'prices.overview': 'Products x key territories',
|
|
'prices.withAuto': 'App Store equalized prices',
|
|
'prices.auto': 'Equalized',
|
|
'prices.manual': 'Manual',
|
|
'prices.autoLegend': 'grey: App Store equalized from the base territory',
|
|
'prices.gapLegend': 'Δ: gap between the stores ≥ {pct} %',
|
|
'prices.perRegion': '{product} in every territory',
|
|
'prices.perRegionSub': '{count} territories',
|
|
'prices.searchRegion': 'Territory or currency',
|
|
'prices.otherCurrency': 'other currency',
|
|
'prices.scheduled': 'from {date}: {price}',
|
|
'prices.missingNote': 'Not on the store yet: {list}. Create them from the Catalog tab, then read again.',
|
|
'cat.openPrices': 'Open prices',
|
|
'cat.pricesHere': 'Prices per territory, the price sheet and applying it are on the Prices tab.',
|
|
|
|
'art.title': 'Store art',
|
|
'art.images': 'Images',
|
|
'art.imagesSub': '{count} languages',
|
|
'art.imagesSub_one': '1 language',
|
|
'art.videos': 'App previews',
|
|
'art.videosSub': 'App Store and promo videos',
|
|
'art.errors': 'Store errors',
|
|
'art.errorsSub': 'Size, alpha, format, count',
|
|
'art.warnings': 'Warnings',
|
|
'art.rendered': 'Scanned {when}',
|
|
'art.variant': 'Variant',
|
|
'art.base': 'Base',
|
|
'art.onlyIssues': 'Only issues',
|
|
'art.openFolder': 'Open folder',
|
|
'art.openPage': 'Open review page',
|
|
'art.openPageHint': 'Opens the gallery page (index.html) in your browser',
|
|
'art.writePage': 'Write review page',
|
|
'art.render': 'Render {lang}',
|
|
'art.notThere': 'Not there yet',
|
|
'art.count': '{count} files',
|
|
'art.count_one': '1 file',
|
|
'art.open': 'Open {name}',
|
|
'art.tooBig': 'too big to preview',
|
|
'art.prev': 'Previous',
|
|
'art.next': 'Next',
|
|
'art.emptyTitle': 'No renders yet',
|
|
'art.emptyText': 'Render the store screenshots from the frames and the copy file: press Render. It runs locally (ffmpeg and Chrome) and uploads nothing.',
|
|
'art.noIssues': 'No issues here',
|
|
'art.noIssuesText': 'Every file of this language passes the local store checks.',
|
|
'art.foot': 'Local files only, read {when}. Uploading is on the Listings tab.',
|
|
|
|
'gr.analytics': 'Store analytics',
|
|
'gr.analyticsSub': '{count} snapshots since {since}',
|
|
'gr.analyticsSubNone': 'Snapshots in .storebound/analytics, next to the listing changes in git',
|
|
'gr.setup': 'Start App Store reports',
|
|
'gr.setupDone': 'Report request created',
|
|
'gr.setupHint': 'Creates the ongoing App Store analytics report request once (Admin key). Changes nothing public.',
|
|
'gr.snapshot': 'Take a snapshot',
|
|
'gr.snapshotDone': 'Snapshot saved',
|
|
'gr.snapshotHint': 'Reads impressions, page views, downloads (App Store) and visitors, installs (Play) into .storebound/analytics',
|
|
'gr.noneTitle': 'No analytics snapshots yet',
|
|
'gr.noneText': 'A snapshot keeps 28 days of store traffic in the app folder (.storebound/analytics). With a few of them, this tab shows each listing change from git next to the conversion before and after it.',
|
|
'gr.noBucket': 'For Google Play, set play.reportsBucket in the config first.',
|
|
'gr.impressions': 'Impressions',
|
|
'gr.downloads': 'Downloads',
|
|
'gr.visitors': 'Listing visitors',
|
|
'gr.acquisitions': 'Acquisitions',
|
|
'gr.conversion': 'Conversion',
|
|
'gr.conversionSub': 'Installs per reach, whole window',
|
|
'gr.days': '{count} days',
|
|
'gr.days_one': '1 day',
|
|
'gr.daysN': '{count} days',
|
|
'gr.daysN_one': '1 day',
|
|
'gr.chartAria': 'Daily store traffic on {store} with listing changes',
|
|
'gr.changes': '{count} listing changes',
|
|
'gr.changes_one': '1 listing change',
|
|
'gr.indexLabel': 'Index: 100 = each line\'s own average over these days. Hover for the real numbers.',
|
|
'gr.noDataTitle': 'No {store} days in the snapshots yet',
|
|
'gr.noDataText': 'The snapshots read no daily numbers for this store yet. Take a new snapshot once the store has data.',
|
|
'gr.oneDay': 'One day of data so far: the chart starts with the second day.',
|
|
'gr.change': 'Listing change (git)',
|
|
'gr.before': 'Before',
|
|
'gr.after': 'After',
|
|
'gr.reading': 'A change needs several days on both sides and enough traffic; seasonality, featuring and ads move these numbers too.',
|
|
'gr.aso': 'ASO',
|
|
'gr.asoSub': 'aso audit, offline, {date}',
|
|
'gr.asoSubNone': 'Keyword field, rank trend and next steps from the app folder (aso audit, offline)',
|
|
'gr.asoField': 'Keyword field',
|
|
'gr.asoFieldSub': 'check --aso over store/appstore.md',
|
|
'gr.asoErrors': '{count} errors',
|
|
'gr.asoErrors_one': '1 error',
|
|
'gr.asoWarnings': '{count} warnings',
|
|
'gr.asoWarnings_one': '1 warning',
|
|
'gr.asoDrafts': 'Draft keywords to review: {locales}',
|
|
'gr.asoRanked': 'Keywords ranked',
|
|
'gr.asoLatest': 'In the first 200 results · {date}',
|
|
'gr.asoNoRanks': 'No rank snapshot yet: storebound aso rank',
|
|
'gr.asoGaps': 'Coverage gaps',
|
|
'gr.asoGapsSub': 'Words in top apps\' names you do not cover · {date}',
|
|
'gr.asoNoCompetitors': 'No competitor snapshot yet: storebound aso competitors',
|
|
'gr.asoChartAria': 'Keyword ranks over the rank snapshots, rank 1 at the top',
|
|
'gr.asoNotRanked': 'not ranked',
|
|
'gr.asoKeyword': 'Keyword',
|
|
'gr.asoRank': 'Rank',
|
|
'gr.asoBest': 'Best',
|
|
'gr.asoNext': 'Next 3 actions',
|
|
'gr.asoReading': 'Ranks follow the public iTunes Search API order, which is close to, not equal to, App Store search: read them as a trend. Popularity comes only from Apple Ads (aso suggest with an Apple Ads API key), never estimated.',
|
|
'gr.ppo': 'Product Page Optimization',
|
|
'gr.ppoSub': 'App Store A/B tests of the screenshots',
|
|
'gr.ppoRead': 'Read tests',
|
|
'gr.ppoNotRead': 'Tests not read yet',
|
|
'gr.ppoNotReadText': 'Read-only: the tests, their state, traffic share and treatments. Results per treatment are only in App Store Connect.',
|
|
'gr.ppoNone': 'No tests yet',
|
|
'gr.ppoNoneText': 'Create a test from a screenshot variant below, upload its screenshots, then start it.',
|
|
'gr.ppoNoVariants': 'Add a screenshot variant to shots.variants in the config (store-screenshots skill) and render it; each variant becomes one treatment.',
|
|
'gr.results': 'Results in App Store Connect',
|
|
'gr.test': 'Test',
|
|
'gr.state': 'State',
|
|
'gr.traffic': 'Traffic',
|
|
'gr.dates': 'Running',
|
|
'gr.treatments': 'Treatments',
|
|
'gr.owner': 'Owner action',
|
|
'gr.running': 'running',
|
|
'gr.notStarted': 'not started',
|
|
'gr.treatment': '{name} ({count} locales)',
|
|
'gr.treatment_one': '{name} (1 locale)',
|
|
'gr.startBtn': 'Start',
|
|
'gr.stopBtn': 'Stop',
|
|
'gr.start': 'Start the test "{name}"',
|
|
'gr.stop': 'Stop the test "{name}"',
|
|
'gr.started': 'Test start requested',
|
|
'gr.stopped': 'Test stop requested',
|
|
'gr.create': 'New test',
|
|
'gr.variant': 'Variant {id}',
|
|
'gr.createBtn': 'Create test',
|
|
'gr.createTitle': 'Create a Product Page Optimization test',
|
|
'gr.created': 'Test created (not started)',
|
|
'gr.upload': 'Treatment screenshots',
|
|
'gr.uploadBtn': 'Upload screenshots',
|
|
'gr.uploadTitle': 'Upload the screenshots of variant {id}',
|
|
'gr.uploadInto': 'Into the editable test "{name}"',
|
|
'gr.uploadNoTest': 'Create a test first: uploads go into the editable test.',
|
|
'gr.ppoNote': 'Create and upload change nothing visitors see. Start and stop are your decision: each shows a system dialog that names the action; a stopped test cannot be restarted.',
|
|
'gr.ppoStoreOnly': 'Read-only for a store-only app: link an app folder to create and run tests.',
|
|
'gr.playExp': 'Store listing experiments',
|
|
'gr.playExpSub': 'Google Play: no API',
|
|
'gr.playExpText': 'Google Play has no API for store listing experiments: create and run them in Play Console > Grow > Store listing experiments, with the variant screenshots storebound renders.',
|
|
'gr.seeVariants': 'See the variant renders',
|
|
|
|
'ai.askTitle': '{count} questions only you can answer',
|
|
'ai.askTitle_one': '1 question only you can answer',
|
|
'ai.askSub': 'The config does not prove these answers. storebound never guesses a compliance answer: decide, then set it in the config.',
|
|
'ai.allAnswered': 'Every declaration this tab shows comes from the config. The answers are still yours: review them before each submission.',
|
|
'ai.aDataSafety': 'Data safety',
|
|
'ai.aAppPrivacy': 'App Privacy',
|
|
'ai.aAppInfo': 'App info',
|
|
'ai.aEncryption': 'Export compliance',
|
|
'ai.aReview': 'App Review',
|
|
'ai.askedHere': '{count} open questions about this form above',
|
|
'ai.askedHere_one': '1 open question about this form above',
|
|
'ai.dsTitle': 'Data safety',
|
|
'ai.dsSub': 'Google Play, from dataSafety in the config',
|
|
'ai.dsUpload': 'Upload Data safety',
|
|
'ai.dsUploadHint': 'Replaces the whole Play Data safety form (dry run and system dialog first)',
|
|
'ai.dsUploaded': 'Data safety uploaded',
|
|
'ai.dsNoneTitle': 'No Data safety answers',
|
|
'ai.dsNoneText': 'Add dataSafety to storebound.config.ts (store-declarations skill): what the app and every SDK collect, why, and whether it is shared.',
|
|
'ai.dsCollects': 'Collects or shares data',
|
|
'ai.dsEncrypted': 'Encrypted in transit',
|
|
'ai.dsDeletion': 'Users can ask for deletion',
|
|
'ai.dsAccounts': 'Account creation',
|
|
'ai.dsNever': 'Play cannot read this form back. Once you upload from here, this tab shows what changed since.',
|
|
'ai.dsSame': 'Same as the last upload ({when}).',
|
|
'ai.dsChanged': '{count} answers changed since the last upload ({when}): upload again to bring Play up to date.',
|
|
'ai.dsChanged_one': '1 answer changed since the last upload ({when}): upload again to bring Play up to date.',
|
|
'ai.show': 'Show',
|
|
'ai.hide': 'Hide',
|
|
'ai.colType': 'Data type',
|
|
'ai.colCollected': 'Collected for',
|
|
'ai.colShared': 'Shared for',
|
|
'ai.notShared': 'not shared',
|
|
'ai.optional': 'optional',
|
|
'ai.ephemeral': 'ephemeral',
|
|
'ai.dsFoot': 'The upload sends {rows} CSV rows (Play\'s import format) and replaces every earlier answer.',
|
|
'ai.apTitle': 'App Privacy',
|
|
'ai.apSub': 'App Store, suggested from the Data safety answers',
|
|
'ai.apOpen': 'Open App Privacy',
|
|
'ai.apNote': 'App Privacy has no API: enter these answers in App Store Connect > App Privacy. Apple also asks per type whether it is linked to the user and used for tracking.',
|
|
'ai.apNoneTitle': 'No data collected',
|
|
'ai.apNoneText': 'The Data safety answers list no data types: in App Store Connect answer "Data Not Collected", if that is true for every SDK.',
|
|
'ai.apUnknownTitle': 'Nothing to suggest yet',
|
|
'ai.apUnknownText': 'Answer the data collection once in dataSafety; the App Privacy answers follow from it.',
|
|
'ai.colAppleType': 'Data type',
|
|
'ai.colPurposes': 'Purposes',
|
|
'ai.colLinked': 'Linked to user',
|
|
'ai.colTracking': 'Tracking',
|
|
'ai.ask': 'Your answer',
|
|
'ai.askLikely': 'Check: shared',
|
|
'ai.noPlay': 'Not on Google Play',
|
|
'ai.noPlayText': 'The config has no play section.',
|
|
'ai.noApple': 'Not on the App Store',
|
|
'ai.noAppleText': 'The config has no apple section.',
|
|
'ai.infoTitle': 'App info',
|
|
'ai.infoSub': 'Categories, age rating, content rights',
|
|
'ai.infoPush': 'Push the App Store app info',
|
|
'ai.push': 'Push',
|
|
'ai.pushed': 'Pushed to App Store Connect',
|
|
'ai.category': 'Category',
|
|
'ai.age': 'Age rating',
|
|
'ai.ageAllNone': 'Every question "none": confirm',
|
|
'ai.rights': 'Content rights',
|
|
'ai.rightsOwn': 'No third-party content',
|
|
'ai.rightsThird': 'Third-party content, rights held',
|
|
'ai.price': 'Price',
|
|
'ai.free': 'Free, every territory',
|
|
'ai.paid': 'Paid (set in App Store Connect)',
|
|
'ai.notSet': 'Not set',
|
|
'ai.notAnswered': 'Not answered',
|
|
'ai.encTitle': 'Export compliance',
|
|
'ai.encSub': 'Encryption answer for every build',
|
|
'ai.encAnswer': 'Answer builds',
|
|
'ai.encPush': 'Answer export compliance for the builds',
|
|
'ai.encYes': 'Uses non-exempt encryption',
|
|
'ai.encNo': 'Only exempt encryption',
|
|
'ai.encYesText': 'Builds are linked to the approved encryption declaration in App Store Connect.',
|
|
'ai.encNoText': 'Builds without an answer get usesNonExemptEncryption = false. Better: ITSAppUsesNonExemptEncryption = NO in Info.plist.',
|
|
'ai.encUnset': 'apple.usesNonExemptEncryption is not set. Decide it with the export-compliance skill; storebound never guesses it.',
|
|
'ai.encUnsetHint': 'Answer apple.usesNonExemptEncryption in the config first',
|
|
'ai.reviewTitle': 'App Review details',
|
|
'ai.reviewSub': 'Contact, demo account, notes',
|
|
'ai.reviewPush': 'Push the App Review details',
|
|
'ai.signIn': 'Sign-in needed',
|
|
'ai.contact': 'Contact',
|
|
'ai.demo': 'Demo account',
|
|
'ai.demoNone': 'none needed',
|
|
'ai.missing': 'Missing',
|
|
'ai.notes': 'Notes for the reviewer',
|
|
'ai.notesBytes': '{n} / {max} bytes',
|
|
'ai.notesNone': 'No notes (apple.info.reviewNotes, reviewAccess.instructions).',
|
|
'ai.reviewSafe': 'Contact and demo account stay in the app folder\'s .storebound/ (gitignored); shown masked, never the password.',
|
|
'ai.foot': 'From the config and .storebound/, read {when}. Nothing here was sent anywhere.',
|
|
'ds.functionality': 'App functionality',
|
|
'ds.analytics': 'Analytics',
|
|
'ds.communications': 'Developer communications',
|
|
'ds.fraud': 'Fraud prevention, security',
|
|
'ds.advertising': 'Advertising or marketing',
|
|
'ds.personalization': 'Personalization',
|
|
'ds.account': 'Account management',
|
|
|
|
'folders.fastlane': 'Import from fastlane',
|
|
'folders.fastlaneHint': 'Pick a folder with a fastlane setup: storebound shows the import plan in a system dialog, then writes its files next to fastlane (never overwrites)',
|
|
'folders.imported': '{name} imported from fastlane',
|
|
'folders.importedDetail': 'Config, listing files and screenshot frames written. Next: replace the placeholders, then Checks.',
|
|
'folders.startShort': 'Start an app folder',
|
|
'folders.newNote': 'Both ask for a folder in a system dialog, show what they would write, and write only after you press Apply. Existing files are kept.',
|
|
'folders.open': 'Open',
|
|
'folders.openApp': 'Open this app',
|
|
'folders.reveal': 'Show in the file manager',
|
|
|
|
'wz.s0': 'Your studio',
|
|
'wz.studioTitle': 'Which studio are these apps from?',
|
|
'wz.studioLead': 'A studio groups store accounts and their apps (a company, a client, a side project). Pick one or create it; the keys of the next steps go into it. You can move things later.',
|
|
'wz.studioPick': 'Studio',
|
|
'wz.studioAccounts': '{count} store accounts',
|
|
'wz.studioAccounts_one': '1 store account',
|
|
'wz.studioPicked': 'Selected',
|
|
'wz.studioNoneHint': 'Keep accounts without a studio',
|
|
'wz.studioNew': 'Create your studio',
|
|
'wz.studioAnother': 'Or create another studio',
|
|
'wz.studioNewText': 'A name and a colour; a logo can come later in Studios & accounts.',
|
|
'wz.studioPlaceholder': 'For example: Example Games',
|
|
'wz.studioCreate': 'Create studio',
|
|
'wz.fastlaneTitle': 'Import from fastlane',
|
|
'wz.fastlaneText': 'The folder has a fastlane setup (deliver, supply). storebound turns it into its config and listing files and leaves fastlane untouched.',
|
|
'wz.fastlaneGo': 'Choose the folder and import',
|
|
'wz.fastlaneNote': 'You see the import plan and what it does not map before anything is written.',
|
|
'wz.keysInto': 'New keys go into {name}.',
|
|
'wz.keysNoStudio': 'New keys stay without a studio.',
|
|
'wz.change': 'Change',
|
|
|
|
'crash.titleApp': 'storebound hit an error',
|
|
'crash.titleScreen': 'This screen hit an error',
|
|
'crash.leadApp': 'The window could not be shown. Your app folders, store keys and saved data are untouched. Reload usually fixes it; if it keeps happening, copy the details into a bug report.',
|
|
'crash.leadScreen': 'The rest of the app still works. Try again, reload the window, or copy the details into a bug report.',
|
|
'crash.details': 'Details',
|
|
'crash.copy': 'Copy details',
|
|
'crash.copied': 'Details copied.',
|
|
'crash.copyFailed': 'Could not copy: select the details and copy them by hand.',
|
|
'crash.retry': 'Try again',
|
|
'crash.reload': 'Reload',
|
|
'crash.reset': 'Reset saved state (keeps a backup)',
|
|
'crash.resetHint': 'Starts with an empty list. The saved state is kept as a backup file, store keys stay in the keychain, app folders are not touched.',
|
|
'crash.resetDone': 'Saved state reset. Backup: {path}. Reloading…',
|
|
'crash.logNote': 'Also written to logs/webview.log in the app data folder (home folder shown as ~, no keys).',
|
|
'folder.missing': 'Folder not found.',
|
|
'folder.missingText': 'storebound cannot find this app folder at {path}. It may have been moved, renamed or deleted. Locate it to keep its accounts and saved reads, or remove it from the list (no files are touched).',
|
|
'folder.missingShort': 'Folder not found',
|
|
'folder.locate': 'Locate…',
|
|
'folder.locateHint': 'Pick the folder that now holds this app\'s storebound.config.ts',
|
|
'folder.located': '{name} found',
|
|
'folder.locateFailed': 'Could not use that folder',
|
|
'folder.remove': 'Remove from list',
|
|
'folder.removed': '{name} removed from the list',
|
|
|
|
'cf.button': 'Fill in console',
|
|
'cf.hint': 'Fill in {form} in the console from your config: you review every field and press Save yourself',
|
|
'cf.appleAppRecord': 'App Store app record',
|
|
'cf.appleAgeRating': 'App Store age rating',
|
|
'cf.appleAppPrivacy': 'App Privacy',
|
|
'cf.playContentRating': 'Play content rating',
|
|
'cf.playTargetAudience': 'Play target audience and content',
|
|
'cf.playAppRecord': 'Play app (Create app)',
|
|
'cf.dryFailed': 'Could not prepare {form}',
|
|
'cf.panelTitle': 'Fill in console: {form}',
|
|
'cf.disclaimer': 'Console pages change. This is AI-assisted: review every field in the browser and press the final button (Publish, Submit, Save or Create) yourself. storebound moves through the pages for you and never submits or publishes; App Privacy answers stay a draft until you press Publish.',
|
|
'cf.notOpened': 'You chose Cancel in the dialog: no browser was opened.',
|
|
'cf.runningText': 'The browser is open with storebound\'s own profile (the first time, sign in there yourself; it is kept for the next runs). storebound opens the form, fills the fields and marks the ones you answer. Review every field, press Save yourself, then close the browser.',
|
|
'cf.doneText': 'Browser closed. Filled: {filled}, marked for you: {highlighted}. Check in the console that your answers are saved.',
|
|
'cf.closed': 'Browser closed.',
|
|
'cf.cancelled': 'Stopped: the browser was closed.',
|
|
'cf.failed': 'The browser run stopped',
|
|
'cf.fallback': 'The page did not look as expected, so storebound only marked the fields. Enter the answers yourself.',
|
|
'cf.answers': '{count} answers from your config',
|
|
'cf.answers_one': '1 answer from your config',
|
|
'cf.uncertain': '{count} for you',
|
|
'cf.noAnswers': 'The config has no answers for this form: every field is yours.',
|
|
'cf.youAnswer': 'You answer this',
|
|
'cf.foot': 'A native dialog asks once more before the browser opens.',
|
|
'cf.cancelRun': 'Cancel: close the browser',
|
|
'cf.open': 'Open the browser',
|
|
'cf.waiting': 'Waiting until you close the browser',
|
|
'cf.playTitle': 'Play Console forms',
|
|
'cf.playSub': 'No API: storebound fills them in the console, you press the final button',
|
|
'cf.playContentRatingText': 'The IARC questionnaire that gives the app its age ratings.',
|
|
'cf.playTargetAudienceText': 'Target age groups and whether the app appeals to children.',
|
|
'cf.playAppRecordText': 'The Play Developer API cannot create apps: storebound fills Create app (name, language, app or game, free or paid). You tick the declarations and press Create app; the first AAB upload sets the package name.',
|
|
'cf.noRecordTitle': 'No App Store app record yet',
|
|
'cf.noRecordText': 'App Store Connect has no API to create the app record. storebound fills the New App form from your config; you press Create yourself, then put the Apple ID into apple.appId.',
|
|
} as const;
|