Skip to content

Commit 3a47b77

Browse files
committed
Migrate Content.swift strings to Localizable.xcstrings for localization support
1 parent 22836e1 commit 3a47b77

13 files changed

Lines changed: 637 additions & 50 deletions

SwiftRadio.xcodeproj/project.pbxproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@
103103
CEE9A27C2B535C780018FE68 /* AlbumArtworkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE9A27A2B535C780018FE68 /* AlbumArtworkView.swift */; };
104104
CEE9A27E2B54A5520018FE68 /* ControlsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE9A27D2B54A5520018FE68 /* ControlsView.swift */; };
105105
CEE9A27F2B54A5520018FE68 /* ControlsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE9A27D2B54A5520018FE68 /* ControlsView.swift */; };
106+
CA5F00042F41000000000001 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = CA5F00062F41000000000003 /* Localizable.xcstrings */; };
107+
CA5F00052F41000000000002 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = CA5F00062F41000000000003 /* Localizable.xcstrings */; };
106108
/* End PBXBuildFile section */
107109

108110
/* Begin PBXContainerItemProxy section */
@@ -191,6 +193,7 @@
191193
CEE9A2772B5345C30018FE68 /* NowPlayingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NowPlayingViewController.swift; sourceTree = "<group>"; };
192194
CEE9A27A2B535C780018FE68 /* AlbumArtworkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlbumArtworkView.swift; sourceTree = "<group>"; };
193195
CEE9A27D2B54A5520018FE68 /* ControlsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ControlsView.swift; sourceTree = "<group>"; };
196+
CA5F00062F41000000000003 /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = "<group>"; };
194197
/* End PBXFileReference section */
195198

196199
/* Begin PBXFrameworksBuildPhase section */
@@ -274,6 +277,7 @@
274277
BB0000012D4E000000000001 /* App */,
275278
BB0000022D4E000000000002 /* Config */,
276279
9409E1251ABF6FEA00312E2B /* Images.xcassets */,
280+
CA5F00062F41000000000003 /* Localizable.xcstrings */,
277281
9409E11A1ABF6FEA00312E2B /* Info.plist */,
278282
CEA82F492921F260009E9FA0 /* Info-CarPlay.plist */,
279283
);
@@ -553,6 +557,7 @@
553557
945DB3C51AD5A6E200495EBB /* NothingFoundCell.xib in Resources */,
554558
6258DCDA22D93A5400166C65 /* LogoShareView.xib in Resources */,
555559
9409E1261ABF6FEA00312E2B /* Images.xcassets in Resources */,
560+
CA5F00042F41000000000001 /* Localizable.xcstrings in Resources */,
556561
);
557562
runOnlyForDeploymentPostprocessing = 0;
558563
};
@@ -564,6 +569,7 @@
564569
CE6A3E47291F376D0058C82A /* NothingFoundCell.xib in Resources */,
565570
CE6A3E48291F376D0058C82A /* LogoShareView.xib in Resources */,
566571
CE6A3E4B291F376D0058C82A /* Images.xcassets in Resources */,
572+
CA5F00052F41000000000002 /* Localizable.xcstrings in Resources */,
567573
);
568574
runOnlyForDeploymentPostprocessing = 0;
569575
};

SwiftRadio/Cells/NothingFoundCell.xib

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="t6R-Cw-i7I">
2323
<rect key="frame" x="32" y="11" width="256" height="66"/>
2424
<subviews>
25-
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Loading Stations..." lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="nc3-Ld-cfB">
25+
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" tag="100" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="nc3-Ld-cfB">
2626
<rect key="frame" x="53.5" y="0.0" width="149.5" height="66"/>
2727
<fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/>
2828
<color key="textColor" red="0.84939253330230713" green="0.84936714172363281" blue="0.84938156604766846" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>

