From d2b93a019f89c370341aadef17559c9d23fd761c Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Wed, 17 Dec 2025 08:15:52 -0600 Subject: [PATCH] Signed-off-by: Matt Bruce --- Baccarat.xcodeproj/project.pbxproj | 8 + Baccarat/LaunchScreen.storyboard | 49 + Baccarat/Resources/Localizable.xcstrings | 4428 +++++++++-------- Baccarat/Views/BrandingPreviewView.swift | 130 + Baccarat/Views/IconGeneratorView.swift | 192 + CasinoKit/README.md | 378 ++ CasinoKit/Sources/CasinoKit/Exports.swift | 5 + .../CasinoKit/Resources/Localizable.xcstrings | 27 + .../Views/Branding/AppIconView.swift | 218 + .../Views/Branding/IconRenderer.swift | 139 + .../Views/Branding/LaunchScreenView.swift | 351 ++ 11 files changed, 3768 insertions(+), 2157 deletions(-) create mode 100644 Baccarat/LaunchScreen.storyboard create mode 100644 Baccarat/Views/BrandingPreviewView.swift create mode 100644 Baccarat/Views/IconGeneratorView.swift create mode 100644 CasinoKit/README.md create mode 100644 CasinoKit/Sources/CasinoKit/Views/Branding/AppIconView.swift create mode 100644 CasinoKit/Sources/CasinoKit/Views/Branding/IconRenderer.swift create mode 100644 CasinoKit/Sources/CasinoKit/Views/Branding/LaunchScreenView.swift diff --git a/Baccarat.xcodeproj/project.pbxproj b/Baccarat.xcodeproj/project.pbxproj index 511ab95..0ba5be4 100644 --- a/Baccarat.xcodeproj/project.pbxproj +++ b/Baccarat.xcodeproj/project.pbxproj @@ -423,11 +423,14 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = 6R7KLBPBLZ; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_CFBundleDisplayName = Baccarat; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.casino-games"; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES; @@ -440,6 +443,7 @@ MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.mbrucedogs.Baccarat; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_APPROACHABLE_CONCURRENCY = YES; SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor; @@ -455,11 +459,14 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = 6R7KLBPBLZ; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_CFBundleDisplayName = Baccarat; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.casino-games"; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchScreen_Generation = YES; @@ -472,6 +479,7 @@ MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.mbrucedogs.Baccarat; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_APPROACHABLE_CONCURRENCY = YES; SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor; diff --git a/Baccarat/LaunchScreen.storyboard b/Baccarat/LaunchScreen.storyboard new file mode 100644 index 0000000..05f7d66 --- /dev/null +++ b/Baccarat/LaunchScreen.storyboard @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Baccarat/Resources/Localizable.xcstrings b/Baccarat/Resources/Localizable.xcstrings index 6a4a7be..53e85de 100644 --- a/Baccarat/Resources/Localizable.xcstrings +++ b/Baccarat/Resources/Localizable.xcstrings @@ -1,3280 +1,3394 @@ { - "sourceLanguage": "en", - "strings": { - "%lld": { - "comment": "The number of rounds a player has played in the game.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%lld" + "sourceLanguage" : "en", + "strings" : { + "%lld" : { + "comment" : "The number of rounds a player has played in the game.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "%lld" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "%lld" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "%lld" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "%lld" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "%lld" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld" } } } }, - "•": { - "comment": "A bullet point used to list items in a rule section.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "•" + "%lld." : { + "comment" : "A numbered list item with a callout number and accompanying text. The first argument is the number of the item. The second argument is the text of the item.", + "isCommentAutoGenerated" : true + }, + "%lldpx" : { + "comment" : "A text label displaying the size of the app icon. The argument is the size of the icon in pixels.", + "isCommentAutoGenerated" : true + }, + "•" : { + "comment" : "A bullet point used to list items in a rule section.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "•" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "•" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "•" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "•" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "•" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "•" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "•" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "•" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "•" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "•" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "•" } } } }, - "+%lld": { - "comment": "A text element displaying the total winnings in the round, prefixed by a plus sign. The argument is the total winnings amount.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "+%lld" + "• Add to Assets.xcassets/AppIcon" : { + "comment" : "A step in the process of exporting app icons.", + "isCommentAutoGenerated" : true + }, + "• Call IconRenderer.renderAppIcon(config: .baccarat)" : { + + }, + "• Run the preview in Xcode" : { + + }, + "• Save the resulting UIImage to files" : { + "comment" : "A step in the process of exporting app icons.", + "isCommentAutoGenerated" : true + }, + "• Screenshot the 1024px icon" : { + "comment" : "A step in the process of exporting app icons, describing how to take a screenshot of a 1024px icon.", + "isCommentAutoGenerated" : true + }, + "• Use an online tool to generate all sizes" : { + "comment" : "A bullet point in the \"How to Export Icons\" section, describing how to use an online tool to generate all sizes for an app icon.", + "isCommentAutoGenerated" : true + }, + "+%lld" : { + "comment" : "A text element displaying the total winnings in the round, prefixed by a plus sign. The argument is the total winnings amount.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "+%lld" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "+%lld" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "+%lld" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "+%lld" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "+%lld" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "+%lld" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "+%lld" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "+%lld" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "+%lld" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "+%lld" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "+%lld" } } } }, - "$": { - "comment": "The currency symbol \"$\".", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "$" + "$" : { + "comment" : "The currency symbol \"$\".", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "$" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "$" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "$" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "$" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "$" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "$" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "$" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "€" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "€" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "$" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "$" } } } }, - "$%@": { - "comment": "The value of the balance displayed in the top bar.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "$%@" + "$%@" : { + "comment" : "The value of the balance displayed in the top bar.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "$%@" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "$%@" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "$%@" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "$%@" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "$%@" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "$%@" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "$%@" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "%@ €" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ €" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "%@ $" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ $" } } } }, - "$%lldK": { - "comment": "A button that allows the user to select a starting balance for the game.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "$%lldK" + "$%lldK" : { + "comment" : "A button that allows the user to select a starting balance for the game.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "$%lldK" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "$%lldK" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "$%lldK" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "$%lldK" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "$%lldK" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "$%lldK" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "$%lldK" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "%lld K €" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld K €" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "%lld K $" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld K $" } } } }, - "8 : 1": { - "comment": "The payout ratio for a tie bet.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "8 : 1" + "8 : 1" : { + "comment" : "The payout ratio for a tie bet.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "8 : 1" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "8 : 1" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "8 : 1" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "8 : 1" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "8 : 1" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "8 : 1" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "8 : 1" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "8 : 1" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "8 : 1" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "8 : 1" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "8 : 1" } } } }, - "11 : 1": { - "comment": "The payout ratio for a pair bet.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "11 : 1" + "11 : 1" : { + "comment" : "The payout ratio for a pair bet.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "11 : 1" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "11 : 1" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "11 : 1" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "11 : 1" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "11 : 1" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "11 : 1" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "11 : 1" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "11 : 1" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "11 : 1" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "11 : 1" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "11 : 1" } } } }, - "11:1": { - "comment": "The payout ratio for a pair bonus bet.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "11:1" + "11:1" : { + "comment" : "The payout ratio for a pair bonus bet.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "11:1" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "11:1" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "11:1" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "11:1" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "11:1" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "11:1" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "11:1" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "11:1" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "11:1" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "11:1" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "11:1" } } } }, - "B": { - "comment": "The letter \"B\" displayed in the center of the playing card's back.", - "extractionState": "stale", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "B" + "After generating:" : { + "comment" : "A heading for the instructions section of the icon generator view.", + "isCommentAutoGenerated" : true + }, + "All Sizes" : { + "comment" : "A heading that describes the various sizes of the app icon.", + "isCommentAutoGenerated" : true + }, + "Alternative: Use an online tool" : { + "comment" : "A section header that suggests using an online tool to generate app icon sizes.", + "isCommentAutoGenerated" : true + }, + "App Icon" : { + "comment" : "A label displayed above the preview of the app icon.", + "isCommentAutoGenerated" : true + }, + "App Icon Preview" : { + "comment" : "A header describing the preview of the app icon.", + "isCommentAutoGenerated" : true + }, + "B" : { + "comment" : "The letter \"B\" displayed in the center of the playing card's back.", + "extractionState" : "stale", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "B" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "B" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "B" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "B" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "B" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "B" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "B" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "B" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "B" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "B" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "B" } } } }, - "B Pair": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "B Pair" + "B Pair" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "B Pair" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Par B" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Par B" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Par B" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Par B" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Par B" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Par B" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Paire B" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Paire B" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Paire B" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Paire B" } } } }, - "BACCARAT": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "BACCARAT" + "BACCARAT" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "BACCARAT" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "BACCARAT" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "BACCARAT" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "BACCARAT" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "BACCARAT" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "BACCARAT" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "BACCARAT" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "BACCARAT" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "BACCARAT" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "BACCARAT" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "BACCARAT" } } } }, - "BACK TO GAME": { - "comment": "A button label that takes the user back to the main game screen.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "BACK TO GAME" + "BACK TO GAME" : { + "comment" : "A button label that takes the user back to the main game screen.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "BACK TO GAME" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "VOLVER AL JUEGO" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "VOLVER AL JUEGO" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "VOLVER AL JUEGO" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "VOLVER AL JUEGO" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "VOLVER AL JUEGO" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "VOLVER AL JUEGO" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "RETOUR AU JEU" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "RETOUR AU JEU" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "RETOUR AU JEU" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "RETOUR AU JEU" } } } }, - "Balance": { - "comment": "A label describing the user's current balance.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Balance" + "Balance" : { + "comment" : "A label describing the user's current balance.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Balance" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Saldo" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Saldo" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Saldo" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Saldo" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Saldo" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Saldo" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Solde" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Solde" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Solde" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Solde" } } } }, - "BALANCE": { - "comment": "The label for the user's balance in the top bar.", - "extractionState": "stale", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "BALANCE" + "BALANCE" : { + "comment" : "The label for the user's balance in the top bar.", + "extractionState" : "stale", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "BALANCE" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "SALDO" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "SALDO" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "SALDO" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "SALDO" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "SALDO" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "SALDO" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "SOLDE" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "SOLDE" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "SOLDE" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "SOLDE" } } } }, - "Banker": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Banker" + "Banker" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Banker" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Banca" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Banca" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Banca" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Banca" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Banca" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Banca" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Banquier" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Banquier" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Banquier" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Banquier" } } } }, - "BANKER": { - "comment": "A label displayed above the banker's hand in the baccarat table view.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "BANKER" + "BANKER" : { + "comment" : "A label displayed above the banker's hand in the baccarat table view.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "BANKER" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "BANCA" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "BANCA" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "BANCA" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "BANCA" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "BANCA" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "BANCA" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "BANQUE" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "BANQUE" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "BANQUE" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "BANQUE" } } } }, - "Banker %@:": { - "comment": "A label displaying the total for the banker and an action to take based on that total. The first argument is the banker's total. The second argument is a string describing the action to take based on that total", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Banker %@:" + "Banker %@:" : { + "comment" : "A label displaying the total for the banker and an action to take based on that total. The first argument is the banker's total. The second argument is a string describing the action to take based on that total", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Banker %@:" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Banca %@:" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Banca %@:" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Banca %@:" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Banca %@:" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Banca %@:" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Banca %@:" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Banquier %@ :" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Banquier %@ :" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Banquier %@ :" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Banquier %@ :" } } } }, - "Banker hand": { - "comment": "A label displayed above the banker's hand.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Banker hand" + "Banker hand" : { + "comment" : "A label displayed above the banker's hand.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Banker hand" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Mano de la banca" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mano de la banca" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Mano de la banca" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mano de la banca" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Mano de la banca" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mano de la banca" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Main du banquier" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Main du banquier" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Main du banquier" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Main du banquier" } } } }, - "Banker Rules": { - "comment": "A section header for the banker's rules in the third card rules content.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Banker Rules" + "Banker Rules" : { + "comment" : "A section header for the banker's rules in the third card rules content.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Banker Rules" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Reglas de la banca" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reglas de la banca" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Reglas de la banca" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reglas de la banca" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Reglas de la banca" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reglas de la banca" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Règles du banquier" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Règles du banquier" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Règles du banquier" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Règles du banquier" } } } }, - "BANKER WINS": { - "comment": "Result banner text when banker wins.", - "extractionState": "stale", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "BANKER WINS" + "BANKER WINS" : { + "comment" : "Result banner text when banker wins.", + "extractionState" : "stale", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "BANKER WINS" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "GANA BANCA" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "GANA BANCA" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "GANA BANCA" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "GANA BANCA" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "GANA BANCA" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "GANA BANCA" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "BANQUE GAGNE" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "BANQUE GAGNE" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "BANQUE GAGNE" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "BANQUE GAGNE" } } } }, - "BONUS": { - "comment": "The text displayed in the center of the bonus zone.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "BONUS" + "Blackjack" : { + "comment" : "The name of a blackjack game.", + "isCommentAutoGenerated" : true + }, + "BONUS" : { + "comment" : "The text displayed in the center of the bonus zone.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "BONUS" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "BONO" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "BONO" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "BONO" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "BONO" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "BONO" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "BONO" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "BONUS" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "BONUS" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "BONUS" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "BONUS" } } } }, - "Cancel": { - "comment": "The label of a button to cancel making changes in the settings.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Cancel" + "Cancel" : { + "comment" : "The label of a button to cancel making changes in the settings.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cancel" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Cancelar" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cancelar" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Cancelar" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cancelar" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Cancelar" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cancelar" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Annuler" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Annuler" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Annuler" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Annuler" } } } }, - "Card Values": { - "comment": "A heading that explains the values of playing cards.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Card Values" + "Card Values" : { + "comment" : "A heading that explains the values of playing cards.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Card Values" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Valores de cartas" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Valores de cartas" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Valores de cartas" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Valores de cartas" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Valores de cartas" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Valores de cartas" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Valeurs des cartes" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Valeurs des cartes" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Valeurs des cartes" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Valeurs des cartes" } } } }, - "Cards face down": { - "comment": "Voiceover description of the player's hand when no cards are visible.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Cards face down" + "Cards face down" : { + "comment" : "Voiceover description of the player's hand when no cards are visible.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cards face down" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Cartas boca abajo" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cartas boca abajo" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Cartas boca abajo" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cartas boca abajo" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Cartas boca abajo" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cartas boca abajo" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Cartes face cachée" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cartes face cachée" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Cartes face cachée" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cartes face cachée" } } } }, - "Cards remaining in shoe": { - "comment": "A label describing the number of cards remaining in the shoe.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Cards remaining in shoe" + "Cards remaining in shoe" : { + "comment" : "A label describing the number of cards remaining in the shoe.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cards remaining in shoe" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Cartas restantes" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cartas restantes" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Cartas restantes" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cartas restantes" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Cartas restantes" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cartas restantes" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Cartes restantes" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cartes restantes" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Cartes restantes" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cartes restantes" } } } }, - "Clear": { - "comment": "The label of a button that clears all current bets in the game.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Clear" + "Clear" : { + "comment" : "The label of a button that clears all current bets in the game.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Clear" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Borrar" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Borrar" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Borrar" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Borrar" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Borrar" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Borrar" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Effacer" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Effacer" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Effacer" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Effacer" } } } }, - "Deal": { - "comment": "The label of a button that deals cards in a game.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Deal" + "Deal" : { + "comment" : "The label of a button that deals cards in a game.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Deal" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Repartir" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Repartir" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Repartir" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Repartir" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Repartir" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Repartir" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Distribuer" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Distribuer" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Distribuer" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Distribuer" } } } }, - "Dealing Speed": { - "comment": "A label describing the speed at which cards are dealt in the game.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Dealing Speed" + "Dealing Speed" : { + "comment" : "A label describing the speed at which cards are dealt in the game.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dealing Speed" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Velocidad de reparto" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Velocidad de reparto" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Velocidad de reparto" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Velocidad de reparto" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Velocidad de reparto" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Velocidad de reparto" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Vitesse de distribution" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vitesse de distribution" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Vitesse de distribution" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vitesse de distribution" } } } }, - "Dealing...": { - "comment": "A placeholder text shown while a game is being dealt.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Dealing..." + "Dealing..." : { + "comment" : "A placeholder text shown while a game is being dealt.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dealing..." } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Repartiendo..." + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Repartiendo..." } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Repartiendo..." + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Repartiendo..." } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Repartiendo..." + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Repartiendo..." } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Distribution..." + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Distribution..." } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Distribution..." + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Distribution..." } } } }, - "Done": { - "comment": "The text for a button that confirms and saves settings.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Done" + "Done" : { + "comment" : "The text for a button that confirms and saves settings.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Done" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Listo" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Listo" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Listo" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Listo" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Listo" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Listo" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Terminé" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Terminé" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Terminé" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Terminé" } } } }, - "Dragon Bonus": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Dragon Bonus" + "Dragon Bonus" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dragon Bonus" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Bono Dragón" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bono Dragón" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Bono Dragón" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bono Dragón" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Bono Dragón" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bono Dragón" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Bonus Dragon" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bonus Dragon" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Bonus Dragon" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bonus Dragon" } } } }, - "Examples": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Examples" + "Examples" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Examples" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Ejemplos" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ejemplos" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Ejemplos" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ejemplos" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Ejemplos" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ejemplos" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Exemples" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exemples" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Exemples" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exemples" } } } }, - "Game history": { - "comment": "The accessibility label for the road map view, describing it as a display of game results.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Game history" + "Game history" : { + "comment" : "The accessibility label for the road map view, describing it as a display of game results.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Game history" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Historial" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Historial" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Historial" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Historial" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Historial" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Historial" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Historique" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Historique" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Historique" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Historique" } } } }, - "Game Over": { - "comment": "The title of the game over screen.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Game Over" + "Game Over" : { + "comment" : "The title of the game over screen.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Game Over" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Fin del juego" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fin del juego" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Fin del juego" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fin del juego" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Fin del juego" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fin del juego" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Partie terminée" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Partie terminée" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Partie terminée" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Partie terminée" } } } }, - "GAME OVER": { - "comment": "The title of the game over screen.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "GAME OVER" + "GAME OVER" : { + "comment" : "The title of the game over screen.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "GAME OVER" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "FIN DEL JUEGO" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "FIN DEL JUEGO" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "FIN DEL JUEGO" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "FIN DEL JUEGO" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "FIN DEL JUEGO" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "FIN DEL JUEGO" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "FIN DE PARTIE" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "FIN DE PARTIE" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "FIN DE PARTIE" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "FIN DE PARTIE" } } } }, - "handValueFormat": { - "comment": "A description of the player's hand, including the visible cards and their total value.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%@ of %@. Value: %lld" + "Generate & Save Icons" : { + "comment" : "A button label that triggers the generation of app icons.", + "isCommentAutoGenerated" : true + }, + "Generated Icons:" : { + "comment" : "A label displayed above the list of generated icon filenames.", + "isCommentAutoGenerated" : true + }, + "Generating..." : { + "comment" : "A text that appears while generating icons.", + "isCommentAutoGenerated" : true + }, + "handValueFormat" : { + "comment" : "Format for displaying hand value. The argument is the numeric value of the hand.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Value: %lld" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "%@ de %@. Valor: %lld" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Valor: %lld" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "%@ de %@. Valor: %lld" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Valor: %lld" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "%@ de %@. Valor: %lld" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Valor: %lld" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "%@ de %@. Valeur : %lld" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Valeur : %lld" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "%@ de %@. Valeur : %lld" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Valeur : %lld" } } } }, - "Help": { - "comment": "The label of a button that shows help information.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Help" + "Help" : { + "comment" : "The label of a button that shows help information.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Help" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Ayuda" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ayuda" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Ayuda" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ayuda" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Ayuda" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ayuda" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Aide" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aide" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Aide" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aide" } } } }, - "HISTORY": { - "comment": "A label displayed above the road map view, indicating that it shows a history of past game results.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "HISTORY" + "HISTORY" : { + "comment" : "A label displayed above the road map view, indicating that it shows a history of past game results.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "HISTORY" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "HISTORIAL" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "HISTORIAL" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "HISTORIAL" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "HISTORIAL" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "HISTORIAL" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "HISTORIAL" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "HISTORIQUE" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "HISTORIQUE" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "HISTORIQUE" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "HISTORIQUE" } } } }, - "historySummaryFormat": { - "comment": "Format string used to create a summary of the user's game history, including the total number of rounds played, as well as the number of rounds won by the player, the banker, and as ties.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%lld rounds: %lld player, %lld banker, %lld ties" + "historySummaryFormat" : { + "comment" : "Format string used to create a summary of the user's game history, including the total number of rounds played, as well as the number of rounds won by the player, the banker, and as ties.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld rounds: %lld player, %lld banker, %lld ties" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "%lld rondas: %lld jugador, %lld banca, %lld empates" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld rondas: %lld jugador, %lld banca, %lld empates" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "%lld rondas: %lld jugador, %lld banca, %lld empates" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld rondas: %lld jugador, %lld banca, %lld empates" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "%lld rondas: %lld jugador, %lld banca, %lld empates" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld rondas: %lld jugador, %lld banca, %lld empates" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "%lld parties : %lld joueur, %lld banquier, %lld égalités" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld parties : %lld joueur, %lld banquier, %lld égalités" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "%lld parties : %lld joueur, %lld banquier, %lld égalités" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld parties : %lld joueur, %lld banquier, %lld égalités" } } } }, - "How to Play": { - "comment": "Title for the first rule page in the help view.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "How to Play" + "How to Export Icons" : { + "comment" : "A section header explaining how to export app icons.", + "isCommentAutoGenerated" : true + }, + "How to Play" : { + "comment" : "Title for the first rule page in the help view.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "How to Play" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Cómo jugar" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cómo jugar" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Cómo jugar" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cómo jugar" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Cómo jugar" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cómo jugar" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Comment jouer" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Comment jouer" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Comment jouer" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Comment jouer" } } } }, - "Important": { - "comment": "A heading for important information related to a section of a view.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Important" + "Icon" : { + "comment" : "The title for the tab that displays the app icon preview.", + "isCommentAutoGenerated" : true + }, + "Icon Generator" : { + "comment" : "The title of the Icon Generator view.", + "isCommentAutoGenerated" : true + }, + "Important" : { + "comment" : "A heading for important information related to a section of a view.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Important" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Importante" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Importante" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Importante" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Importante" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Importante" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Importante" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Important" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Important" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Important" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Important" } } } }, - "MAX": { - "comment": "A label displayed as a badge on top-right of a chip to indicate it's the maximum bet.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "MAX" + "Launch" : { + "comment" : "A tab label for the launch screen preview.", + "isCommentAutoGenerated" : true + }, + "MAX" : { + "comment" : "A label displayed as a badge on top-right of a chip to indicate it's the maximum bet.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "MAX" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "MÁX" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "MÁX" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "MÁX" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "MÁX" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "MÁX" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "MÁX" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "MAX" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "MAX" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "MAX" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "MAX" } } } }, - "Natural Win": { - "comment": "A section header for information about winning with a natural hand.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Natural Win" + "Natural Win" : { + "comment" : "A section header for information about winning with a natural hand.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Natural Win" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Natural" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Natural" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Natural" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Natural" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Natural" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Natural" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Main naturelle" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Main naturelle" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Main naturelle" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Main naturelle" } } } }, - "Naturals": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Naturals" + "Naturals" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Naturals" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Naturales" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Naturales" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Naturales" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Naturales" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Naturales" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Naturales" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Naturels" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Naturels" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Naturels" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Naturels" } } } }, - "New Round": { - "comment": "The label of a button that starts a new round of the game.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "New Round" + "New Round" : { + "comment" : "The label of a button that starts a new round of the game.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "New Round" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Nueva ronda" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nueva ronda" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Nueva ronda" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nueva ronda" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Nueva ronda" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nueva ronda" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Nouvelle manche" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nouvelle manche" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Nouvelle manche" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nouvelle manche" } } } }, - "No cards": { - "comment": "A description of the player's hand when they have no cards.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No cards" + "No cards" : { + "comment" : "A description of the player's hand when they have no cards.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No cards" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Sin cartas" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sin cartas" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Sin cartas" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sin cartas" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Sin cartas" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sin cartas" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Aucune carte" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aucune carte" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Aucune carte" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aucune carte" } } } }, - "No history yet": { - "comment": "Summary text for a road map view when there is no history.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No history yet" + "No history yet" : { + "comment" : "Summary text for a road map view when there is no history.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No history yet" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Sin historial" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sin historial" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Sin historial" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sin historial" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Sin historial" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sin historial" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Pas d'historique" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pas d'historique" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Pas d'historique" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pas d'historique" } } } }, - "No rounds played yet": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No rounds played yet" + "No rounds played yet" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No rounds played yet" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Aún no hay rondas jugadas" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aún no hay rondas jugadas" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Aún no hay rondas jugadas" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aún no hay rondas jugadas" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Aún no hay rondas jugadas" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aún no hay rondas jugadas" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Aucune partie jouée" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aucune partie jouée" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Aucune partie jouée" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aucune partie jouée" } } } }, - "P Pair": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "P Pair" + "Option 1: Screenshot from Preview" : { + "comment" : "A description of one method for exporting app icons.", + "isCommentAutoGenerated" : true + }, + "Option 2: Use IconRenderer in Code" : { + "comment" : "A description of how to use the `IconRenderer` in code to generate app icons.", + "isCommentAutoGenerated" : true + }, + "Other Game Icons" : { + "comment" : "A label displayed above a section of the BrandingPreviewView", + "isCommentAutoGenerated" : true + }, + "Others" : { + "comment" : "The tab label for the section that previews branding assets for other games.", + "isCommentAutoGenerated" : true + }, + "P Pair" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "P Pair" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Par J" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Par J" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Par J" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Par J" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Par J" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Par J" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Paire J" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Paire J" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Paire J" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Paire J" } } } }, - "Pair Bonus": { - "comment": "Title of the page explaining the pair bonus in Baccarat.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Pair Bonus" + "Pair Bonus" : { + "comment" : "Title of the page explaining the pair bonus in Baccarat.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pair Bonus" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Bono de par" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bono de par" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Bono de par" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bono de par" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Bono de par" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bono de par" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Bonus paire" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bonus paire" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Bonus paire" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bonus paire" } } } }, - "Pair Pays": { - "comment": "The text that appears above the payout value for a pair bonus bet.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Pair Pays" + "Pair Pays" : { + "comment" : "The text that appears above the payout value for a pair bonus bet.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pair Pays" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Par paga" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Par paga" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Par paga" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Par paga" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Par paga" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Par paga" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Paire paie" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Paire paie" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Paire paie" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Paire paie" } } } }, - "Payout": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Payout" + "Payout" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Payout" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Pago" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pago" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Pago" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pago" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Pago" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pago" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Paiement" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Paiement" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Paiement" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Paiement" } } } }, - "Payout Table": { - "comment": "The title of a table that lists possible payouts for a dragon bonus bet.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Payout Table" + "Payout Table" : { + "comment" : "The title of a table that lists possible payouts for a dragon bonus bet.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Payout Table" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Tabla de pagos" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tabla de pagos" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Tabla de pagos" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tabla de pagos" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Tabla de pagos" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tabla de pagos" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Table des gains" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Table des gains" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Table des gains" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Table des gains" } } } }, - "PAYS 0.95 TO 1": { - "comment": "A description of the payout for betting on the banker in a mini baccarat table.", - "extractionState": "stale", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "PAYS 0.95 TO 1" + "PAYS 0.95 TO 1" : { + "comment" : "A description of the payout for betting on the banker in a mini baccarat table.", + "extractionState" : "stale", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAYS 0.95 TO 1" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "PAGA 0,95 A 1" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAGA 0,95 A 1" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "PAGA 0.95 A 1" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAGA 0.95 A 1" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "PAGA 0.95 A 1" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAGA 0.95 A 1" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "PAIE 0,95 POUR 1" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAIE 0,95 POUR 1" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "PAIE 0,95 POUR 1" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAIE 0,95 POUR 1" } } } }, - "PAYS 1 TO 1": { - "comment": "A description of the payout ratio for the player bet.", - "extractionState": "stale", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "PAYS 1 TO 1" + "PAYS 1 TO 1" : { + "comment" : "A description of the payout ratio for the player bet.", + "extractionState" : "stale", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAYS 1 TO 1" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "PAGA 1 A 1" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAGA 1 A 1" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "PAGA 1 A 1" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAGA 1 A 1" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "PAGA 1 A 1" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAGA 1 A 1" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "PAIE 1 POUR 1" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAIE 1 POUR 1" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "PAIE 1 POUR 1" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAIE 1 POUR 1" } } } }, - "PAYS 8 TO 1": { - "comment": "A description of the payout for betting on a tie in mini baccarat.", - "extractionState": "stale", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "PAYS 8 TO 1" + "PAYS 8 TO 1" : { + "comment" : "A description of the payout for betting on a tie in mini baccarat.", + "extractionState" : "stale", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAYS 8 TO 1" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "PAGA 8 A 1" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAGA 8 A 1" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "PAGA 8 A 1" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAGA 8 A 1" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "PAGA 8 A 1" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAGA 8 A 1" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "PAIE 8 POUR 1" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAIE 8 POUR 1" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "PAIE 8 POUR 1" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAIE 8 POUR 1" } } } }, - "Play Again": { - "comment": "A button label that says \"Play Again\".", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Play Again" + "Play Again" : { + "comment" : "A button label that says \"Play Again\".", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Play Again" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Jugar de nuevo" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Jugar de nuevo" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Jugar de nuevo" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Jugar de nuevo" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Jugar de nuevo" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Jugar de nuevo" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Rejouer" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rejouer" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Rejouer" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rejouer" } } } }, - "Player": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Player" + "Player" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Player" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Jugador" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Jugador" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Jugador" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Jugador" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Jugador" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Jugador" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Joueur" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Joueur" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Joueur" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Joueur" } } } }, - "PLAYER": { - "comment": "The label for the player's hand in the cards display area.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "PLAYER" + "PLAYER" : { + "comment" : "The label for the player's hand in the cards display area.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "PLAYER" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "JUGADOR" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "JUGADOR" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "JUGADOR" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "JUGADOR" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "JUGADOR" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "JUGADOR" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "JOUEUR" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "JOUEUR" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "JOUEUR" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "JOUEUR" } } } }, - "Player hand": { - "comment": "An accessibility label for the player's hand in the cards display area.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Player hand" + "Player hand" : { + "comment" : "An accessibility label for the player's hand in the cards display area.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Player hand" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Mano del jugador" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mano del jugador" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Mano del jugador" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mano del jugador" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Mano del jugador" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mano del jugador" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Main du joueur" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Main du joueur" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Main du joueur" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Main du joueur" } } } }, - "Player Rules": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Player Rules" + "Player Rules" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Player Rules" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Reglas del jugador" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reglas del jugador" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Reglas del jugador" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reglas del jugador" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Reglas del jugador" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reglas del jugador" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Règles du joueur" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Règles du joueur" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Règles du joueur" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Règles du joueur" } } } }, - "PLAYER WINS": { - "comment": "Result banner text when player wins.", - "extractionState": "stale", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "PLAYER WINS" + "PLAYER WINS" : { + "comment" : "Result banner text when player wins.", + "extractionState" : "stale", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "PLAYER WINS" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "GANA JUGADOR" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "GANA JUGADOR" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "GANA JUGADOR" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "GANA JUGADOR" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "GANA JUGADOR" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "GANA JUGADOR" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "JOUEUR GAGNE" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "JOUEUR GAGNE" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "JOUEUR GAGNE" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "JOUEUR GAGNE" } } } }, - "Reset": { - "comment": "A button that resets the game to its initial state.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Reset" + "Poker" : { + "comment" : "The name of a poker game.", + "isCommentAutoGenerated" : true + }, + "Reset" : { + "comment" : "A button that resets the game to its initial state.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reset" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Reiniciar" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reiniciar" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Reiniciar" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reiniciar" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Reiniciar" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reiniciar" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Réinitialiser" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Réinitialiser" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Réinitialiser" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Réinitialiser" } } } }, - "Reset to Defaults": { - "comment": "A button label that resets game settings to their default values.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Reset to Defaults" + "Reset to Defaults" : { + "comment" : "A button label that resets game settings to their default values.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reset to Defaults" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Restaurar valores predeterminados" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Restaurar valores predeterminados" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Restaurar valores predeterminados" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Restaurar valores predeterminados" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Restaurar valores predeterminados" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Restaurar valores predeterminados" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Réinitialiser par défaut" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Réinitialiser par défaut" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Réinitialiser par défaut" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Réinitialiser par défaut" } } } }, - "Rounds": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Rounds" + "Roulette" : { + "comment" : "The name of a roulette game.", + "isCommentAutoGenerated" : true + }, + "Rounds" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rounds" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Rondas" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rondas" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Rondas" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rondas" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Rondas" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rondas" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Parties" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Parties" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Parties" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Parties" } } } }, - "Rounds Played": { - "comment": "A label displayed next to the number of rounds played in the game over screen.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Rounds Played" + "Rounds Played" : { + "comment" : "A label displayed next to the number of rounds played in the game over screen.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rounds Played" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Rondas jugadas" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rondas jugadas" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Rondas jugadas" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rondas jugadas" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Rondas jugadas" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rondas jugadas" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Manches jouées" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Manches jouées" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Manches jouées" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Manches jouées" } } } }, - "Settings": { - "comment": "The label of a button that navigates to the settings screen.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Settings" + "Settings" : { + "comment" : "The label of a button that navigates to the settings screen.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Settings" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Configuración" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Configuración" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Configuración" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Configuración" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Configuración" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Configuración" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Paramètres" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Paramètres" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Paramètres" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Paramètres" } } } }, - "Statistics": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Statistics" + "Statistics" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Statistics" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Estadísticas" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Estadísticas" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Estadísticas" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Estadísticas" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Estadísticas" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Estadísticas" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Statistiques" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Statistiques" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Statistiques" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Statistiques" } } } }, - "tableLimitsFormat": { - "comment": "Format string for table limits display. First argument is min bet, second is max bet.", - "extractionState": "stale", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "TABLE LIMITS: $%@ - $%@" + "tableLimitsFormat" : { + "comment" : "Format string for table limits display. First argument is min bet, second is max bet.", + "extractionState" : "stale", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "TABLE LIMITS: $%@ - $%@" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "LÍMITES: $%@ - $%@" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "LÍMITES: $%@ - $%@" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "LÍMITES: $%@ - $%@" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "LÍMITES: $%@ - $%@" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "LÍMITES: $%@ - $%@" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "LÍMITES: $%@ - $%@" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "LIMITES: %@ € - %@ €" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "LIMITES: %@ € - %@ €" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "LIMITES: %@ $ - %@ $" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "LIMITES: %@ $ - %@ $" } } } }, - "Third Card Rules": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Third Card Rules" + "These show how the same pattern works for other games" : { + "comment" : "A description below the section of the view that previews icons for other games.", + "isCommentAutoGenerated" : true + }, + "Third Card Rules" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Third Card Rules" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Reglas de tercera carta" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reglas de tercera carta" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Reglas de tercera carta" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reglas de tercera carta" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Reglas de tercera carta" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reglas de tercera carta" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Règles de la 3e carte" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Règles de la 3e carte" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Règles de la 3e carte" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Règles de la 3e carte" } } } }, - "Tie": { - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Tie" + "Tie" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tie" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Empate" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Empate" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Empate" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Empate" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Empate" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Empate" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Égalité" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Égalité" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Égalité" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Égalité" } } } }, - "TIE": { - "comment": "The text displayed in the TIE betting zone.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "TIE" + "TIE" : { + "comment" : "The text displayed in the TIE betting zone.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "TIE" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "EMPATE" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "EMPATE" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "EMPATE" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "EMPATE" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "EMPATE" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "EMPATE" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "ÉGALITÉ" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "ÉGALITÉ" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "ÉGALITÉ" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "ÉGALITÉ" } } } }, - "TIE GAME": { - "comment": "Result banner text when the game is a tie.", - "extractionState": "stale", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "TIE GAME" + "TIE GAME" : { + "comment" : "Result banner text when the game is a tie.", + "extractionState" : "stale", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "TIE GAME" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "EMPATE" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "EMPATE" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "EMPATE" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "EMPATE" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "EMPATE" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "EMPATE" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "ÉGALITÉ" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "ÉGALITÉ" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "ÉGALITÉ" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "ÉGALITÉ" } } } }, - "Tips": { - "comment": "A section header for tips related to pair bonuses.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Tips" + "Tips" : { + "comment" : "A section header for tips related to pair bonuses.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tips" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Consejos" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Consejos" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Consejos" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Consejos" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Consejos" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Consejos" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Conseils" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Conseils" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Conseils" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Conseils" } } } }, - "TOTAL": { - "comment": "A label displayed next to the total winnings in the result banner.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "TOTAL" + "TOTAL" : { + "comment" : "A label displayed next to the total winnings in the result banner.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "TOTAL" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "TOTAL" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "TOTAL" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "TOTAL" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "TOTAL" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "TOTAL" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "TOTAL" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "TOTAL" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "TOTAL" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "TOTAL" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "TOTAL" } } } }, - "View detailed game statistics": { - "comment": "A hint that appears when hovering over the \"Statistics\" button, explaining its function.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "View detailed game statistics" + "Upload the 1024px icon to appicon.co or makeappicon.com to generate all sizes automatically." : { + "comment" : "A description of an alternative method for generating app icons.", + "isCommentAutoGenerated" : true + }, + "View detailed game statistics" : { + "comment" : "A hint that appears when hovering over the \"Statistics\" button, explaining its function.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "View detailed game statistics" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Ver estadísticas detalladas" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ver estadísticas detalladas" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Ver estadísticas detalladas" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ver estadísticas detalladas" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Ver estadísticas detalladas" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ver estadísticas detalladas" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Voir les statistiques" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Voir les statistiques" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Voir les statistiques" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Voir les statistiques" } } } }, - "WIN": { - "comment": "The text that appears as a badge when a player wins a hand in baccarat.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "WIN" + "WIN" : { + "comment" : "The text that appears as a badge when a player wins a hand in baccarat.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "WIN" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "GANA" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "GANA" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "GANA" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "GANA" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "GANA" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "GANA" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "GAGNÉ" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "GAGNÉ" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "GAGNÉ" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "GAGNÉ" } } } }, - "Winner": { - "comment": "A description of the player's hand, including its value and whether they won.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Winner" + "Winner" : { + "comment" : "A description of the player's hand, including its value and whether they won.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Winner" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "Ganador" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ganador" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "Ganador" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ganador" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "Ganador" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ganador" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Gagnant" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gagnant" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Gagnant" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gagnant" } } } }, - "You've run out of chips!": { - "comment": "A message displayed when a player runs out of money in the game over screen.", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "You've run out of chips!" + "You've run out of chips!" : { + "comment" : "A message displayed when a player runs out of money in the game over screen.", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "You've run out of chips!" } }, - "es": { - "stringUnit": { - "state": "translated", - "value": "¡Te quedaste sin fichas!" + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "¡Te quedaste sin fichas!" } }, - "es-MX": { - "stringUnit": { - "state": "translated", - "value": "¡Te quedaste sin fichas!" + "es-MX" : { + "stringUnit" : { + "state" : "translated", + "value" : "¡Te quedaste sin fichas!" } }, - "es-US": { - "stringUnit": { - "state": "translated", - "value": "¡Te quedaste sin fichas!" + "es-US" : { + "stringUnit" : { + "state" : "translated", + "value" : "¡Te quedaste sin fichas!" } }, - "fr": { - "stringUnit": { - "state": "translated", - "value": "Vous n'avez plus de jetons!" + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vous n'avez plus de jetons!" } }, - "fr-CA": { - "stringUnit": { - "state": "translated", - "value": "Vous n'avez plus de jetons!" + "fr-CA" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vous n'avez plus de jetons!" } } } } }, - "version": "1.1" + "version" : "1.1" } \ No newline at end of file diff --git a/Baccarat/Views/BrandingPreviewView.swift b/Baccarat/Views/BrandingPreviewView.swift new file mode 100644 index 0000000..94e6bee --- /dev/null +++ b/Baccarat/Views/BrandingPreviewView.swift @@ -0,0 +1,130 @@ +// +// BrandingPreviewView.swift +// Baccarat +// +// Development view for previewing and exporting app icons and launch screens. +// Access this during development to generate icon assets. +// + +import SwiftUI +import CasinoKit + +/// Preview view for app branding assets. +/// Use this during development to preview and export icons. +struct BrandingPreviewView: View { + var body: some View { + TabView { + // App Icon Preview + ScrollView { + VStack(spacing: 32) { + Text("App Icon") + .font(.largeTitle.bold()) + + AppIconView(config: .baccarat, size: 300) + .clipShape(.rect(cornerRadius: 300 * 0.22)) + .shadow(radius: 20) + + Text("All Sizes") + .font(.title2.bold()) + + LazyVGrid(columns: [GridItem(.adaptive(minimum: 100))], spacing: 20) { + ForEach([180, 120, 87, 60, 40], id: \.self) { size in + VStack { + AppIconView(config: .baccarat, size: CGFloat(size)) + .clipShape(.rect(cornerRadius: CGFloat(size) * 0.22)) + Text("\(size)px") + .font(.caption) + .foregroundStyle(.secondary) + } + } + } + + instructionsSection + } + .padding() + } + .tabItem { + Label("Icon", systemImage: "app.fill") + } + + // Launch Screen Preview + LaunchScreenView(config: .baccarat) + .tabItem { + Label("Launch", systemImage: "rectangle.portrait.fill") + } + + // Other Games Preview + ScrollView { + VStack(spacing: 32) { + Text("Other Game Icons") + .font(.largeTitle.bold()) + + HStack(spacing: 20) { + VStack { + AppIconView(config: .blackjack, size: 150) + .clipShape(.rect(cornerRadius: 150 * 0.22)) + Text("Blackjack") + .font(.caption) + } + + VStack { + AppIconView(config: .poker, size: 150) + .clipShape(.rect(cornerRadius: 150 * 0.22)) + Text("Poker") + .font(.caption) + } + + VStack { + AppIconView(config: .roulette, size: 150) + .clipShape(.rect(cornerRadius: 150 * 0.22)) + Text("Roulette") + .font(.caption) + } + } + + Text("These show how the same pattern works for other games") + .font(.callout) + .foregroundStyle(.secondary) + } + .padding() + } + .tabItem { + Label("Others", systemImage: "square.grid.2x2") + } + } + } + + private var instructionsSection: some View { + VStack(alignment: .leading, spacing: 12) { + Text("How to Export Icons") + .font(.headline) + + VStack(alignment: .leading, spacing: 8) { + Text("Option 1: Screenshot from Preview") + .font(.subheadline.bold()) + Text("• Run the preview in Xcode") + Text("• Screenshot the 1024px icon") + Text("• Use an online tool to generate all sizes") + } + + VStack(alignment: .leading, spacing: 8) { + Text("Option 2: Use IconRenderer in Code") + .font(.subheadline.bold()) + Text("• Call IconRenderer.renderAppIcon(config: .baccarat)") + Text("• Save the resulting UIImage to files") + Text("• Add to Assets.xcassets/AppIcon") + } + } + .font(.callout) + .foregroundStyle(.secondary) + .frame(maxWidth: .infinity, alignment: .leading) + .padding() + .background(Color.gray.opacity(0.1)) + .clipShape(.rect(cornerRadius: 12)) + } +} + +#Preview { + BrandingPreviewView() +} + diff --git a/Baccarat/Views/IconGeneratorView.swift b/Baccarat/Views/IconGeneratorView.swift new file mode 100644 index 0000000..a76c889 --- /dev/null +++ b/Baccarat/Views/IconGeneratorView.swift @@ -0,0 +1,192 @@ +// +// IconGeneratorView.swift +// Baccarat +// +// Development tool to generate and export app icon images. +// Run this view, tap the button, then find the icons in the Files app. +// + +import SwiftUI +import CasinoKit + +/// A development view that generates and saves app icon images. +/// After running, find the icons in Files app → On My iPhone → Baccarat +struct IconGeneratorView: View { + @State private var status: String = "Tap the button to generate icons" + @State private var isGenerating = false + @State private var generatedIcons: [GeneratedIcon] = [] + + var body: some View { + NavigationStack { + ScrollView { + VStack(spacing: 24) { + // Preview + AppIconView(config: .baccarat, size: 200) + .clipShape(.rect(cornerRadius: 200 * 0.22)) + .shadow(radius: 10) + + Text("App Icon Preview") + .font(.headline) + + // Generate button + Button { + Task { + await generateIcons() + } + } label: { + HStack { + if isGenerating { + ProgressView() + .tint(.white) + } + Text(isGenerating ? "Generating..." : "Generate & Save Icons") + } + .font(.headline) + .foregroundStyle(.white) + .frame(maxWidth: .infinity) + .padding() + .background(isGenerating ? Color.gray : Color.blue) + .clipShape(.rect(cornerRadius: 12)) + } + .disabled(isGenerating) + .padding(.horizontal) + + // Status + Text(status) + .font(.callout) + .foregroundStyle(.secondary) + .multilineTextAlignment(.center) + .padding(.horizontal) + + // Generated icons + if !generatedIcons.isEmpty { + VStack(alignment: .leading, spacing: 12) { + Text("Generated Icons:") + .font(.headline) + + ForEach(generatedIcons) { icon in + HStack { + Image(systemName: "checkmark.circle.fill") + .foregroundStyle(.green) + Text(icon.filename) + .font(.caption.monospaced()) + Spacer() + Text("\(Int(icon.size))px") + .font(.caption) + .foregroundStyle(.secondary) + } + } + } + .padding() + .background(Color.green.opacity(0.1)) + .clipShape(.rect(cornerRadius: 12)) + .padding(.horizontal) + } + + // Instructions + instructionsSection + } + .padding(.vertical) + } + .navigationTitle("Icon Generator") + } + } + + private var instructionsSection: some View { + VStack(alignment: .leading, spacing: 12) { + Text("After generating:") + .font(.headline) + + VStack(alignment: .leading, spacing: 8) { + instructionRow(number: 1, text: "Open Files app on your device/simulator") + instructionRow(number: 2, text: "Navigate to: On My iPhone → Baccarat") + instructionRow(number: 3, text: "Find the AppIcon-1024.png file") + instructionRow(number: 4, text: "AirDrop or share to your Mac") + instructionRow(number: 5, text: "Drag into Xcode's Assets.xcassets/AppIcon") + } + + Divider() + + Text("Alternative: Use an online tool") + .font(.subheadline.bold()) + Text("Upload the 1024px icon to appicon.co or makeappicon.com to generate all sizes automatically.") + .font(.caption) + .foregroundStyle(.secondary) + } + .padding() + .background(Color.gray.opacity(0.1)) + .clipShape(.rect(cornerRadius: 12)) + .padding(.horizontal) + } + + private func instructionRow(number: Int, text: String) -> some View { + HStack(alignment: .top, spacing: 8) { + Text("\(number).") + .font(.callout.bold()) + .foregroundStyle(.blue) + Text(text) + .font(.callout) + } + } + + @MainActor + private func generateIcons() async { + isGenerating = true + generatedIcons = [] + status = "Generating icons..." + + let sizes: [(CGFloat, String)] = [ + (1024, "AppIcon-1024"), + (180, "AppIcon-180"), + (120, "AppIcon-120"), + (87, "AppIcon-87"), + (80, "AppIcon-80"), + (60, "AppIcon-60"), + (40, "AppIcon-40") + ] + + let documentsPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] + + for (size, name) in sizes { + // Render the icon + let view = AppIconView(config: .baccarat, size: size) + let renderer = ImageRenderer(content: view) + renderer.scale = 1.0 + + if let uiImage = renderer.uiImage, + let data = uiImage.pngData() { + let filename = "\(name).png" + let fileURL = documentsPath.appending(path: filename) + + do { + try data.write(to: fileURL) + generatedIcons.append(GeneratedIcon(filename: filename, size: size)) + } catch { + status = "Error saving \(filename): \(error.localizedDescription)" + } + } + + // Small delay for UI feedback + try? await Task.sleep(for: .milliseconds(100)) + } + + if generatedIcons.count == sizes.count { + status = "✅ All icons saved to Documents folder!\nOpen Files app to find them." + } else { + status = "⚠️ Some icons failed to generate" + } + + isGenerating = false + } +} + +struct GeneratedIcon: Identifiable { + let id = UUID() + let filename: String + let size: CGFloat +} + +#Preview { + IconGeneratorView() +} + diff --git a/CasinoKit/README.md b/CasinoKit/README.md new file mode 100644 index 0000000..b921c26 --- /dev/null +++ b/CasinoKit/README.md @@ -0,0 +1,378 @@ +# CasinoKit + +A reusable Swift Package for building casino card games with SwiftUI. This package provides common components, themes, and utilities shared across casino game apps. + +## Requirements + +- iOS 17.0+ +- Swift 6.0+ +- Xcode 16.0+ + +## Installation + +This package is included as a local package in the workspace. To use in another project: + +1. Copy the `CasinoKit` folder to your project +2. In Xcode: File → Add Package Dependencies → Add Local +3. Select the `CasinoKit` folder + +## Features + +### 🎴 Cards + +**CardView** - A playing card with flip animation support. + +```swift +import CasinoKit + +// Face-up card +CardView(card: Card(suit: .hearts, rank: .ace), faceUp: true) + +// Face-down card +CardView(card: card, faceUp: false) + +// Empty placeholder (dotted outline) +CardPlaceholderView() +``` + +**Card Model** +```swift +let card = Card(suit: .spades, rank: .king) +print(card.displayValue) // "K" +print(card.suit.symbol) // "♠" +``` + +### 🎰 Chips + +**ChipView** - A casino chip with denomination display. + +```swift +ChipView(denomination: .hundred, size: 60, isSelected: true) +``` + +**ChipSelectorView** - Horizontal chip selector. + +```swift +@State var selectedChip: ChipDenomination = .hundred + +ChipSelectorView( + denominations: ChipDenomination.allCases, + selectedDenomination: $selectedChip +) +``` + +**ChipStackView** - Stacked chips showing bet amount. + +```swift +ChipStackView(amount: 500, chipColor: .red) +``` + +**Chip Denominations** +- `.one` (1) +- `.five` (5) +- `.twentyFive` (25) +- `.hundred` (100) +- `.fiveHundred` (500) +- `.thousand` (1000) + +### 📋 Sheets & Popups + +**SheetContainerView** - Consistent modal sheet styling. + +```swift +SheetContainerView( + title: "Settings", + content: { + SheetSection(title: "DISPLAY", icon: "eye") { + Toggle("Dark Mode", isOn: $darkMode) + } + + SheetSection(title: "SOUND", icon: "speaker.wave.2") { + Slider(value: $volume) + } + }, + onCancel: { dismiss() }, + onDone: { save(); dismiss() }, + doneButtonText: String(localized: "Done"), + cancelButtonText: String(localized: "Cancel") +) +``` + +**SheetSection** - Styled section within sheets. + +```swift +SheetSection(title: "SECTION TITLE", icon: "star.fill") { + // Your content +} +``` + +### 🎨 Branding & Icons + +**AppIconView** - Generate app icons with consistent styling. + +```swift +// Use a preset +AppIconView(config: .baccarat, size: 1024) + +// Custom configuration +let config = AppIconConfig( + title: "BLACKJACK", + subtitle: "21", + iconSymbol: "suit.club.fill", + primaryColor: Color(red: 0.1, green: 0.2, blue: 0.35), + secondaryColor: Color(red: 0.05, green: 0.12, blue: 0.25), + accentColor: .yellow +) +AppIconView(config: config, size: 1024) +``` + +**Preset Configurations:** +- `.baccarat` - Spade symbol +- `.blackjack` - Club symbol with "21" subtitle +- `.poker` - Diamond symbol, red accent +- `.roulette` - Grid symbol, red theme + +**LaunchScreenView** - Animated splash screen. + +```swift +LaunchScreenView(config: .baccarat) +``` + +**IconRenderer** - Render views to images. + +```swift +// Render single icon +let image = IconRenderer.renderAppIcon(config: .baccarat, size: 1024) + +// Render all iOS sizes +let allImages = IconRenderer.renderAllSizes(config: .baccarat) +``` + +### 🎨 Design System + +**CasinoDesign** - Shared design constants. + +```swift +// Spacing +CasinoDesign.Spacing.small // 8 +CasinoDesign.Spacing.medium // 12 +CasinoDesign.Spacing.large // 16 + +// Corner Radius +CasinoDesign.CornerRadius.small // 8 +CasinoDesign.CornerRadius.medium // 12 +CasinoDesign.CornerRadius.large // 16 + +// Font Sizes (base values for @ScaledMetric) +CasinoDesign.BaseFontSize.small // 12 +CasinoDesign.BaseFontSize.body // 14 +CasinoDesign.BaseFontSize.large // 20 + +// Opacity +CasinoDesign.Opacity.subtle // 0.05 +CasinoDesign.Opacity.light // 0.2 +CasinoDesign.Opacity.medium // 0.5 +CasinoDesign.Opacity.heavy // 0.8 + +// Animation +CasinoDesign.Animation.quick // 0.2 +CasinoDesign.Animation.standard // 0.3 +CasinoDesign.Animation.springDuration // 0.4 +``` + +**Color.Sheet** - Sheet/popup colors. + +```swift +Color.Sheet.background // Dark background +Color.Sheet.sectionFill // Section card fill +Color.Sheet.accent // Yellow accent +Color.Sheet.secondaryText // Muted text +Color.Sheet.cancelText // Cancel button text +``` + +### 🌍 Localization + +CasinoKit includes localization for: +- English (en) +- Spanish - Mexico (es-MX) +- French - Canada (fr-CA) + +**Localized Strings:** +- Card names (Ace, King, Queen, etc.) +- Suit names (Hearts, Diamonds, Clubs, Spades) +- Chip-related strings +- Accessibility labels + +**Adding Localizations:** + +The package uses String Catalogs (`.xcstrings`). Edit: +``` +CasinoKit/Sources/CasinoKit/Resources/Localizable.xcstrings +``` + +## Usage in a New Game + +### 1. Import the Package + +```swift +import SwiftUI +import CasinoKit +``` + +### 2. Create Your Game View + +```swift +struct BlackjackTableView: View { + @State private var deck = Deck(numberOfDecks: 6) + @State private var selectedChip: ChipDenomination = .hundred + + var body: some View { + VStack { + // Player's hand + HStack { + ForEach(playerCards) { card in + CardView(card: card, faceUp: true) + } + } + + // Chip selector + ChipSelectorView( + denominations: ChipDenomination.allCases, + selectedDenomination: $selectedChip + ) + } + } +} +``` + +### 3. Create Settings Sheet + +```swift +struct SettingsView: View { + @Environment(\.dismiss) var dismiss + + var body: some View { + SheetContainerView(title: "Settings") { + SheetSection(title: "GAME OPTIONS", icon: "gearshape") { + // Your settings + } + } onDone: { + dismiss() + } + } +} +``` + +### 4. Generate App Icon + +```swift +// In a preview or development view +#Preview { + let config = AppIconConfig( + title: "BLACKJACK", + subtitle: "21", + iconSymbol: "suit.club.fill" + ) + return AppIconView(config: config, size: 512) +} +``` + +Screenshot the preview and add to your Assets.xcassets. + +## File Structure + +``` +CasinoKit/ +├── Package.swift +├── README.md +├── Sources/CasinoKit/ +│ ├── CasinoKit.swift +│ ├── Exports.swift +│ ├── Models/ +│ │ ├── Card.swift +│ │ ├── Deck.swift +│ │ └── ChipDenomination.swift +│ ├── Views/ +│ │ ├── Cards/ +│ │ │ └── CardView.swift +│ │ ├── Chips/ +│ │ │ ├── ChipView.swift +│ │ │ ├── ChipSelectorView.swift +│ │ │ ├── ChipStackView.swift +│ │ │ └── ChipOnTableView.swift +│ │ ├── Sheets/ +│ │ │ └── SheetContainerView.swift +│ │ └── Branding/ +│ │ ├── AppIconView.swift +│ │ ├── LaunchScreenView.swift +│ │ └── IconRenderer.swift +│ ├── Theme/ +│ │ ├── CasinoTheme.swift +│ │ └── CasinoDesign.swift +│ └── Resources/ +│ └── Localizable.xcstrings +└── Tests/CasinoKitTests/ + └── CasinoKitTests.swift +``` + +## Best Practices + +### Design Constants + +Always use `CasinoDesign` constants instead of magic numbers: + +```swift +// ✅ Good +.padding(CasinoDesign.Spacing.medium) +.opacity(CasinoDesign.Opacity.heavy) + +// ❌ Bad +.padding(12) +.opacity(0.8) +``` + +### Localization + +Always pass localized strings for button text: + +```swift +SheetContainerView( + title: String(localized: "Settings"), + content: { ... }, + onDone: { dismiss() }, + doneButtonText: String(localized: "Done") +) +``` + +### Accessibility + +All components include VoiceOver support: +- Cards announce suit and rank +- Chips announce denomination +- Interactive elements have labels and hints + +### Dynamic Type + +Use `@ScaledMetric` with base font sizes: + +```swift +@ScaledMetric(relativeTo: .body) +private var fontSize: CGFloat = CasinoDesign.BaseFontSize.body +``` + +## Apps Using CasinoKit + +- **Baccarat** - The classic casino card game + +## Version History + +- **1.0.0** - Initial release + - Card and Chip components + - Sheet container views + - App icon and launch screen generators + - Localization support (EN, ES-MX, FR-CA) + +## License + +This package is for personal use in your casino game projects. + diff --git a/CasinoKit/Sources/CasinoKit/Exports.swift b/CasinoKit/Sources/CasinoKit/Exports.swift index ee4e0c7..f8f4b16 100644 --- a/CasinoKit/Sources/CasinoKit/Exports.swift +++ b/CasinoKit/Sources/CasinoKit/Exports.swift @@ -21,6 +21,11 @@ // - ChipStackView, ChipOnTableView // - SheetContainerView, SheetSection +// MARK: - Branding +// - AppIconView, AppIconConfig +// - LaunchScreenView, LaunchScreenConfig, StaticLaunchScreenView +// - IconRenderer, IconExportView + // MARK: - Theme // - CasinoTheme (protocol) // - DefaultCasinoTheme diff --git a/CasinoKit/Sources/CasinoKit/Resources/Localizable.xcstrings b/CasinoKit/Sources/CasinoKit/Resources/Localizable.xcstrings index babcb0d..97778e3 100644 --- a/CasinoKit/Sources/CasinoKit/Resources/Localizable.xcstrings +++ b/CasinoKit/Sources/CasinoKit/Resources/Localizable.xcstrings @@ -45,6 +45,21 @@ } } }, + "%lldpt" : { + "comment" : "A caption below an app icon that shows its size in points. The argument is the size of the icon in points.", + "isCommentAutoGenerated" : true + }, + "1. Use Xcode's preview to screenshot these icons" : { + + }, + "2. Or use IconRenderer.renderAppIcon() in code" : { + "comment" : "An instruction in the Icon Export View explaining how to generate app icons using code.", + "isCommentAutoGenerated" : true + }, + "3. Add generated images to Assets.xcassets/AppIcon" : { + "comment" : "Instructions for adding generated app icon images to Xcode's asset catalog.", + "isCommentAutoGenerated" : true + }, "Ace" : { "localizations" : { "en" : { @@ -67,6 +82,10 @@ } } }, + "App Icon Preview" : { + "comment" : "A title for the preview section of the icon export view.", + "isCommentAutoGenerated" : true + }, "Card face down" : { "localizations" : { "en" : { @@ -221,6 +240,10 @@ } } }, + "Export Instructions" : { + "comment" : "A section header describing how to export app icons.", + "isCommentAutoGenerated" : true + }, "Five" : { "localizations" : { "en" : { @@ -485,6 +508,10 @@ } } }, + "Size Variants" : { + "comment" : "A heading for the different sizes of the app icon previews.", + "isCommentAutoGenerated" : true + }, "Spades" : { "localizations" : { "en" : { diff --git a/CasinoKit/Sources/CasinoKit/Views/Branding/AppIconView.swift b/CasinoKit/Sources/CasinoKit/Views/Branding/AppIconView.swift new file mode 100644 index 0000000..90b16bb --- /dev/null +++ b/CasinoKit/Sources/CasinoKit/Views/Branding/AppIconView.swift @@ -0,0 +1,218 @@ +// +// AppIconView.swift +// CasinoKit +// +// A reusable app icon design that can be customized for different casino games. +// Render this view to an image for use as your app icon. +// + +import SwiftUI + +/// Configuration for the app icon appearance. +public struct AppIconConfig: Sendable { + public let title: String + public let subtitle: String? + public let iconSymbol: String + public let primaryColor: Color + public let secondaryColor: Color + public let accentColor: Color + + public init( + title: String, + subtitle: String? = nil, + iconSymbol: String, + primaryColor: Color = Color(red: 0.1, green: 0.2, blue: 0.35), + secondaryColor: Color = Color(red: 0.05, green: 0.12, blue: 0.25), + accentColor: Color = .yellow + ) { + self.title = title + self.subtitle = subtitle + self.iconSymbol = iconSymbol + self.primaryColor = primaryColor + self.secondaryColor = secondaryColor + self.accentColor = accentColor + } + + // MARK: - Preset Configurations + + /// Baccarat game icon configuration. + public static let baccarat = AppIconConfig( + title: "BACCARAT", + iconSymbol: "suit.spade.fill" + ) + + /// Blackjack game icon configuration. + public static let blackjack = AppIconConfig( + title: "BLACKJACK", + subtitle: "21", + iconSymbol: "suit.club.fill" + ) + + /// Poker game icon configuration. + public static let poker = AppIconConfig( + title: "POKER", + iconSymbol: "suit.diamond.fill", + accentColor: .red + ) + + /// Roulette game icon configuration. + public static let roulette = AppIconConfig( + title: "ROULETTE", + iconSymbol: "circle.grid.3x3.fill", + primaryColor: Color(red: 0.4, green: 0.1, blue: 0.1), + secondaryColor: Color(red: 0.25, green: 0.05, blue: 0.05) + ) +} + +/// A customizable app icon view for casino games. +/// Render this view to create your app icon assets. +public struct AppIconView: View { + let config: AppIconConfig + let size: CGFloat + + public init(config: AppIconConfig, size: CGFloat = 1024) { + self.config = config + self.size = size + } + + private var cornerRadius: CGFloat { size * 0.22 } + private var iconSize: CGFloat { size * 0.35 } + private var titleSize: CGFloat { size * 0.12 } + private var subtitleSize: CGFloat { size * 0.25 } + private var borderWidth: CGFloat { size * 0.02 } + + public var body: some View { + ZStack { + // Background gradient + RoundedRectangle(cornerRadius: cornerRadius) + .fill( + LinearGradient( + colors: [config.primaryColor, config.secondaryColor], + startPoint: .topLeading, + endPoint: .bottomTrailing + ) + ) + + // Subtle pattern overlay + DiamondPatternOverlay(size: size) + .opacity(0.08) + + // Gold border + RoundedRectangle(cornerRadius: cornerRadius) + .strokeBorder( + LinearGradient( + colors: [ + config.accentColor, + config.accentColor.opacity(0.6), + config.accentColor + ], + startPoint: .topLeading, + endPoint: .bottomTrailing + ), + lineWidth: borderWidth + ) + + // Content + VStack(spacing: size * 0.03) { + // Icon symbol + Image(systemName: config.iconSymbol) + .font(.system(size: iconSize, weight: .bold)) + .foregroundStyle( + LinearGradient( + colors: [config.accentColor, config.accentColor.opacity(0.8)], + startPoint: .top, + endPoint: .bottom + ) + ) + .shadow(color: .black.opacity(0.3), radius: size * 0.02, y: size * 0.01) + + // Subtitle (e.g., "21" for Blackjack) + if let subtitle = config.subtitle { + Text(subtitle) + .font(.system(size: subtitleSize, weight: .black, design: .rounded)) + .foregroundStyle( + LinearGradient( + colors: [config.accentColor, .orange], + startPoint: .top, + endPoint: .bottom + ) + ) + .shadow(color: .black.opacity(0.5), radius: size * 0.01) + } + + // Title + Text(config.title) + .font(.system(size: titleSize, weight: .black, design: .rounded)) + .tracking(size * 0.005) + .foregroundStyle( + LinearGradient( + colors: [.white, .white.opacity(0.85)], + startPoint: .top, + endPoint: .bottom + ) + ) + .shadow(color: .black.opacity(0.5), radius: size * 0.01) + } + } + .frame(width: size, height: size) + } +} + +/// Diamond pattern overlay for the icon background. +private struct DiamondPatternOverlay: View { + let size: CGFloat + + private var spacing: CGFloat { size * 0.08 } + private var diamondSize: CGFloat { size * 0.03 } + + var body: some View { + Canvas { context, canvasSize in + let rows = Int(canvasSize.height / spacing) + 1 + let cols = Int(canvasSize.width / spacing) + 1 + + for row in 0.. UIImage? { + let view = AppIconView(config: config, size: size) + let renderer = ImageRenderer(content: view) + renderer.scale = 1.0 + return renderer.uiImage + } + + /// Renders app icons at all standard iOS sizes. + /// - Parameter config: The app icon configuration. + /// - Returns: Dictionary of size to UIImage. + public static func renderAllSizes(config: AppIconConfig) -> [CGFloat: UIImage] { + var images: [CGFloat: UIImage] = [:] + for size in iOSIconSizes { + if let image = renderAppIcon(config: config, size: size) { + images[size] = image + } + } + return images + } + + /// Renders a launch screen to a UIImage. + /// - Parameters: + /// - config: The launch screen configuration. + /// - size: The size to render at. + /// - Returns: A rendered UIImage. + public static func renderLaunchScreen(config: LaunchScreenConfig, size: CGSize) -> UIImage? { + let view = StaticLaunchScreenView(config: config) + .frame(width: size.width, height: size.height) + let renderer = ImageRenderer(content: view) + renderer.scale = 1.0 + return renderer.uiImage + } +} + +// MARK: - Icon Export View + +/// A development view for previewing and exporting app icons. +/// Add this to your app during development to easily export icons. +public struct IconExportView: View { + let config: AppIconConfig + @State private var exportedMessage: String? + + public init(config: AppIconConfig) { + self.config = config + } + + public var body: some View { + ScrollView { + VStack(spacing: 24) { + Text("App Icon Preview") + .font(.title.bold()) + + // Large preview + AppIconView(config: config, size: 256) + .clipShape(.rect(cornerRadius: 256 * 0.22)) + .shadow(radius: 10) + + // Size variants + Text("Size Variants") + .font(.headline) + + LazyVGrid(columns: [ + GridItem(.adaptive(minimum: 100)) + ], spacing: 16) { + ForEach([180, 120, 87, 60, 40], id: \.self) { size in + VStack { + AppIconView(config: config, size: CGFloat(size)) + .clipShape(.rect(cornerRadius: CGFloat(size) * 0.22)) + Text("\(size)pt") + .font(.caption) + .foregroundStyle(.secondary) + } + } + } + + // Export instructions + Text("Export Instructions") + .font(.headline) + .padding(.top) + + VStack(alignment: .leading, spacing: 8) { + Text("1. Use Xcode's preview to screenshot these icons") + Text("2. Or use IconRenderer.renderAppIcon() in code") + Text("3. Add generated images to Assets.xcassets/AppIcon") + } + .font(.callout) + .foregroundStyle(.secondary) + .frame(maxWidth: .infinity, alignment: .leading) + .padding() + .background(Color.gray.opacity(0.1)) + .clipShape(.rect(cornerRadius: 12)) + + if let message = exportedMessage { + Text(message) + .foregroundStyle(.green) + } + } + .padding() + } + } +} + +#Preview("Icon Export") { + IconExportView(config: .baccarat) +} + diff --git a/CasinoKit/Sources/CasinoKit/Views/Branding/LaunchScreenView.swift b/CasinoKit/Sources/CasinoKit/Views/Branding/LaunchScreenView.swift new file mode 100644 index 0000000..f5d8743 --- /dev/null +++ b/CasinoKit/Sources/CasinoKit/Views/Branding/LaunchScreenView.swift @@ -0,0 +1,351 @@ +// +// LaunchScreenView.swift +// CasinoKit +// +// A reusable launch screen design that can be customized for different casino games. +// + +import SwiftUI + +/// Configuration for the launch screen appearance. +public struct LaunchScreenConfig: Sendable { + public let title: String + public let subtitle: String? + public let tagline: String? + public let iconSymbols: [String] + public let primaryColor: Color + public let secondaryColor: Color + public let accentColor: Color + public let showLoadingIndicator: Bool + + public init( + title: String, + subtitle: String? = nil, + tagline: String? = nil, + iconSymbols: [String] = ["suit.spade.fill", "suit.heart.fill"], + primaryColor: Color = Color(red: 0.05, green: 0.12, blue: 0.22), + secondaryColor: Color = Color(red: 0.02, green: 0.06, blue: 0.12), + accentColor: Color = .yellow, + showLoadingIndicator: Bool = false + ) { + self.title = title + self.subtitle = subtitle + self.tagline = tagline + self.iconSymbols = iconSymbols + self.primaryColor = primaryColor + self.secondaryColor = secondaryColor + self.accentColor = accentColor + self.showLoadingIndicator = showLoadingIndicator + } + + // MARK: - Preset Configurations + + /// Baccarat game launch screen configuration. + public static let baccarat = LaunchScreenConfig( + title: "BACCARAT", + tagline: "The Classic Casino Card Game", + iconSymbols: ["suit.spade.fill", "suit.heart.fill"] + ) + + /// Blackjack game launch screen configuration. + public static let blackjack = LaunchScreenConfig( + title: "BLACKJACK", + subtitle: "21", + tagline: "Beat the Dealer", + iconSymbols: ["suit.club.fill", "suit.diamond.fill"] + ) + + /// Poker game launch screen configuration. + public static let poker = LaunchScreenConfig( + title: "POKER", + tagline: "Texas Hold'em", + iconSymbols: ["suit.diamond.fill", "suit.club.fill"], + accentColor: .red + ) +} + +/// A customizable launch screen view for casino games. +public struct LaunchScreenView: View { + let config: LaunchScreenConfig + + @State private var logoScale: CGFloat = 0.8 + @State private var logoOpacity: Double = 0 + @State private var titleOffset: CGFloat = 20 + @State private var titleOpacity: Double = 0 + + public init(config: LaunchScreenConfig) { + self.config = config + } + + public var body: some View { + GeometryReader { geometry in + ZStack { + // Background gradient + backgroundGradient + + // Pattern overlay + patternOverlay + .opacity(0.05) + + // Decorative corner elements + cornerDecorations(in: geometry) + + // Main content + VStack(spacing: 0) { + Spacer() + + // Logo section + logoSection + .scaleEffect(logoScale) + .opacity(logoOpacity) + + Spacer() + + // Bottom tagline + if let tagline = config.tagline { + Text(tagline) + .font(.system(size: 14, weight: .medium, design: .rounded)) + .foregroundStyle(.white.opacity(0.6)) + .tracking(2) + .padding(.bottom, 40) + .offset(y: titleOffset) + .opacity(titleOpacity) + } + + // Loading indicator + if config.showLoadingIndicator { + ProgressView() + .progressViewStyle(.circular) + .tint(config.accentColor) + .scaleEffect(1.2) + .padding(.bottom, 60) + } + } + } + } + .ignoresSafeArea() + .onAppear { + withAnimation(.easeOut(duration: 0.6)) { + logoScale = 1.0 + logoOpacity = 1.0 + } + withAnimation(.easeOut(duration: 0.6).delay(0.3)) { + titleOffset = 0 + titleOpacity = 1.0 + } + } + } + + // MARK: - Background + + private var backgroundGradient: some View { + LinearGradient( + colors: [ + config.primaryColor, + config.secondaryColor + ], + startPoint: .top, + endPoint: .bottom + ) + } + + private var patternOverlay: some View { + Canvas { context, size in + let spacing: CGFloat = 40 + let diamondSize: CGFloat = 8 + let rows = Int(size.height / spacing) + 1 + let cols = Int(size.width / spacing) + 1 + + for row in 0.. some View { + ZStack { + // Top-left + cornerSymbol + .position(x: 50, y: 80) + + // Top-right + cornerSymbol + .rotationEffect(.degrees(90)) + .position(x: geometry.size.width - 50, y: 80) + + // Bottom-left + cornerSymbol + .rotationEffect(.degrees(-90)) + .position(x: 50, y: geometry.size.height - 80) + + // Bottom-right + cornerSymbol + .rotationEffect(.degrees(180)) + .position(x: geometry.size.width - 50, y: geometry.size.height - 80) + } + .opacity(0.15) + } + + private var cornerSymbol: some View { + Image(systemName: "suit.spade.fill") + .font(.system(size: 30)) + .foregroundStyle(config.accentColor) + } + + // MARK: - Logo Section + + private var logoSection: some View { + VStack(spacing: 16) { + // Card suit icons + HStack(spacing: -8) { + ForEach(config.iconSymbols.indices, id: \.self) { index in + Image(systemName: config.iconSymbols[index]) + .font(.system(size: 48, weight: .bold)) + .foregroundStyle(iconColor(for: index)) + .shadow(color: .black.opacity(0.3), radius: 4, y: 2) + } + } + + // Subtitle (e.g., "21" for Blackjack) + if let subtitle = config.subtitle { + Text(subtitle) + .font(.system(size: 72, weight: .black, design: .rounded)) + .foregroundStyle( + LinearGradient( + colors: [config.accentColor, .orange], + startPoint: .top, + endPoint: .bottom + ) + ) + .shadow(color: .black.opacity(0.4), radius: 4, y: 2) + } + + // Title + Text(config.title) + .font(.system(size: 42, weight: .black, design: .rounded)) + .tracking(6) + .foregroundStyle( + LinearGradient( + colors: [config.accentColor, .orange], + startPoint: .top, + endPoint: .bottom + ) + ) + .shadow(color: .black.opacity(0.4), radius: 4, y: 2) + + // Decorative line + HStack(spacing: 12) { + decorativeLine + + Image(systemName: "diamond.fill") + .font(.system(size: 10)) + .foregroundStyle(config.accentColor.opacity(0.6)) + + decorativeLine + } + .frame(width: 200) + } + } + + private func iconColor(for index: Int) -> Color { + let symbol = config.iconSymbols[index] + if symbol.contains("heart") || symbol.contains("diamond") { + return .red + } + return .white + } + + private var decorativeLine: some View { + Rectangle() + .fill( + LinearGradient( + colors: [.clear, config.accentColor.opacity(0.4), .clear], + startPoint: .leading, + endPoint: .trailing + ) + ) + .frame(height: 1) + } +} + +// MARK: - Static Launch Screen (for LaunchScreen.storyboard alternative) + +/// A static version of the launch screen without animations. +/// Use this if you need to render a static image. +public struct StaticLaunchScreenView: View { + let config: LaunchScreenConfig + + public init(config: LaunchScreenConfig) { + self.config = config + } + + public var body: some View { + GeometryReader { geometry in + ZStack { + // Background + LinearGradient( + colors: [config.primaryColor, config.secondaryColor], + startPoint: .top, + endPoint: .bottom + ) + + // Logo + VStack(spacing: 16) { + HStack(spacing: -8) { + ForEach(config.iconSymbols.indices, id: \.self) { index in + let symbol = config.iconSymbols[index] + Image(systemName: symbol) + .font(.system(size: 48, weight: .bold)) + .foregroundStyle( + symbol.contains("heart") || symbol.contains("diamond") ? .red : .white + ) + } + } + + if let subtitle = config.subtitle { + Text(subtitle) + .font(.system(size: 72, weight: .black, design: .rounded)) + .foregroundStyle(config.accentColor) + } + + Text(config.title) + .font(.system(size: 42, weight: .black, design: .rounded)) + .tracking(6) + .foregroundStyle(config.accentColor) + } + } + } + .ignoresSafeArea() + } +} + +// MARK: - Preview + +#Preview("Baccarat Launch") { + LaunchScreenView(config: .baccarat) +} + +#Preview("Blackjack Launch") { + LaunchScreenView(config: .blackjack) +} + +#Preview("Static Launch") { + StaticLaunchScreenView(config: .baccarat) +} +