├── .gitignore ├── LICENSE ├── Localized String Shortcut.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── LocalizedString ├── BaseSourceEditorCommand.swift ├── BundleLocalizedStringCommand.swift ├── CompleteLocalizedStringCommand.swift ├── Info.plist ├── LocalizedString.entitlements ├── MinimumLocalizedStringCommand.swift ├── SimpleLocalizedStringCommand.swift ├── SourceEditorExtension.swift ├── TableLocalizedStringCommand.swift └── WithDefaultValueLocalizedStringCommand.swift ├── LocalizedStringShortcut ├── AppDelegate.swift ├── Assets.xcassets │ └── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── translate_128@1x.png │ │ ├── translate_128@2x.png │ │ ├── translate_16@1x.png │ │ ├── translate_16@2x.png │ │ ├── translate_256@1x.png │ │ ├── translate_256@2x.png │ │ ├── translate_32@1x.png │ │ ├── translate_32@2x.png │ │ ├── translate_512@1x.png │ │ └── translate_512@2x.png ├── Base.lproj │ └── MainMenu.xib └── Info.plist ├── README.md └── images ├── LocalizedStringObjectiveC.gif ├── LocalizedStringShortcutApp01.png ├── LocalizedStringShortcutApp02.png ├── LocalizedStringShortcutApp03.png ├── LocalizedStringShortcutApp04.png └── LocalizedStringSwift.gif /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xcuserstate 23 | .DS_Store 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | ## Playgrounds 32 | timeline.xctimeline 33 | playground.xcworkspace 34 | 35 | # Swift Package Manager 36 | 37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 38 | Packages/ 39 | .build/ 40 | 41 | # CocoaPods 42 | 43 | # We recommend against adding the Pods directory to your .gitignore. However 44 | # you should judge for yourself, the pros and cons are mentioned at: 45 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 46 | 47 | Pods/ 48 | 49 | # Carthage 50 | 51 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 52 | Carthage/Checkouts 53 | 54 | Carthage/Build 55 | 56 | # fastlane 57 | 58 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 59 | # screenshots whenever they are needed. 60 | # For more information about the recommended setup visit: 61 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 62 | 63 | fastlane/report.xml 64 | fastlane/Preview.html 65 | fastlane/screenshots 66 | fastlane/test_output 67 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Mateus Gustavo de Freitas e Silva 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Localized String Shortcut.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | CB5ED10E1DEC6C72000FB4A4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB5ED10D1DEC6C72000FB4A4 /* AppDelegate.swift */; }; 11 | CB5ED1101DEC6C73000FB4A4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CB5ED10F1DEC6C73000FB4A4 /* Assets.xcassets */; }; 12 | CB5ED1131DEC6C73000FB4A4 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = CB5ED1111DEC6C73000FB4A4 /* MainMenu.xib */; }; 13 | CB5ED1211DEC6CDD000FB4A4 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CB5ED1201DEC6CDD000FB4A4 /* Cocoa.framework */; }; 14 | CB5ED1261DEC6CDD000FB4A4 /* SourceEditorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB5ED1251DEC6CDD000FB4A4 /* SourceEditorExtension.swift */; }; 15 | CB5ED12C1DEC6CDD000FB4A4 /* LocalizedString.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = CB5ED11E1DEC6CDD000FB4A4 /* LocalizedString.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 16 | CB5ED1381DEC6DC1000FB4A4 /* BaseSourceEditorCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB5ED1311DEC6DC1000FB4A4 /* BaseSourceEditorCommand.swift */; }; 17 | CB5ED1391DEC6DC1000FB4A4 /* BundleLocalizedStringCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB5ED1321DEC6DC1000FB4A4 /* BundleLocalizedStringCommand.swift */; }; 18 | CB5ED13A1DEC6DC1000FB4A4 /* CompleteLocalizedStringCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB5ED1331DEC6DC1000FB4A4 /* CompleteLocalizedStringCommand.swift */; }; 19 | CB5ED13B1DEC6DC1000FB4A4 /* MinimumLocalizedStringCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB5ED1341DEC6DC1000FB4A4 /* MinimumLocalizedStringCommand.swift */; }; 20 | CB5ED13C1DEC6DC1000FB4A4 /* SimpleLocalizedStringCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB5ED1351DEC6DC1000FB4A4 /* SimpleLocalizedStringCommand.swift */; }; 21 | CB5ED13D1DEC6DC1000FB4A4 /* TableLocalizedStringCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB5ED1361DEC6DC1000FB4A4 /* TableLocalizedStringCommand.swift */; }; 22 | CB5ED13E1DEC6DC1000FB4A4 /* WithDefaultValueLocalizedStringCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB5ED1371DEC6DC1000FB4A4 /* WithDefaultValueLocalizedStringCommand.swift */; }; 23 | /* End PBXBuildFile section */ 24 | 25 | /* Begin PBXContainerItemProxy section */ 26 | CB5ED12A1DEC6CDD000FB4A4 /* PBXContainerItemProxy */ = { 27 | isa = PBXContainerItemProxy; 28 | containerPortal = CB5ED1021DEC6C72000FB4A4 /* Project object */; 29 | proxyType = 1; 30 | remoteGlobalIDString = CB5ED11D1DEC6CDD000FB4A4; 31 | remoteInfo = LocalizedString; 32 | }; 33 | /* End PBXContainerItemProxy section */ 34 | 35 | /* Begin PBXCopyFilesBuildPhase section */ 36 | CB5ED1301DEC6CDD000FB4A4 /* Embed App Extensions */ = { 37 | isa = PBXCopyFilesBuildPhase; 38 | buildActionMask = 2147483647; 39 | dstPath = ""; 40 | dstSubfolderSpec = 13; 41 | files = ( 42 | CB5ED12C1DEC6CDD000FB4A4 /* LocalizedString.appex in Embed App Extensions */, 43 | ); 44 | name = "Embed App Extensions"; 45 | runOnlyForDeploymentPostprocessing = 0; 46 | }; 47 | /* End PBXCopyFilesBuildPhase section */ 48 | 49 | /* Begin PBXFileReference section */ 50 | CB5ED10A1DEC6C72000FB4A4 /* Localized String Shortcut.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Localized String Shortcut.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 51 | CB5ED10D1DEC6C72000FB4A4 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 52 | CB5ED10F1DEC6C73000FB4A4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 53 | CB5ED1121DEC6C73000FB4A4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 54 | CB5ED1141DEC6C73000FB4A4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 55 | CB5ED11E1DEC6CDD000FB4A4 /* LocalizedString.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = LocalizedString.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 56 | CB5ED1201DEC6CDD000FB4A4 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 57 | CB5ED1241DEC6CDD000FB4A4 /* LocalizedString.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = LocalizedString.entitlements; sourceTree = ""; }; 58 | CB5ED1251DEC6CDD000FB4A4 /* SourceEditorExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceEditorExtension.swift; sourceTree = ""; }; 59 | CB5ED1291DEC6CDD000FB4A4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 60 | CB5ED1311DEC6DC1000FB4A4 /* BaseSourceEditorCommand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseSourceEditorCommand.swift; sourceTree = ""; }; 61 | CB5ED1321DEC6DC1000FB4A4 /* BundleLocalizedStringCommand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BundleLocalizedStringCommand.swift; sourceTree = ""; }; 62 | CB5ED1331DEC6DC1000FB4A4 /* CompleteLocalizedStringCommand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CompleteLocalizedStringCommand.swift; sourceTree = ""; }; 63 | CB5ED1341DEC6DC1000FB4A4 /* MinimumLocalizedStringCommand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MinimumLocalizedStringCommand.swift; sourceTree = ""; }; 64 | CB5ED1351DEC6DC1000FB4A4 /* SimpleLocalizedStringCommand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SimpleLocalizedStringCommand.swift; sourceTree = ""; }; 65 | CB5ED1361DEC6DC1000FB4A4 /* TableLocalizedStringCommand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableLocalizedStringCommand.swift; sourceTree = ""; }; 66 | CB5ED1371DEC6DC1000FB4A4 /* WithDefaultValueLocalizedStringCommand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WithDefaultValueLocalizedStringCommand.swift; sourceTree = ""; }; 67 | /* End PBXFileReference section */ 68 | 69 | /* Begin PBXFrameworksBuildPhase section */ 70 | CB5ED1071DEC6C72000FB4A4 /* Frameworks */ = { 71 | isa = PBXFrameworksBuildPhase; 72 | buildActionMask = 2147483647; 73 | files = ( 74 | ); 75 | runOnlyForDeploymentPostprocessing = 0; 76 | }; 77 | CB5ED11B1DEC6CDD000FB4A4 /* Frameworks */ = { 78 | isa = PBXFrameworksBuildPhase; 79 | buildActionMask = 2147483647; 80 | files = ( 81 | CB5ED1211DEC6CDD000FB4A4 /* Cocoa.framework in Frameworks */, 82 | ); 83 | runOnlyForDeploymentPostprocessing = 0; 84 | }; 85 | /* End PBXFrameworksBuildPhase section */ 86 | 87 | /* Begin PBXGroup section */ 88 | CB5ED1011DEC6C72000FB4A4 = { 89 | isa = PBXGroup; 90 | children = ( 91 | CB5ED10C1DEC6C72000FB4A4 /* LocalizedStringShortcut */, 92 | CB5ED1221DEC6CDD000FB4A4 /* LocalizedString */, 93 | CB5ED11F1DEC6CDD000FB4A4 /* Frameworks */, 94 | CB5ED10B1DEC6C72000FB4A4 /* Products */, 95 | ); 96 | sourceTree = ""; 97 | }; 98 | CB5ED10B1DEC6C72000FB4A4 /* Products */ = { 99 | isa = PBXGroup; 100 | children = ( 101 | CB5ED10A1DEC6C72000FB4A4 /* Localized String Shortcut.app */, 102 | CB5ED11E1DEC6CDD000FB4A4 /* LocalizedString.appex */, 103 | ); 104 | name = Products; 105 | sourceTree = ""; 106 | }; 107 | CB5ED10C1DEC6C72000FB4A4 /* LocalizedStringShortcut */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | CB5ED1141DEC6C73000FB4A4 /* Info.plist */, 111 | CB5ED10D1DEC6C72000FB4A4 /* AppDelegate.swift */, 112 | CB5ED10F1DEC6C73000FB4A4 /* Assets.xcassets */, 113 | CB5ED1111DEC6C73000FB4A4 /* MainMenu.xib */, 114 | ); 115 | path = LocalizedStringShortcut; 116 | sourceTree = ""; 117 | }; 118 | CB5ED11F1DEC6CDD000FB4A4 /* Frameworks */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | CB5ED1201DEC6CDD000FB4A4 /* Cocoa.framework */, 122 | ); 123 | name = Frameworks; 124 | sourceTree = ""; 125 | }; 126 | CB5ED1221DEC6CDD000FB4A4 /* LocalizedString */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | CB5ED1291DEC6CDD000FB4A4 /* Info.plist */, 130 | CB5ED1251DEC6CDD000FB4A4 /* SourceEditorExtension.swift */, 131 | CB5ED13F1DEC6DC8000FB4A4 /* Commands */, 132 | CB5ED1231DEC6CDD000FB4A4 /* Supporting Files */, 133 | ); 134 | path = LocalizedString; 135 | sourceTree = ""; 136 | }; 137 | CB5ED1231DEC6CDD000FB4A4 /* Supporting Files */ = { 138 | isa = PBXGroup; 139 | children = ( 140 | CB5ED1241DEC6CDD000FB4A4 /* LocalizedString.entitlements */, 141 | ); 142 | name = "Supporting Files"; 143 | sourceTree = ""; 144 | }; 145 | CB5ED13F1DEC6DC8000FB4A4 /* Commands */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | CB5ED1321DEC6DC1000FB4A4 /* BundleLocalizedStringCommand.swift */, 149 | CB5ED1331DEC6DC1000FB4A4 /* CompleteLocalizedStringCommand.swift */, 150 | CB5ED1341DEC6DC1000FB4A4 /* MinimumLocalizedStringCommand.swift */, 151 | CB5ED1351DEC6DC1000FB4A4 /* SimpleLocalizedStringCommand.swift */, 152 | CB5ED1361DEC6DC1000FB4A4 /* TableLocalizedStringCommand.swift */, 153 | CB5ED1371DEC6DC1000FB4A4 /* WithDefaultValueLocalizedStringCommand.swift */, 154 | CB5ED1401DEC6DD6000FB4A4 /* Base */, 155 | ); 156 | name = Commands; 157 | sourceTree = ""; 158 | }; 159 | CB5ED1401DEC6DD6000FB4A4 /* Base */ = { 160 | isa = PBXGroup; 161 | children = ( 162 | CB5ED1311DEC6DC1000FB4A4 /* BaseSourceEditorCommand.swift */, 163 | ); 164 | name = Base; 165 | sourceTree = ""; 166 | }; 167 | /* End PBXGroup section */ 168 | 169 | /* Begin PBXNativeTarget section */ 170 | CB5ED1091DEC6C72000FB4A4 /* Localized String Shortcut */ = { 171 | isa = PBXNativeTarget; 172 | buildConfigurationList = CB5ED1171DEC6C73000FB4A4 /* Build configuration list for PBXNativeTarget "Localized String Shortcut" */; 173 | buildPhases = ( 174 | CB5ED1061DEC6C72000FB4A4 /* Sources */, 175 | CB5ED1071DEC6C72000FB4A4 /* Frameworks */, 176 | CB5ED1081DEC6C72000FB4A4 /* Resources */, 177 | CB5ED1301DEC6CDD000FB4A4 /* Embed App Extensions */, 178 | ); 179 | buildRules = ( 180 | ); 181 | dependencies = ( 182 | CB5ED12B1DEC6CDD000FB4A4 /* PBXTargetDependency */, 183 | ); 184 | name = "Localized String Shortcut"; 185 | productName = LocalizedStringShortcut; 186 | productReference = CB5ED10A1DEC6C72000FB4A4 /* Localized String Shortcut.app */; 187 | productType = "com.apple.product-type.application"; 188 | }; 189 | CB5ED11D1DEC6CDD000FB4A4 /* LocalizedString */ = { 190 | isa = PBXNativeTarget; 191 | buildConfigurationList = CB5ED12D1DEC6CDD000FB4A4 /* Build configuration list for PBXNativeTarget "LocalizedString" */; 192 | buildPhases = ( 193 | CB5ED11A1DEC6CDD000FB4A4 /* Sources */, 194 | CB5ED11B1DEC6CDD000FB4A4 /* Frameworks */, 195 | CB5ED11C1DEC6CDD000FB4A4 /* Resources */, 196 | ); 197 | buildRules = ( 198 | ); 199 | dependencies = ( 200 | ); 201 | name = LocalizedString; 202 | productName = LocalizedString; 203 | productReference = CB5ED11E1DEC6CDD000FB4A4 /* LocalizedString.appex */; 204 | productType = "com.apple.product-type.xcode-extension"; 205 | }; 206 | /* End PBXNativeTarget section */ 207 | 208 | /* Begin PBXProject section */ 209 | CB5ED1021DEC6C72000FB4A4 /* Project object */ = { 210 | isa = PBXProject; 211 | attributes = { 212 | LastSwiftUpdateCheck = 0810; 213 | LastUpgradeCheck = 0810; 214 | ORGANIZATIONNAME = "Mateus Gustavo de Freitas e Silva"; 215 | TargetAttributes = { 216 | CB5ED1091DEC6C72000FB4A4 = { 217 | CreatedOnToolsVersion = 8.1; 218 | DevelopmentTeam = DJUND43ZC7; 219 | ProvisioningStyle = Automatic; 220 | }; 221 | CB5ED11D1DEC6CDD000FB4A4 = { 222 | CreatedOnToolsVersion = 8.1; 223 | DevelopmentTeam = DJUND43ZC7; 224 | ProvisioningStyle = Automatic; 225 | }; 226 | }; 227 | }; 228 | buildConfigurationList = CB5ED1051DEC6C72000FB4A4 /* Build configuration list for PBXProject "Localized String Shortcut" */; 229 | compatibilityVersion = "Xcode 3.2"; 230 | developmentRegion = English; 231 | hasScannedForEncodings = 0; 232 | knownRegions = ( 233 | en, 234 | Base, 235 | ); 236 | mainGroup = CB5ED1011DEC6C72000FB4A4; 237 | productRefGroup = CB5ED10B1DEC6C72000FB4A4 /* Products */; 238 | projectDirPath = ""; 239 | projectRoot = ""; 240 | targets = ( 241 | CB5ED1091DEC6C72000FB4A4 /* Localized String Shortcut */, 242 | CB5ED11D1DEC6CDD000FB4A4 /* LocalizedString */, 243 | ); 244 | }; 245 | /* End PBXProject section */ 246 | 247 | /* Begin PBXResourcesBuildPhase section */ 248 | CB5ED1081DEC6C72000FB4A4 /* Resources */ = { 249 | isa = PBXResourcesBuildPhase; 250 | buildActionMask = 2147483647; 251 | files = ( 252 | CB5ED1101DEC6C73000FB4A4 /* Assets.xcassets in Resources */, 253 | CB5ED1131DEC6C73000FB4A4 /* MainMenu.xib in Resources */, 254 | ); 255 | runOnlyForDeploymentPostprocessing = 0; 256 | }; 257 | CB5ED11C1DEC6CDD000FB4A4 /* Resources */ = { 258 | isa = PBXResourcesBuildPhase; 259 | buildActionMask = 2147483647; 260 | files = ( 261 | ); 262 | runOnlyForDeploymentPostprocessing = 0; 263 | }; 264 | /* End PBXResourcesBuildPhase section */ 265 | 266 | /* Begin PBXSourcesBuildPhase section */ 267 | CB5ED1061DEC6C72000FB4A4 /* Sources */ = { 268 | isa = PBXSourcesBuildPhase; 269 | buildActionMask = 2147483647; 270 | files = ( 271 | CB5ED10E1DEC6C72000FB4A4 /* AppDelegate.swift in Sources */, 272 | ); 273 | runOnlyForDeploymentPostprocessing = 0; 274 | }; 275 | CB5ED11A1DEC6CDD000FB4A4 /* Sources */ = { 276 | isa = PBXSourcesBuildPhase; 277 | buildActionMask = 2147483647; 278 | files = ( 279 | CB5ED13D1DEC6DC1000FB4A4 /* TableLocalizedStringCommand.swift in Sources */, 280 | CB5ED1391DEC6DC1000FB4A4 /* BundleLocalizedStringCommand.swift in Sources */, 281 | CB5ED13E1DEC6DC1000FB4A4 /* WithDefaultValueLocalizedStringCommand.swift in Sources */, 282 | CB5ED13A1DEC6DC1000FB4A4 /* CompleteLocalizedStringCommand.swift in Sources */, 283 | CB5ED1381DEC6DC1000FB4A4 /* BaseSourceEditorCommand.swift in Sources */, 284 | CB5ED13B1DEC6DC1000FB4A4 /* MinimumLocalizedStringCommand.swift in Sources */, 285 | CB5ED13C1DEC6DC1000FB4A4 /* SimpleLocalizedStringCommand.swift in Sources */, 286 | CB5ED1261DEC6CDD000FB4A4 /* SourceEditorExtension.swift in Sources */, 287 | ); 288 | runOnlyForDeploymentPostprocessing = 0; 289 | }; 290 | /* End PBXSourcesBuildPhase section */ 291 | 292 | /* Begin PBXTargetDependency section */ 293 | CB5ED12B1DEC6CDD000FB4A4 /* PBXTargetDependency */ = { 294 | isa = PBXTargetDependency; 295 | target = CB5ED11D1DEC6CDD000FB4A4 /* LocalizedString */; 296 | targetProxy = CB5ED12A1DEC6CDD000FB4A4 /* PBXContainerItemProxy */; 297 | }; 298 | /* End PBXTargetDependency section */ 299 | 300 | /* Begin PBXVariantGroup section */ 301 | CB5ED1111DEC6C73000FB4A4 /* MainMenu.xib */ = { 302 | isa = PBXVariantGroup; 303 | children = ( 304 | CB5ED1121DEC6C73000FB4A4 /* Base */, 305 | ); 306 | name = MainMenu.xib; 307 | sourceTree = ""; 308 | }; 309 | /* End PBXVariantGroup section */ 310 | 311 | /* Begin XCBuildConfiguration section */ 312 | CB5ED1151DEC6C73000FB4A4 /* Debug */ = { 313 | isa = XCBuildConfiguration; 314 | buildSettings = { 315 | ALWAYS_SEARCH_USER_PATHS = NO; 316 | CLANG_ANALYZER_NONNULL = YES; 317 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 318 | CLANG_CXX_LIBRARY = "libc++"; 319 | CLANG_ENABLE_MODULES = YES; 320 | CLANG_ENABLE_OBJC_ARC = YES; 321 | CLANG_WARN_BOOL_CONVERSION = YES; 322 | CLANG_WARN_CONSTANT_CONVERSION = YES; 323 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 324 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 325 | CLANG_WARN_EMPTY_BODY = YES; 326 | CLANG_WARN_ENUM_CONVERSION = YES; 327 | CLANG_WARN_INFINITE_RECURSION = YES; 328 | CLANG_WARN_INT_CONVERSION = YES; 329 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 330 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 331 | CLANG_WARN_UNREACHABLE_CODE = YES; 332 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 333 | CODE_SIGN_IDENTITY = "-"; 334 | COPY_PHASE_STRIP = NO; 335 | CURRENT_PROJECT_VERSION = 1; 336 | DEBUG_INFORMATION_FORMAT = dwarf; 337 | ENABLE_STRICT_OBJC_MSGSEND = YES; 338 | ENABLE_TESTABILITY = YES; 339 | GCC_C_LANGUAGE_STANDARD = gnu99; 340 | GCC_DYNAMIC_NO_PIC = NO; 341 | GCC_NO_COMMON_BLOCKS = YES; 342 | GCC_OPTIMIZATION_LEVEL = 0; 343 | GCC_PREPROCESSOR_DEFINITIONS = ( 344 | "DEBUG=1", 345 | "$(inherited)", 346 | ); 347 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 348 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 349 | GCC_WARN_UNDECLARED_SELECTOR = YES; 350 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 351 | GCC_WARN_UNUSED_FUNCTION = YES; 352 | GCC_WARN_UNUSED_VARIABLE = YES; 353 | MACOSX_DEPLOYMENT_TARGET = 10.12; 354 | MTL_ENABLE_DEBUG_INFO = YES; 355 | ONLY_ACTIVE_ARCH = YES; 356 | SDKROOT = macosx; 357 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 358 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 359 | VERSIONING_SYSTEM = "apple-generic"; 360 | }; 361 | name = Debug; 362 | }; 363 | CB5ED1161DEC6C73000FB4A4 /* Release */ = { 364 | isa = XCBuildConfiguration; 365 | buildSettings = { 366 | ALWAYS_SEARCH_USER_PATHS = NO; 367 | CLANG_ANALYZER_NONNULL = YES; 368 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 369 | CLANG_CXX_LIBRARY = "libc++"; 370 | CLANG_ENABLE_MODULES = YES; 371 | CLANG_ENABLE_OBJC_ARC = YES; 372 | CLANG_WARN_BOOL_CONVERSION = YES; 373 | CLANG_WARN_CONSTANT_CONVERSION = YES; 374 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 375 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 376 | CLANG_WARN_EMPTY_BODY = YES; 377 | CLANG_WARN_ENUM_CONVERSION = YES; 378 | CLANG_WARN_INFINITE_RECURSION = YES; 379 | CLANG_WARN_INT_CONVERSION = YES; 380 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 381 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 382 | CLANG_WARN_UNREACHABLE_CODE = YES; 383 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 384 | CODE_SIGN_IDENTITY = "-"; 385 | COPY_PHASE_STRIP = NO; 386 | CURRENT_PROJECT_VERSION = 1; 387 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 388 | ENABLE_NS_ASSERTIONS = NO; 389 | ENABLE_STRICT_OBJC_MSGSEND = YES; 390 | GCC_C_LANGUAGE_STANDARD = gnu99; 391 | GCC_NO_COMMON_BLOCKS = YES; 392 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 393 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 394 | GCC_WARN_UNDECLARED_SELECTOR = YES; 395 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 396 | GCC_WARN_UNUSED_FUNCTION = YES; 397 | GCC_WARN_UNUSED_VARIABLE = YES; 398 | MACOSX_DEPLOYMENT_TARGET = 10.12; 399 | MTL_ENABLE_DEBUG_INFO = NO; 400 | SDKROOT = macosx; 401 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 402 | VERSIONING_SYSTEM = "apple-generic"; 403 | }; 404 | name = Release; 405 | }; 406 | CB5ED1181DEC6C73000FB4A4 /* Debug */ = { 407 | isa = XCBuildConfiguration; 408 | buildSettings = { 409 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 410 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 411 | CODE_SIGN_IDENTITY = "Mac Developer"; 412 | COMBINE_HIDPI_IMAGES = YES; 413 | DEVELOPMENT_TEAM = DJUND43ZC7; 414 | INFOPLIST_FILE = LocalizedStringShortcut/Info.plist; 415 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 416 | PRODUCT_BUNDLE_IDENTIFIER = com.mateusfsilva.LocalizedStringShortcut; 417 | PRODUCT_NAME = "$(TARGET_NAME)"; 418 | SWIFT_VERSION = 3.0; 419 | }; 420 | name = Debug; 421 | }; 422 | CB5ED1191DEC6C73000FB4A4 /* Release */ = { 423 | isa = XCBuildConfiguration; 424 | buildSettings = { 425 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 426 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 427 | CODE_SIGN_IDENTITY = "Mac Developer"; 428 | COMBINE_HIDPI_IMAGES = YES; 429 | DEVELOPMENT_TEAM = DJUND43ZC7; 430 | INFOPLIST_FILE = LocalizedStringShortcut/Info.plist; 431 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 432 | PRODUCT_BUNDLE_IDENTIFIER = com.mateusfsilva.LocalizedStringShortcut; 433 | PRODUCT_NAME = "$(TARGET_NAME)"; 434 | SWIFT_VERSION = 3.0; 435 | }; 436 | name = Release; 437 | }; 438 | CB5ED12E1DEC6CDD000FB4A4 /* Debug */ = { 439 | isa = XCBuildConfiguration; 440 | buildSettings = { 441 | CODE_SIGN_ENTITLEMENTS = LocalizedString/LocalizedString.entitlements; 442 | CODE_SIGN_IDENTITY = "Mac Developer"; 443 | COMBINE_HIDPI_IMAGES = YES; 444 | CURRENT_PROJECT_VERSION = 1; 445 | DEVELOPMENT_TEAM = DJUND43ZC7; 446 | INFOPLIST_FILE = LocalizedString/Info.plist; 447 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; 448 | MACOSX_DEPLOYMENT_TARGET = 10.11; 449 | PRODUCT_BUNDLE_IDENTIFIER = com.mateusfsilva.LocalizedStringShortcut.LocalizedString; 450 | PRODUCT_NAME = "$(TARGET_NAME)"; 451 | SKIP_INSTALL = YES; 452 | SWIFT_VERSION = 3.0; 453 | VERSIONING_SYSTEM = "apple-generic"; 454 | }; 455 | name = Debug; 456 | }; 457 | CB5ED12F1DEC6CDD000FB4A4 /* Release */ = { 458 | isa = XCBuildConfiguration; 459 | buildSettings = { 460 | CODE_SIGN_ENTITLEMENTS = LocalizedString/LocalizedString.entitlements; 461 | CODE_SIGN_IDENTITY = "Mac Developer"; 462 | COMBINE_HIDPI_IMAGES = YES; 463 | CURRENT_PROJECT_VERSION = 1; 464 | DEVELOPMENT_TEAM = DJUND43ZC7; 465 | INFOPLIST_FILE = LocalizedString/Info.plist; 466 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks"; 467 | MACOSX_DEPLOYMENT_TARGET = 10.11; 468 | PRODUCT_BUNDLE_IDENTIFIER = com.mateusfsilva.LocalizedStringShortcut.LocalizedString; 469 | PRODUCT_NAME = "$(TARGET_NAME)"; 470 | SKIP_INSTALL = YES; 471 | SWIFT_VERSION = 3.0; 472 | VERSIONING_SYSTEM = "apple-generic"; 473 | }; 474 | name = Release; 475 | }; 476 | /* End XCBuildConfiguration section */ 477 | 478 | /* Begin XCConfigurationList section */ 479 | CB5ED1051DEC6C72000FB4A4 /* Build configuration list for PBXProject "Localized String Shortcut" */ = { 480 | isa = XCConfigurationList; 481 | buildConfigurations = ( 482 | CB5ED1151DEC6C73000FB4A4 /* Debug */, 483 | CB5ED1161DEC6C73000FB4A4 /* Release */, 484 | ); 485 | defaultConfigurationIsVisible = 0; 486 | defaultConfigurationName = Release; 487 | }; 488 | CB5ED1171DEC6C73000FB4A4 /* Build configuration list for PBXNativeTarget "Localized String Shortcut" */ = { 489 | isa = XCConfigurationList; 490 | buildConfigurations = ( 491 | CB5ED1181DEC6C73000FB4A4 /* Debug */, 492 | CB5ED1191DEC6C73000FB4A4 /* Release */, 493 | ); 494 | defaultConfigurationIsVisible = 0; 495 | }; 496 | CB5ED12D1DEC6CDD000FB4A4 /* Build configuration list for PBXNativeTarget "LocalizedString" */ = { 497 | isa = XCConfigurationList; 498 | buildConfigurations = ( 499 | CB5ED12E1DEC6CDD000FB4A4 /* Debug */, 500 | CB5ED12F1DEC6CDD000FB4A4 /* Release */, 501 | ); 502 | defaultConfigurationIsVisible = 0; 503 | }; 504 | /* End XCConfigurationList section */ 505 | }; 506 | rootObject = CB5ED1021DEC6C72000FB4A4 /* Project object */; 507 | } 508 | -------------------------------------------------------------------------------- /Localized String Shortcut.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LocalizedString/BaseSourceEditorCommand.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BaseSourceEditorCommand.swift 3 | // Localized String Shortcut 4 | // 5 | // Created by Mateus Gustavo de Freitas e Silva on 26/11/16. 6 | // Copyright © 2016 Mateus Gustavo de Freitas e Silva. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | // SOFTWARE. 25 | // 26 | 27 | import XcodeKit 28 | import Foundation 29 | 30 | class BaseSourceEditorCommand: NSObject { 31 | struct LineAdjust { 32 | var line = -1 33 | var columns = 0 34 | } 35 | 36 | /// The NSLocalizedString format options 37 | /// 38 | /// - SwiftMinimumLocalizedString: NSLocalizedString(value, comment: "") 39 | /// - SwiftSimpleLocalizedString: NSLocalizedString(value, comment: comment) 40 | /// - SwiftCompleteLocalizedString: NSLocalizedString(key, value: value, comment: comment) 41 | /// - SwiftBundleLocalizedString: NSLocalizedString(key, tableName: tableName, bundle: bundle, value: value, comment: comment) 42 | /// - ObjectiveCMinimumLocalizedString: NSLocalizedString(key, nil) 43 | /// - ObjectiveCSimpleLocalizedString: NSLocalizedString(key, comment) 44 | /// - ObjectiveCTableLocalizedString: NSLocalizedStringFromTable(key, tableName, comment) 45 | /// - ObjectiveCBundleLocalizedString: NSLocalizedStringFromTableInBundle(\(originalString), tableName, bundle, comment) 46 | /// - ObjectiveCWithDefaultLocalizedString: NSLocalizedStringWithDefaultValue(\(originalString), tableName, bundle, value, comment) 47 | enum CommandFormat { 48 | case SwiftMinimumLocalizedString 49 | case SwiftSimpleLocalizedString 50 | case SwiftCompleteLocalizedString 51 | case SwiftBundleLocalizedString 52 | case ObjectiveCMinimumLocalizedString 53 | case ObjectiveCSimpleLocalizedString 54 | case ObjectiveCTableLocalizedString 55 | case ObjectiveCBundleLocalizedString 56 | case ObjectiveCWithDefaultLocalizedString 57 | } 58 | 59 | let SWIFT_SOURCE = "public.swift-source" 60 | let OBJECTIVEC_SOURCE = "public.objective-c-source" 61 | let HEADER_FILE = "public.c-header" 62 | 63 | var updatedSelections = [XCSourceTextRange]() 64 | var lineAdjust = LineAdjust() 65 | 66 | /// Replace the selected strings in source file with NSLocalizedString function 67 | /// 68 | /// - Parameters: 69 | /// - buffer: The string buffer 70 | /// - format: The NSLocalizedString format 71 | func localizedString(in buffer: XCSourceTextBuffer, with format: CommandFormat) { 72 | for selected in buffer.selections { 73 | if let selectedRange = selected as? XCSourceTextRange { 74 | // If nothing is selected, exit 75 | if selectedRange.start.column == selectedRange.end.column && selectedRange.start.line == selectedRange.end.line { 76 | return 77 | } 78 | 79 | // Adjusts the selection to add the previous changes 80 | if selectedRange.start.line == lineAdjust.line { 81 | selectedRange.start.column = selectedRange.start.column + lineAdjust.columns 82 | selectedRange.end.column = selectedRange.end.column + lineAdjust.columns 83 | } 84 | 85 | // Gets the original string 86 | var originalString = text(inRange: selectedRange, inBuffer: buffer) 87 | 88 | // Makes the new string 89 | var newString = "" 90 | var newStringLength = 0 91 | var originalStringLength = 0 92 | 93 | // If is the end of line adds line break in new text 94 | if originalString.substring(from: originalString.index(before: originalString.endIndex)) == "\n" { 95 | newString = "\n" 96 | newStringLength = -1 97 | } 98 | 99 | originalString = originalString.substring(to: originalString.index(before: originalString.endIndex)) 100 | 101 | originalStringLength = originalStringLength + originalString.characters.count 102 | 103 | // Updates the new string 104 | switch format { 105 | case .SwiftMinimumLocalizedString: newString = "NSLocalizedString(\(originalString), comment: \"\")" + newString 106 | case .SwiftSimpleLocalizedString: newString = "NSLocalizedString(\(originalString), comment: <#comment#>)" + newString 107 | case .SwiftCompleteLocalizedString: newString = "NSLocalizedString(<#key#>, value: \(originalString), comment: <#comment#>)" + newString 108 | case .SwiftBundleLocalizedString: newString = "NSLocalizedString(<#key#>, tableName: <#tableName#>, bundle: <#bundle#>, value: \(originalString), comment: <#comment#>)" + newString 109 | case .ObjectiveCMinimumLocalizedString: newString = "NSLocalizedString(\(originalString), nil)" + newString 110 | case .ObjectiveCSimpleLocalizedString: newString = "NSLocalizedString(\(originalString), <#comment#>)" + newString 111 | case .ObjectiveCTableLocalizedString: newString = "NSLocalizedStringFromTable(\(originalString), <#tableName#>, <#comment#>)" + newString 112 | case .ObjectiveCBundleLocalizedString: newString = "NSLocalizedStringFromTableInBundle(\(originalString), <#tableName#>, <#bundle#>, <#comment#>)" + newString 113 | case .ObjectiveCWithDefaultLocalizedString: newString = "NSLocalizedStringWithDefaultValue(<#key#>, <#tableName#>, <#bundle#>, \(originalString), <#comment#>)" + newString 114 | } 115 | 116 | newStringLength = newStringLength + newString.characters.count 117 | 118 | // Replaces the old text with the new text 119 | replace(position: selectedRange.start, length: originalStringLength, with: newString, inBuffer: buffer) 120 | 121 | // Stores the position of the new text 122 | let selection = XCSourceTextRange() 123 | selection.start = selectedRange.start 124 | selection.end = XCSourceTextPosition(line: selectedRange.end.line, column: selectedRange.start.column + newStringLength) 125 | updatedSelections.append(selection) 126 | 127 | // Updates the line adjust 128 | if selectedRange.start.line != lineAdjust.line { 129 | lineAdjust.line = selectedRange.start.line 130 | lineAdjust.columns = 0 131 | } 132 | 133 | lineAdjust.columns = lineAdjust.columns + newString.characters.count - originalStringLength 134 | } 135 | } 136 | 137 | buffer.selections.setArray(updatedSelections) 138 | } 139 | 140 | /// Returns a text in given position on buffer 141 | /// 142 | /// - Parameters: 143 | /// - textRange: The position of the text to be returned 144 | /// - buffer: The string buffer 145 | /// - Returns: The found text 146 | func text(inRange textRange: XCSourceTextRange, inBuffer buffer: XCSourceTextBuffer) -> String { 147 | if textRange.start.line == textRange.end.line { 148 | let lineText = buffer.lines[textRange.start.line] as! String 149 | let from = lineText.index(lineText.startIndex, offsetBy: textRange.start.column) 150 | let to = lineText.index(lineText.startIndex, offsetBy: textRange.end.column) 151 | 152 | return lineText[from...to] 153 | } 154 | 155 | var text = "" 156 | 157 | for aLine in textRange.start.line...textRange.end.line { 158 | let lineText = buffer.lines[aLine] as! String 159 | 160 | switch aLine { 161 | case textRange.start.line: text += lineText.substring(from: lineText.index(lineText.startIndex, offsetBy: textRange.start.column)) 162 | case textRange.end.line: text += lineText.substring(to: lineText.index(lineText.startIndex, offsetBy: textRange.end.column + 1)) 163 | default: text += lineText 164 | } 165 | } 166 | 167 | return text 168 | } 169 | 170 | /// Replaces a text in the buffer 171 | /// 172 | /// - Parameters: 173 | /// - position: The position of the text to be replaced 174 | /// - length: The length of the text to be replaced 175 | /// - newElements: The new text 176 | /// - buffer: The string buffer 177 | func replace(position: XCSourceTextPosition, length: Int, with newElements: String, inBuffer buffer: XCSourceTextBuffer) { 178 | var lineText = buffer.lines[position.line] as! String 179 | 180 | var start = lineText.index(lineText.startIndex, offsetBy: position.column) 181 | var end = lineText.index(start, offsetBy: length) 182 | 183 | if length < 0 { 184 | swap(&start, &end) 185 | } 186 | 187 | lineText.replaceSubrange(start.. Void) { 32 | if invocation.buffer.contentUTI == SWIFT_SOURCE { 33 | localizedString(in: invocation.buffer, with: .SwiftBundleLocalizedString) 34 | } else if invocation.buffer.contentUTI == OBJECTIVEC_SOURCE || invocation.buffer.contentUTI == HEADER_FILE { 35 | localizedString(in: invocation.buffer, with: .ObjectiveCBundleLocalizedString) 36 | } 37 | 38 | completionHandler(nil) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /LocalizedString/CompleteLocalizedStringCommand.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CompleteLocalizedStringCommand.swift 3 | // Localized String Shortcut 4 | // 5 | // Created by Mateus Gustavo de Freitas e Silva on 25/11/16. 6 | // Copyright © 2016 Mateus Gustavo de Freitas e Silva. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | // SOFTWARE. 25 | // 26 | 27 | import XcodeKit 28 | import Foundation 29 | 30 | class CompleteLocalizedStringCommand: BaseSourceEditorCommand, XCSourceEditorCommand { 31 | func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void) { 32 | if invocation.buffer.contentUTI == SWIFT_SOURCE { 33 | localizedString(in: invocation.buffer, with: .SwiftCompleteLocalizedString) 34 | } 35 | 36 | completionHandler(nil) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /LocalizedString/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | LocalizedString 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | XPC! 19 | CFBundleShortVersionString 20 | 1.0.0 21 | CFBundleVersion 22 | 1 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSExtension 26 | 27 | NSExtensionAttributes 28 | 29 | XCSourceEditorCommandDefinitions 30 | 31 | 32 | XCSourceEditorCommandClassName 33 | $(PRODUCT_MODULE_NAME).SourceEditorCommand 34 | XCSourceEditorCommandIdentifier 35 | $(PRODUCT_BUNDLE_IDENTIFIER).SourceEditorCommand 36 | XCSourceEditorCommandName 37 | Source Editor Command 38 | 39 | 40 | XCSourceEditorExtensionPrincipalClass 41 | $(PRODUCT_MODULE_NAME).SourceEditorExtension 42 | 43 | NSExtensionPointIdentifier 44 | com.apple.dt.Xcode.extension.source-editor 45 | 46 | NSHumanReadableCopyright 47 | Copyright © 2016 Mateus Gustavo de Freitas e Silva. All rights reserved. 48 | 49 | 50 | -------------------------------------------------------------------------------- /LocalizedString/LocalizedString.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /LocalizedString/MinimumLocalizedStringCommand.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MinimumLocalizedStringCommand.swift 3 | // Localized String Shortcut 4 | // 5 | // Created by Mateus Gustavo de Freitas e Silva on 28/11/16. 6 | // Copyright © 2016 Mateus Gustavo de Freitas e Silva. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | // SOFTWARE. 25 | // 26 | 27 | import XcodeKit 28 | import Foundation 29 | 30 | class MinimumLocalizedStringCommand: BaseSourceEditorCommand, XCSourceEditorCommand { 31 | func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void) { 32 | if invocation.buffer.contentUTI == SWIFT_SOURCE { 33 | localizedString(in: invocation.buffer, with: .SwiftMinimumLocalizedString) 34 | } else if invocation.buffer.contentUTI == OBJECTIVEC_SOURCE || invocation.buffer.contentUTI == HEADER_FILE { 35 | localizedString(in: invocation.buffer, with: .ObjectiveCMinimumLocalizedString) 36 | } 37 | 38 | completionHandler(nil) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /LocalizedString/SimpleLocalizedStringCommand.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SimpleLocalizedStringCommand.swift 3 | // Localized String Shortcut 4 | // 5 | // Created by Mateus Gustavo de Freitas e Silva on 25/11/16. 6 | // Copyright © 2016 Mateus Gustavo de Freitas e Silva. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | // SOFTWARE. 25 | // 26 | 27 | import XcodeKit 28 | import Foundation 29 | 30 | class SimpleLocalizedStringCommand: BaseSourceEditorCommand, XCSourceEditorCommand { 31 | func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void) { 32 | if invocation.buffer.contentUTI == SWIFT_SOURCE { 33 | localizedString(in: invocation.buffer, with: .SwiftSimpleLocalizedString) 34 | } else if invocation.buffer.contentUTI == OBJECTIVEC_SOURCE || invocation.buffer.contentUTI == HEADER_FILE { 35 | localizedString(in: invocation.buffer, with: .ObjectiveCSimpleLocalizedString) 36 | } 37 | 38 | completionHandler(nil) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /LocalizedString/SourceEditorExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SourceEditorExtension.swift 3 | // Action 4 | // 5 | // Created by Mateus Gustavo de Freitas e Silva on 25/11/16. 6 | // Copyright © 2016 Mateus Gustavo de Freitas e Silva. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | // SOFTWARE. 25 | // 26 | 27 | import Foundation 28 | import XcodeKit 29 | 30 | class SourceEditorExtension: NSObject, XCSourceEditorExtension { 31 | func extensionDidFinishLaunching() { 32 | // If your extension needs to do any work at launch, implement this optional method. 33 | } 34 | 35 | var commandDefinitions: [[XCSourceEditorCommandDefinitionKey: Any]] { 36 | let productIdentifier = Bundle.main.infoDictionary![kCFBundleIdentifierKey as String] as! String 37 | 38 | func definitionForClassNamed(_ className: String, commandName: String) -> [XCSourceEditorCommandDefinitionKey: Any] { 39 | return [XCSourceEditorCommandDefinitionKey.identifierKey: productIdentifier + className, 40 | XCSourceEditorCommandDefinitionKey.classNameKey: className, 41 | XCSourceEditorCommandDefinitionKey.nameKey: commandName] 42 | } 43 | 44 | let myDefinitions : [[XCSourceEditorCommandDefinitionKey: Any]] = [ 45 | definitionForClassNamed(MinimumLocalizedStringCommand.className(), commandName: "Get a NSLocalizedString without comment"), 46 | definitionForClassNamed(SimpleLocalizedStringCommand.className(), commandName: "Get a NSLocalizedString with comment"), 47 | definitionForClassNamed(CompleteLocalizedStringCommand.className(), commandName: "Get a NSLocalizedString with key (Swift)"), 48 | definitionForClassNamed(BundleLocalizedStringCommand.className(), commandName: "Get NSLocalizedString with bundle"), 49 | definitionForClassNamed(TableLocalizedStringCommand.className(), commandName: "Get NSLocalizedString with table (Objective-C)"), 50 | definitionForClassNamed(WithDefaultValueLocalizedStringCommand.className(), commandName: "Get a NSLocalizedString with default value (Objective-C"), 51 | ] 52 | 53 | return myDefinitions 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /LocalizedString/TableLocalizedStringCommand.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TableLocalizedStringCommand.swift 3 | // Localized String Shortcut 4 | // 5 | // Created by Mateus Gustavo de Freitas e Silva on 28/11/16. 6 | // Copyright © 2016 Mateus Gustavo de Freitas e Silva. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | // SOFTWARE. 25 | // 26 | 27 | import XcodeKit 28 | import Foundation 29 | 30 | class TableLocalizedStringCommand: BaseSourceEditorCommand, XCSourceEditorCommand { 31 | func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void) { 32 | if invocation.buffer.contentUTI == OBJECTIVEC_SOURCE || invocation.buffer.contentUTI == HEADER_FILE { 33 | localizedString(in: invocation.buffer, with: .ObjectiveCTableLocalizedString) 34 | } 35 | 36 | completionHandler(nil) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /LocalizedString/WithDefaultValueLocalizedStringCommand.swift: -------------------------------------------------------------------------------- 1 | // 2 | // WithDefaultValueLocalizedStringCommand.swift 3 | // Localized String Shortcut 4 | // 5 | // Created by Mateus Gustavo de Freitas e Silva on 28/11/16. 6 | // Copyright © 2016 Mateus Gustavo de Freitas e Silva. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | // SOFTWARE. 25 | // 26 | 27 | import XcodeKit 28 | import Foundation 29 | 30 | class WithDefaultValueLocalizedStringCommand: BaseSourceEditorCommand, XCSourceEditorCommand { 31 | func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void) { 32 | if invocation.buffer.contentUTI == OBJECTIVEC_SOURCE || invocation.buffer.contentUTI == HEADER_FILE { 33 | localizedString(in: invocation.buffer, with: .ObjectiveCWithDefaultLocalizedString) 34 | } 35 | 36 | completionHandler(nil) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /LocalizedStringShortcut/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // LocalizedStringShortcut 4 | // 5 | // Created by Mateus Gustavo de Freitas e Silva on 28/11/16. 6 | // Copyright © 2016 Mateus Gustavo de Freitas e Silva. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in all 16 | // copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | // SOFTWARE. 25 | // 26 | 27 | import Cocoa 28 | 29 | @NSApplicationMain 30 | class AppDelegate: NSObject, NSApplicationDelegate { 31 | @IBOutlet weak var window: NSWindow! 32 | 33 | func applicationDidFinishLaunching(_ aNotification: Notification) { 34 | // Insert code here to initialize your application 35 | } 36 | 37 | func applicationWillTerminate(_ aNotification: Notification) { 38 | // Insert code here to tear down your application 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /LocalizedStringShortcut/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "translate_16@1x.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "translate_16@2x.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "translate_32@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "translate_32@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "translate_128@1x.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "translate_128@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "translate_256@1x.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "translate_256@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "translate_512@1x.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "translate_512@2x.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /LocalizedStringShortcut/Assets.xcassets/AppIcon.appiconset/translate_128@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mateusfsilva/LocalizedString/ad1a58b0004c814c0e71b1d6332d59022eb369e8/LocalizedStringShortcut/Assets.xcassets/AppIcon.appiconset/translate_128@1x.png -------------------------------------------------------------------------------- /LocalizedStringShortcut/Assets.xcassets/AppIcon.appiconset/translate_128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mateusfsilva/LocalizedString/ad1a58b0004c814c0e71b1d6332d59022eb369e8/LocalizedStringShortcut/Assets.xcassets/AppIcon.appiconset/translate_128@2x.png -------------------------------------------------------------------------------- /LocalizedStringShortcut/Assets.xcassets/AppIcon.appiconset/translate_16@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mateusfsilva/LocalizedString/ad1a58b0004c814c0e71b1d6332d59022eb369e8/LocalizedStringShortcut/Assets.xcassets/AppIcon.appiconset/translate_16@1x.png -------------------------------------------------------------------------------- /LocalizedStringShortcut/Assets.xcassets/AppIcon.appiconset/translate_16@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mateusfsilva/LocalizedString/ad1a58b0004c814c0e71b1d6332d59022eb369e8/LocalizedStringShortcut/Assets.xcassets/AppIcon.appiconset/translate_16@2x.png -------------------------------------------------------------------------------- /LocalizedStringShortcut/Assets.xcassets/AppIcon.appiconset/translate_256@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mateusfsilva/LocalizedString/ad1a58b0004c814c0e71b1d6332d59022eb369e8/LocalizedStringShortcut/Assets.xcassets/AppIcon.appiconset/translate_256@1x.png -------------------------------------------------------------------------------- /LocalizedStringShortcut/Assets.xcassets/AppIcon.appiconset/translate_256@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mateusfsilva/LocalizedString/ad1a58b0004c814c0e71b1d6332d59022eb369e8/LocalizedStringShortcut/Assets.xcassets/AppIcon.appiconset/translate_256@2x.png -------------------------------------------------------------------------------- /LocalizedStringShortcut/Assets.xcassets/AppIcon.appiconset/translate_32@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mateusfsilva/LocalizedString/ad1a58b0004c814c0e71b1d6332d59022eb369e8/LocalizedStringShortcut/Assets.xcassets/AppIcon.appiconset/translate_32@1x.png -------------------------------------------------------------------------------- /LocalizedStringShortcut/Assets.xcassets/AppIcon.appiconset/translate_32@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mateusfsilva/LocalizedString/ad1a58b0004c814c0e71b1d6332d59022eb369e8/LocalizedStringShortcut/Assets.xcassets/AppIcon.appiconset/translate_32@2x.png -------------------------------------------------------------------------------- /LocalizedStringShortcut/Assets.xcassets/AppIcon.appiconset/translate_512@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mateusfsilva/LocalizedString/ad1a58b0004c814c0e71b1d6332d59022eb369e8/LocalizedStringShortcut/Assets.xcassets/AppIcon.appiconset/translate_512@1x.png -------------------------------------------------------------------------------- /LocalizedStringShortcut/Assets.xcassets/AppIcon.appiconset/translate_512@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mateusfsilva/LocalizedString/ad1a58b0004c814c0e71b1d6332d59022eb369e8/LocalizedStringShortcut/Assets.xcassets/AppIcon.appiconset/translate_512@2x.png -------------------------------------------------------------------------------- /LocalizedStringShortcut/Base.lproj/MainMenu.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | Default 539 | 540 | 541 | 542 | 543 | 544 | 545 | Left to Right 546 | 547 | 548 | 549 | 550 | 551 | 552 | Right to Left 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | Default 564 | 565 | 566 | 567 | 568 | 569 | 570 | Left to Right 571 | 572 | 573 | 574 | 575 | 576 | 577 | Right to Left 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | -------------------------------------------------------------------------------- /LocalizedStringShortcut/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0.0 21 | CFBundleVersion 22 | 1 23 | LSApplicationCategoryType 24 | public.app-category.developer-tools 25 | LSMinimumSystemVersion 26 | $(MACOSX_DEPLOYMENT_TARGET) 27 | NSHumanReadableCopyright 28 | Copyright © 2016 Mateus Gustavo de Freitas e Silva. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LocalizedString 2 | [![license](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/mateusfsilva/LocalizedString/blob/master/LICENSE) 3 | 4 | Xcode Source Editor Extension that helps to localize Swift and Objective-C source files 5 | 6 | ## Swift Example 7 | 8 | ![LocalizedStringSwift](images/LocalizedStringSwift.gif) 9 | 10 | ## Objective-C Example 11 | 12 | ![LocalizedStringObjectiveC](images/LocalizedStringObjectiveC.gif) 13 | 14 | ## Install on Xcode 8 15 | 16 | 1. Download the [Localized.String.Shortcut.app.zip📎](https://github.com/mateusfsilva/LocalizedString/releases/download/v1.0.0/Localized.String.Shortcut.app.zip) 17 | 2. Open and copy `Localized String Shortcut.app` to `/Applications` folder 18 | 3. Run it then close it. 19 | 20 | ![help-1](images/LocalizedStringShortcutApp01.png) 21 | 22 | ## Usage without installing: 23 | 24 | 1. Install Xcode 8 25 | 2. Run Xcode 8 and install additional system components 26 | 3. Open this project in Xcode 8 and run the extension 27 | 4. Choose an app to run: Xcode 8 28 | 5. Select your code 29 | 6. Choose menu `Editor > LocalizedString` 30 | 31 | ## Usage 32 | 33 | ### 1. Enable LocalizedString 34 | Check System Preferences -> Extensions -> Xocde Source Editor -> LocalizedString 35 | 36 | ![help-2](images/LocalizedStringShortcutApp02.png) 37 | ![help-3](images/LocalizedStringShortcutApp03.png) 38 | 39 | ### 2. Setting Shortcut in Xocde 40 | Preferences -> Key bindings -> Filter: Localized 41 | 42 | ![help-4](images/LocalizedStringShortcutApp04.png) 43 | 44 | ## Author 45 | 46 | Mateus Freitas 47 | 48 | [https://mateusfsilva.com](https://mateusfsilva.com) 49 | 50 | [![Twitter URL](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/mateusfsilva) 51 | 52 | License: 53 | ================= 54 | The MIT License. See the LICENSE file for more infomation. 55 | -------------------------------------------------------------------------------- /images/LocalizedStringObjectiveC.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mateusfsilva/LocalizedString/ad1a58b0004c814c0e71b1d6332d59022eb369e8/images/LocalizedStringObjectiveC.gif -------------------------------------------------------------------------------- /images/LocalizedStringShortcutApp01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mateusfsilva/LocalizedString/ad1a58b0004c814c0e71b1d6332d59022eb369e8/images/LocalizedStringShortcutApp01.png -------------------------------------------------------------------------------- /images/LocalizedStringShortcutApp02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mateusfsilva/LocalizedString/ad1a58b0004c814c0e71b1d6332d59022eb369e8/images/LocalizedStringShortcutApp02.png -------------------------------------------------------------------------------- /images/LocalizedStringShortcutApp03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mateusfsilva/LocalizedString/ad1a58b0004c814c0e71b1d6332d59022eb369e8/images/LocalizedStringShortcutApp03.png -------------------------------------------------------------------------------- /images/LocalizedStringShortcutApp04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mateusfsilva/LocalizedString/ad1a58b0004c814c0e71b1d6332d59022eb369e8/images/LocalizedStringShortcutApp04.png -------------------------------------------------------------------------------- /images/LocalizedStringSwift.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mateusfsilva/LocalizedString/ad1a58b0004c814c0e71b1d6332d59022eb369e8/images/LocalizedStringSwift.gif --------------------------------------------------------------------------------