Skip to content

Commit 2c0dbbe

Browse files
committed
Merge branch 'deploy/1.4.0' into productive
2 parents 0fdd025 + 211ee8f commit 2c0dbbe

File tree

5 files changed

+127
-73
lines changed

5 files changed

+127
-73
lines changed

BartyCrouch CLI/main.swift

Lines changed: 63 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ let cli = CommandLine()
1616
let input = StringOption(
1717
shortFlag: "i",
1818
longFlag: "input",
19-
required: true,
19+
required: false,
2020
helpMessage: "Path to your source file to be used for translation."
2121
)
2222

@@ -197,52 +197,76 @@ func run() {
197197
return .IncrementalUpdate
198198
}()
199199

200-
let inputFilePath = input.value!
201-
202-
let outputStringsFilePaths: [String] = {
203-
switch outputType {
204-
case .StringsFiles:
205-
if let stringsFiles = output.value {
206-
// check if output style is locales-only, e.g. `-o en de zh-Hans pt-BR` - convert to full paths if so
207-
do {
208-
let localeRegex = try NSRegularExpression(pattern: "\\A\\w{2}(-\\w{2,4})?\\z", options: .CaseInsensitive)
209-
let locales = stringsFiles.filter { localeRegex.matchesInString($0, options: .ReportCompletion, range: NSMakeRange(0, $0.characters.count)).count > 0 }
210-
if locales.count == stringsFiles.count {
211-
let lprojLocales = locales.map { "\($0).lproj" }
212-
return StringsFilesSearch.sharedInstance.findAll(inputFilePath).filter { $0.containsAny(ofStrings: lprojLocales) }
213-
}
214-
} catch {
215-
print("Error! Couldn't init locale regex. Please report this issue on https://github.com/Flinesoft/BartyCrouch/issues.")
216-
}
200+
let inputFilePaths: [String] = {
201+
if let inputFilePath = input.value {
202+
return [inputFilePath]
203+
} else if outputType == .Automatic {
204+
if Process.arguments.count > 1 {
205+
let baseDirectoryPath = Process.arguments[1]
206+
return StringsFilesSearch.sharedInstance.findAllIBFiles(baseDirectoryPath)
207+
} else {
208+
print("Error! No directory path specified to search for input files.")
209+
exit(EX_USAGE)
217210
}
218-
return output.value!
219-
case .Automatic:
220-
return StringsFilesSearch.sharedInstance.findAll(inputFilePath).filter { $0 != inputFilePath }
221-
case .Except:
222-
return StringsFilesSearch.sharedInstance.findAll(inputFilePath).filter { $0 != inputFilePath && !except.value!.contains($0) }
223-
case .None:
224-
print("Error! Missing output key '\(output.shortFlag!)' or '\(auto.shortFlag!)'.")
211+
} else {
212+
print("Error! Missing input path(s).")
225213
exit(EX_USAGE)
226214
}
227215
}()
228216

229-
guard NSFileManager.defaultManager().fileExistsAtPath(inputFilePath) else {
230-
print("Error! No file exists at input path '\(inputFilePath)'")
231-
exit(EX_NOINPUT)
217+
guard inputFilePaths.count > 0 else {
218+
print("Error! No input files found.")
219+
exit(EX_USAGE)
232220
}
233221

234-
for outputStringsFilePath in outputStringsFilePaths {
235-
guard NSFileManager.defaultManager().fileExistsAtPath(outputStringsFilePath) else {
236-
print("Error! No file exists at output path '\(outputStringsFilePath)'.")
237-
exit(EX_CONFIG)
222+
for inputFilePath in inputFilePaths {
223+
224+
let outputStringsFilePaths: [String] = {
225+
switch outputType {
226+
case .StringsFiles:
227+
if let stringsFiles = output.value {
228+
// check if output style is locales-only, e.g. `-o en de zh-Hans pt-BR` - convert to full paths if so
229+
do {
230+
let localeRegex = try NSRegularExpression(pattern: "\\A\\w{2}(-\\w{2,4})?\\z", options: .CaseInsensitive)
231+
let locales = stringsFiles.filter { localeRegex.matchesInString($0, options: .ReportCompletion, range: NSMakeRange(0, $0.characters.count)).count > 0 }
232+
if locales.count == stringsFiles.count {
233+
let lprojLocales = locales.map { "\($0).lproj" }
234+
return StringsFilesSearch.sharedInstance.findAllStringsFiles(inputFilePath).filter { $0.containsAny(ofStrings: lprojLocales) }
235+
}
236+
} catch {
237+
print("Error! Couldn't init locale regex. Please report this issue on https://github.com/Flinesoft/BartyCrouch/issues.")
238+
}
239+
}
240+
return output.value!
241+
case .Automatic:
242+
return StringsFilesSearch.sharedInstance.findAllStringsFiles(inputFilePath).filter { $0 != inputFilePath }
243+
case .Except:
244+
return StringsFilesSearch.sharedInstance.findAllStringsFiles(inputFilePath).filter { $0 != inputFilePath && !except.value!.contains($0) }
245+
case .None:
246+
print("Error! Missing output key '\(output.shortFlag!)' or '\(auto.shortFlag!)'.")
247+
exit(EX_USAGE)
248+
}
249+
}()
250+
251+
guard NSFileManager.defaultManager().fileExistsAtPath(inputFilePath) else {
252+
print("Error! No file exists at input path '\(inputFilePath)'")
253+
exit(EX_NOINPUT)
238254
}
239-
}
240-
241-
switch actionType {
242-
case .IncrementalUpdate:
243-
incrementalUpdate(inputFilePath, outputStringsFilePaths)
244-
case .Translate:
245-
translate(credentials: translate.value!, inputFilePath, outputStringsFilePaths)
255+
256+
for outputStringsFilePath in outputStringsFilePaths {
257+
guard NSFileManager.defaultManager().fileExistsAtPath(outputStringsFilePath) else {
258+
print("Error! No file exists at output path '\(outputStringsFilePath)'.")
259+
exit(EX_CONFIG)
260+
}
261+
}
262+
263+
switch actionType {
264+
case .IncrementalUpdate:
265+
incrementalUpdate(inputFilePath, outputStringsFilePaths)
266+
case .Translate:
267+
translate(credentials: translate.value!, inputFilePath, outputStringsFilePaths)
268+
}
269+
246270
}
247271

248272
}

README.md

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
<p align="center">
2-
<img src="https://raw.githubusercontent.com/Flinesoft/BartyCrouch/develop/Logo.png"
2+
<img src="https://raw.githubusercontent.com/Flinesoft/BartyCrouch/stable/Logo.png"
33
width=600 height=167>
44
</p>
55

66
<p align="center">
77
<a href="https://github.com/Flinesoft/BartyCrouch/releases">
8-
<img src="https://img.shields.io/badge/version-1.3.0-blue.svg"
9-
alt="Version: 1.3.0">
8+
<img src="https://img.shields.io/badge/Version-1.4.0-blue.svg"
9+
alt="Version: 1.4.0">
1010
</a>
1111
<a href="#">
1212
<img src="https://img.shields.io/badge/Swift-2.1-DD563C.svg"
1313
alt="Swift: 2.1">
1414
</a>
15-
<a href="https://github.com/Flinesoft/BartyCrouch/blob/develop/LICENSE.md">
16-
<img src="https://img.shields.io/badge/license-MIT-lightgrey.svg"
15+
<a href="https://github.com/Flinesoft/BartyCrouch/blob/stable/LICENSE.md">
16+
<img src="https://img.shields.io/badge/License-MIT-lightgrey.svg"
1717
alt="License: MIT">
1818
</a>
1919
</p>
@@ -60,11 +60,11 @@ Before using BartyCrouch please **make sure you have committed your code**.
6060
With BartyCrouch you can run commands like these:
6161

6262
``` shell
63-
# Incrementally update English and German strings of Main.storyboard
64-
bartycrouch -i "path/Base.lproj/Main.storyboard" -o en de zh-Hans pt-BR"
63+
# Incrementally update English, Simplified Chinese and Brazilian Portuguese strings of Main.storyboard
64+
bartycrouch -i "path/Base.lproj/Main.storyboard" -o en zh-Hans pt-BR
6565

66-
# Incrementally update all languages of Main.storyboard
67-
bartycrouch -i "path/Base.lproj/Main.storyboard" -a
66+
# Incrementally update all languages of all Storyboard/XIB files
67+
bartycrouch "/absolute/path/to/project" -a
6868

6969
# Machine-translate all empty values of all supported languages with English as source
7070
bartycrouch -t "{ id: ID }|{ secret: SECRET }" -i "path/en.lproj/Localizable.strings" -a
@@ -79,11 +79,17 @@ Also you can make your life a lot easier by using the **build script method** de
7979

8080
The `bartycrouch` main command accepts one of the following combinations of arguments:
8181

82-
1. Input and Output/Auto/Except
83-
2. Translate with Input and Output/Auto/Except
82+
1. Automatic input and output search (all localized Storyboards/XIBs)
83+
2. Input and Output/Auto/Except
84+
3. Translate with Input and Output/Auto/Except
8485

8586
You can also additionally specify Force and/or Verbose on each command.
8687

88+
### Full Automatic (aka `/absolute/path -a`)
89+
90+
If you want BartyCrouch to **search for all localized Storyboards/XIBs** (those in Base.lproj folders) and also want BartyCrouch to find the respective output files,
91+
then simply declare the BartyCrouch command with an absolute path followed by `-a` like `/absolute/path/to/project -a`.
92+
8793
#### Input (aka `-i`)
8894

8995
You can specify the input Storyboard, XIB or Strings file using `-i "path/to/my.storyboard"` (`-i` is short `--input`).
@@ -126,34 +132,34 @@ You may want to **update your `.strings` files on each build automatically** wha
126132

127133
``` shell
128134
if which bartycrouch > /dev/null; then
129-
# Set path to base internationalized Storyboard/XIB files
130-
BASE_PATH="$PROJECT_DIR/Sources/Base.lproj"
131-
132135
# Incrementally update all Storyboards/XIBs strings files
133-
bartycrouch -i "$BASE_PATH/Main.storyboard" -a
134-
bartycrouch -i "$BASE_PATH/LaunchScreen.storyboard" -a
135-
bartycrouch -i "$BASE_PATH/CustomView.xib" -a
136-
137-
# Set Microsoft Translator API credentials
138-
EN_PATH="$PROJECT_DIR/Sources/en.lproj"
139-
CREDS="{ id: YOUR_ID }|{ secret: YOUR_SECRET }"
140-
141-
# Machine-translate empty language values for all languages
142-
bartycrouch -t $CREDS -i "$EN_PATH/Localizable.strings" -a
143-
bartycrouch -t $CREDS -i "$EN_PATH/Main.strings" -a
144-
bartycrouch -t $CREDS -i "$EN_PATH/LaunchScreen.strings" -a
145-
bartycrouch -t $CREDS -i "$EN_PATH/CustomView.strings" -a
136+
bartycrouch $PROJECT_DIR -a
146137
else
147138
echo "warning: BartyCrouch not installed, download it from https://github.com/Flinesoft/BartyCrouch"
148139
fi
149140
```
150-
151141
<img src="Build-Script-Example.png">
152142

153-
Update the `BASE_PATH` to point to your Base.lproj directory, remove all unneeded lines, add a `bartycrouch -i ... -a` (or any other BartyCrouch command) for each of your base internationalized Storyboards/XIBs (if any) and you're good to go. You should also uncomment or remove the lines below `# Set Microsoft ...` until `bartycrouch -t ...` if you don't want to use the machine translation feature. Xcode will now run BartyCrouch each time you build your project and update your `.strings` files accordingly.
154-
155143
*Note: Please make sure you commit your code using source control regularly when using the build script method.*
156144

145+
If you want to use the **machine translation functionality** too then simply add the following to the if part:
146+
147+
```
148+
# OPTIONAL
149+
150+
# Set source language for machine translation
151+
EN_PATH="$PROJECT_DIR/Sources/en.lproj"
152+
153+
# Set Microsoft Translator API credentials
154+
CREDS="{ id: YOUR_ID }|{ secret: YOUR_SECRET }"
155+
156+
# Machine-translate empty language values for all languages
157+
bartycrouch -t $CREDS -i "$EN_PATH/Localizable.strings" -a
158+
bartycrouch -t $CREDS -i "$EN_PATH/Main.strings" -a
159+
bartycrouch -t $CREDS -i "$EN_PATH/LaunchScreen.strings" -a
160+
bartycrouch -t $CREDS -i "$EN_PATH/CustomView.strings" -a
161+
```
162+
157163
### Exclude specific views from localization
158164

159165
Sometimes you may want to **ignore some specific views** containing localizable texts e.g. because **their values are set programmatically**.

Sources/Code/StringsFilesSearch.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,18 @@ public class StringsFilesSearch {
1818

1919
// MARK: - Instance Methods
2020

21-
public func findAll(baseFilePath: String) -> [String] {
21+
public func findAllIBFiles(baseDirectoryPath: String) -> [String] {
22+
do {
23+
let ibFileRegex = try NSRegularExpression(pattern: ".*\\Base.lproj.*\\.(storyboard|xib)\\z", options: .CaseInsensitive)
24+
let allFilePaths = try NSFileManager.defaultManager().subpathsOfDirectoryAtPath(baseDirectoryPath)
25+
let ibFilePaths = allFilePaths.filter { ibFileRegex.matchesInString($0, options: .ReportCompletion, range: NSMakeRange(0, $0.characters.count)).count > 0 }
26+
return ibFilePaths.map { baseDirectoryPath + "/" + $0 }
27+
} catch {
28+
return []
29+
}
30+
}
31+
32+
public func findAllStringsFiles(baseFilePath: String) -> [String] {
2233
var pathComponents = baseFilePath.componentsSeparatedByString("/")
2334
let storyboardName: String = {
2435
var fileNameComponents = pathComponents.last!.componentsSeparatedByString(".")

Sources/Supporting Files/Info.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<key>CFBundlePackageType</key>
1616
<string>FMWK</string>
1717
<key>CFBundleShortVersionString</key>
18-
<string>1.0</string>
18+
<string>1.4.0</string>
1919
<key>CFBundleSignature</key>
2020
<string>????</string>
2121
<key>CFBundleVersion</key>

Tests/Code/StringsFilesSearchTests.swift

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,26 @@ import XCTest
1111
@testable import BartyCrouch
1212

1313
class StringsFilesSearchTests: XCTestCase {
14+
15+
func testFindAllIBFiles() {
16+
17+
let basePath = "\(PROJECT_DIR)/Tests"
18+
19+
let expectedIBFilePaths = ["iOS", "OSX", "tvOS"].map { examplePath(platform: $0, locale: "Base", type: "storyboard") }
20+
21+
let results = StringsFilesSearch.sharedInstance.findAllIBFiles(basePath)
22+
23+
XCTAssertEqual(results.count, expectedIBFilePaths.count)
24+
XCTAssertEqual(results, expectedIBFilePaths)
25+
26+
}
1427

15-
func testiOSFindAllWithBaseStoryboardPath() {
28+
func testiOSFindAllStringsFiles() {
1629

1730
let baseStoryboardPath = examplePath(platform: "iOS", locale: "base", type: ".storyboard")
1831
let expectedStringsPaths = ["de", "en", "ja", "zh-Hans"].map { examplePath(platform: "iOS", locale: $0, type: ".strings") }
1932

20-
let results = StringsFilesSearch.sharedInstance.findAll(baseStoryboardPath)
33+
let results = StringsFilesSearch.sharedInstance.findAllStringsFiles(baseStoryboardPath)
2134

2235
XCTAssertEqual(results.count, expectedStringsPaths.count)
2336
XCTAssertEqual(results, expectedStringsPaths)

0 commit comments

Comments
 (0)