SwiftRadio/Config/Config.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,12 @@ struct Config {
2929
// Set this to "false" to show the next/previous player buttons
3030
static let hideNextPreviousButtons = false
3131

32-
// Contact infos
32+
// Contact & links
3333
static let website = "https://github.com/analogcode/Swift-Radio-Pro"
3434
static let email = "contact@fethica.com"
3535
static let emailSubject = "From \(Bundle.main.appName) App"
36+
static let feedbackURL = "https://fethica.com/#contact"
37+
static let licenseURL = "https://raw.githubusercontent.com/analogcode/Swift-Radio-Pro/refs/heads/master/LICENSE"
3638

3739
struct Libraries {
3840
static let items: [LibraryItem] = [
@@ -63,7 +65,7 @@ struct Config {
6365
]),
6466
InfoSection(title: Content.About.Sections.contact, items: [
6567
.email(address: Config.email),
66-
.link(title: Content.About.feedback.0, subtitle: Content.About.feedback.1, url: "https://fethica.com/#contact")
68+
.link(title: Content.About.feedback.0, subtitle: Content.About.feedback.1, url: Config.feedbackURL)
6769
]),
6870
InfoSection(title: Content.About.Sections.support, items: [
6971
.rateApp(appID: "YOUR_APP_ID"),
@@ -74,7 +76,7 @@ struct Config {
7476
.credits(owner: "analogcode", repo: "Swift-Radio-Pro")
7577
]),
7678
InfoSection(title: Content.About.Sections.legal, items: [
77-
.link(title: Content.About.license.0, subtitle: Content.About.license.1, url: "https://raw.githubusercontent.com/analogcode/Swift-Radio-Pro/refs/heads/master/LICENSE")
79+
.link(title: Content.About.license.0, subtitle: Content.About.license.1, url: Config.licenseURL)
7880
]),
7981
InfoSection(title: Content.About.Sections.version, items: [
8082
.version()

SwiftRadio/Config/Content.swift

Lines changed: 62 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,54 +5,85 @@
55
// Created by Fethi El Hassasna on 2025-01-26.
66
// Copyright © 2025 matthewfecher.com. All rights reserved.
77
//
8+
// All user-facing strings are backed by Localizable.xcstrings.
9+
// To update text or add translations, edit the String Catalog in Xcode.
10+
//
811

912
import Foundation
1013

1114
struct Content {
1215
struct About {
13-
static let title = "About Swift Radio"
14-
15-
static let headerText = """
16-
**Swift Radio** is a fully featured, open-source radio station app written entirely in **Swift**. \
17-
It provides robust, professional functionality out of the box, \
18-
complete with **Apple CarPlay** support, making it the perfect foundation \
19-
for **building** or **customizing** your own streaming radio experience.
20-
"""
21-
22-
static let footerAuthors = "Fethi El Hassasna & Matt Fecher"
23-
static let footerCopyright = "Swift Radio"
16+
static let title = String(localized: "about.title")
17+
static let headerText = String(localized: "about.headerText")
18+
static let footerAuthors = String(localized: "about.footerAuthors")
19+
static let footerCopyright = String(localized: "about.footerCopyright")
2420

2521
struct Sections {
26-
static let features = "Features"
27-
static let contact = "Contact"
28-
static let support = "Support"
29-
static let credits = "Credits"
30-
static let legal = "Legal"
31-
static let version = "Version"
22+
static let features = String(localized: "about.sections.features")
23+
static let contact = String(localized: "about.sections.contact")
24+
static let support = String(localized: "about.sections.support")
25+
static let credits = String(localized: "about.sections.credits")
26+
static let legal = String(localized: "about.sections.legal")
27+
static let version = String(localized: "about.sections.version")
3228
}
3329

34-
static let feedback = ("Feedback", "We value your input! Please take a moment to provide feedback")
35-
static let shareText = "Check out Swift Radio!"
36-
static let license = ("License", "MIT License")
30+
static let feedback = (String(localized: "about.feedback.title"), String(localized: "about.feedback.message"))
31+
static let shareText = String(localized: "about.shareText")
32+
static let license = (String(localized: "about.license.title"), String(localized: "about.license.detail"))
3733
}
3834

3935
struct Contributors {
40-
static let title = "Contributors"
36+
static let title = String(localized: "contributors.title")
4137
}
4238

4339
struct Libraries {
44-
static let title = "Libraries"
40+
static let title = String(localized: "libraries.title")
41+
}
42+
43+
struct Stations {
44+
static let title = String(localized: "stations.title")
45+
static let loadingMessage = String(localized: "stations.loadingMessage")
46+
}
47+
48+
struct Loader {
49+
static let errorTitle = String(localized: "loader.errorTitle")
50+
static let retryButton = String(localized: "loader.retryButton")
51+
}
52+
53+
struct StationDetail {
54+
static let title = String(localized: "stationDetail.title")
55+
static let visitWebsite = String(localized: "stationDetail.visitWebsite")
56+
static let defaultDescription = String(localized: "stationDetail.defaultDescription")
57+
}
58+
59+
struct BottomSheet {
60+
static let aboutStation = String(localized: "bottomSheet.aboutStation")
61+
static let shareNowPlaying = String(localized: "bottomSheet.shareNowPlaying")
62+
static let stationWebsite = String(localized: "bottomSheet.stationWebsite")
63+
static let playInMusicApp = String(localized: "bottomSheet.playInMusicApp")
64+
}
65+
66+
struct Player {
67+
static let liveBadge = String(localized: "player.liveBadge")
68+
}
69+
70+
struct Common {
71+
static let ok = String(localized: "common.ok")
72+
static let couldNotSendEmail = String(localized: "common.couldNotSendEmail")
73+
static let emailErrorMessage = String(localized: "common.emailErrorMessage")
74+
static let noDescription = String(localized: "common.noDescription")
75+
static let commitsFormat = String(localized: "common.commitsFormat")
4576
}
4677

4778
struct Features {
48-
static let title = "Features"
49-
50-
static let swiftCodebase = ("Swift Codebase", "Entirely written in Swift with a clean and modern structure.")
51-
static let carPlay = ("Apple CarPlay Support", "Lets users control their radio playback directly from their CarPlay dashboard.")
52-
static let customizableUI = ("Customizable UI", "Includes a flexible interface that you can easily personalize with your own theme and branding.")
53-
static let albumArt = ("Album Art & Metadata", "Displays track information and album covers to enhance the listening experience.")
54-
static let lockScreen = ("Lock Screen & Control Center Integration", "Shows artwork and track info on the lock screen, and provides convenient controls without opening the app.")
55-
static let multipleStations = ("Multiple Stations Setup", "Comes with a straightforward station list manager that supports multiple streaming URLs.")
56-
static let easySetup = ("Easy Project Setup", "Ready to run right out of the box, and you can adjust key settings in a single configuration file.")
79+
static let title = String(localized: "features.title")
80+
81+
static let swiftCodebase = (String(localized: "features.swiftCodebase.title"), String(localized: "features.swiftCodebase.description"))
82+
static let carPlay = (String(localized: "features.carPlay.title"), String(localized: "features.carPlay.description"))
83+
static let customizableUI = (String(localized: "features.customizableUI.title"), String(localized: "features.customizableUI.description"))
84+
static let albumArt = (String(localized: "features.albumArt.title"), String(localized: "features.albumArt.description"))
85+
static let lockScreen = (String(localized: "features.lockScreen.title"), String(localized: "features.lockScreen.description"))
86+
static let multipleStations = (String(localized: "features.multipleStations.title"), String(localized: "features.multipleStations.description"))
87+
static let easySetup = (String(localized: "features.easySetup.title"), String(localized: "features.easySetup.description"))
5788
}
5889
}

SwiftRadio/Helpers/UIViewController+Email.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ extension MFMailComposeViewControllerDelegate where Self: UIViewController {
2929

3030
extension UIViewController {
3131
func showSendMailErrorAlert() {
32-
let sendMailErrorAlert = UIAlertController(title: "Could Not Send Email", message: "Your device could not send e-mail. Please check e-mail configuration and try again.", preferredStyle: .alert)
33-
let cancelAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
32+
let sendMailErrorAlert = UIAlertController(title: Content.Common.couldNotSendEmail, message: Content.Common.emailErrorMessage, preferredStyle: .alert)
33+
let cancelAction = UIAlertAction(title: Content.Common.ok, style: .cancel, handler: nil)
3434

3535
sendMailErrorAlert.addAction(cancelAction)
3636
present(sendMailErrorAlert, animated: true, completion: nil)

0 commit comments

Comments
 (0)