├── .gitignore ├── .travis.yml ├── AMLocalizedStringBuilder.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ └── AMLocalizedStringBuilder.xcscheme ├── AMLocalizedStringBuilder ├── AMConstString.h ├── AMConstString.m ├── AMLocalizedStringBuilder.h ├── AMLocalizedStringBuilder.m ├── AMMenuGenerator.h ├── AMMenuGenerator.m ├── AutoGenLocalizedString.sh ├── ConfigurationWindowController.h ├── ConfigurationWindowController.m ├── ConfigurationWindowController.xib ├── FindLocalizedStringFiles.sh ├── Info.plist ├── MenuItemData.plist ├── NSObject_Extension.h ├── NSObject_Extension.m ├── XcodeHelper.h └── XcodeHelper.m ├── LICENSE ├── README.md └── Screenshots └── screenshot.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 | *.xccheckout 22 | *.moved-aside 23 | *.xcuserstate 24 | *.xcscmblueprint 25 | 26 | ## Obj-C/Swift specific 27 | *.hmap 28 | *.ipa 29 | 30 | # CocoaPods 31 | # 32 | # We recommend against adding the Pods directory to your .gitignore. However 33 | # you should judge for yourself, the pros and cons are mentioned at: 34 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 35 | # 36 | # Pods/ 37 | 38 | # Carthage 39 | # 40 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 41 | # Carthage/Checkouts 42 | 43 | Carthage/Build 44 | 45 | # fastlane 46 | # 47 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 48 | # screenshots whenever they are needed. 49 | # For more information about the recommended setup visit: 50 | # https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md 51 | 52 | fastlane/report.xml 53 | fastlane/screenshots 54 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | osx_image: xcode7.2 2 | language: objective-c 3 | xcode_project: AMLocalizedStringBuilder.xcodeproj 4 | xcode_scheme: AMLocalizedStringBuilder 5 | -------------------------------------------------------------------------------- /AMLocalizedStringBuilder.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 246ADFE21CA9045800A1D5B3 /* ConfigurationWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 246ADFE01CA9045800A1D5B3 /* ConfigurationWindowController.m */; }; 11 | 246ADFE31CA9045800A1D5B3 /* ConfigurationWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 246ADFE11CA9045800A1D5B3 /* ConfigurationWindowController.xib */; }; 12 | 246ADFE51CA9109600A1D5B3 /* FindLocalizedStringFiles.sh in Sources */ = {isa = PBXBuildFile; fileRef = 246ADFE41CA9109600A1D5B3 /* FindLocalizedStringFiles.sh */; }; 13 | 246ADFE61CA919B000A1D5B3 /* FindLocalizedStringFiles.sh in Resources */ = {isa = PBXBuildFile; fileRef = 246ADFE41CA9109600A1D5B3 /* FindLocalizedStringFiles.sh */; }; 14 | 246ADFE81CA91FD600A1D5B3 /* MenuItemData.plist in Resources */ = {isa = PBXBuildFile; fileRef = 246ADFE71CA91FD600A1D5B3 /* MenuItemData.plist */; }; 15 | 246ADFEB1CA9203000A1D5B3 /* AMMenuGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 246ADFEA1CA9203000A1D5B3 /* AMMenuGenerator.m */; }; 16 | 246ADFEE1CA920DF00A1D5B3 /* AMConstString.m in Sources */ = {isa = PBXBuildFile; fileRef = 246ADFED1CA920DF00A1D5B3 /* AMConstString.m */; }; 17 | 24B27A651CA93F2700E4F632 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 24B27A631CA93F2700E4F632 /* LICENSE */; }; 18 | 24B27A661CA93F2700E4F632 /* README.md in Sources */ = {isa = PBXBuildFile; fileRef = 24B27A641CA93F2700E4F632 /* README.md */; }; 19 | 24BA88F01CA8D33300D4B872 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 24BA88EF1CA8D33300D4B872 /* AppKit.framework */; }; 20 | 24BA88F21CA8D33300D4B872 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 24BA88F11CA8D33300D4B872 /* Foundation.framework */; }; 21 | 24BA88F61CA8D33300D4B872 /* AMLocalizedStringBuilder.xcscheme in Resources */ = {isa = PBXBuildFile; fileRef = 24BA88F51CA8D33300D4B872 /* AMLocalizedStringBuilder.xcscheme */; }; 22 | 24BA88F91CA8D33300D4B872 /* AMLocalizedStringBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 24BA88F81CA8D33300D4B872 /* AMLocalizedStringBuilder.m */; }; 23 | 24BA88FC1CA8D33300D4B872 /* XcodeHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 24BA88FB1CA8D33300D4B872 /* XcodeHelper.m */; }; 24 | 24BA89041CA8D3B400D4B872 /* AutoGenLocalizedString.sh in Resources */ = {isa = PBXBuildFile; fileRef = 24BA89031CA8D3B400D4B872 /* AutoGenLocalizedString.sh */; }; 25 | 24BFD8D51CA8E02000E4B2A4 /* NSObject_Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = 24BFD8D41CA8E02000E4B2A4 /* NSObject_Extension.m */; }; 26 | /* End PBXBuildFile section */ 27 | 28 | /* Begin PBXFileReference section */ 29 | 246ADFDF1CA9045800A1D5B3 /* ConfigurationWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConfigurationWindowController.h; sourceTree = ""; }; 30 | 246ADFE01CA9045800A1D5B3 /* ConfigurationWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ConfigurationWindowController.m; sourceTree = ""; }; 31 | 246ADFE11CA9045800A1D5B3 /* ConfigurationWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ConfigurationWindowController.xib; sourceTree = ""; }; 32 | 246ADFE41CA9109600A1D5B3 /* FindLocalizedStringFiles.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = FindLocalizedStringFiles.sh; sourceTree = ""; }; 33 | 246ADFE71CA91FD600A1D5B3 /* MenuItemData.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = MenuItemData.plist; sourceTree = ""; }; 34 | 246ADFE91CA9203000A1D5B3 /* AMMenuGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMMenuGenerator.h; sourceTree = ""; }; 35 | 246ADFEA1CA9203000A1D5B3 /* AMMenuGenerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMMenuGenerator.m; sourceTree = ""; }; 36 | 246ADFEC1CA920DF00A1D5B3 /* AMConstString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMConstString.h; sourceTree = ""; }; 37 | 246ADFED1CA920DF00A1D5B3 /* AMConstString.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMConstString.m; sourceTree = ""; }; 38 | 24B27A631CA93F2700E4F632 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; 39 | 24B27A641CA93F2700E4F632 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 40 | 24BA88EC1CA8D33300D4B872 /* AMLocalizedStringBuilder.xcplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AMLocalizedStringBuilder.xcplugin; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | 24BA88EF1CA8D33300D4B872 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; 42 | 24BA88F11CA8D33300D4B872 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; 43 | 24BA88F51CA8D33300D4B872 /* AMLocalizedStringBuilder.xcscheme */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = AMLocalizedStringBuilder.xcscheme; path = AMLocalizedStringBuilder.xcodeproj/xcshareddata/xcschemes/AMLocalizedStringBuilder.xcscheme; sourceTree = SOURCE_ROOT; }; 44 | 24BA88F71CA8D33300D4B872 /* AMLocalizedStringBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AMLocalizedStringBuilder.h; sourceTree = ""; }; 45 | 24BA88F81CA8D33300D4B872 /* AMLocalizedStringBuilder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AMLocalizedStringBuilder.m; sourceTree = ""; }; 46 | 24BA88FA1CA8D33300D4B872 /* XcodeHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XcodeHelper.h; sourceTree = ""; }; 47 | 24BA88FB1CA8D33300D4B872 /* XcodeHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XcodeHelper.m; sourceTree = ""; }; 48 | 24BA88FD1CA8D33300D4B872 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 49 | 24BA89031CA8D3B400D4B872 /* AutoGenLocalizedString.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = AutoGenLocalizedString.sh; sourceTree = ""; }; 50 | 24BFD8D31CA8E02000E4B2A4 /* NSObject_Extension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSObject_Extension.h; sourceTree = ""; }; 51 | 24BFD8D41CA8E02000E4B2A4 /* NSObject_Extension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSObject_Extension.m; sourceTree = ""; }; 52 | /* End PBXFileReference section */ 53 | 54 | /* Begin PBXFrameworksBuildPhase section */ 55 | 24BA88EA1CA8D33300D4B872 /* Frameworks */ = { 56 | isa = PBXFrameworksBuildPhase; 57 | buildActionMask = 2147483647; 58 | files = ( 59 | 24BA88F01CA8D33300D4B872 /* AppKit.framework in Frameworks */, 60 | 24BA88F21CA8D33300D4B872 /* Foundation.framework in Frameworks */, 61 | ); 62 | runOnlyForDeploymentPostprocessing = 0; 63 | }; 64 | /* End PBXFrameworksBuildPhase section */ 65 | 66 | /* Begin PBXGroup section */ 67 | 24BA88E31CA8D33300D4B872 = { 68 | isa = PBXGroup; 69 | children = ( 70 | 24B27A631CA93F2700E4F632 /* LICENSE */, 71 | 24B27A641CA93F2700E4F632 /* README.md */, 72 | 24BA88F31CA8D33300D4B872 /* AMLocalizedStringBuilder */, 73 | 24BA88EE1CA8D33300D4B872 /* Frameworks */, 74 | 24BA88ED1CA8D33300D4B872 /* Products */, 75 | ); 76 | sourceTree = ""; 77 | }; 78 | 24BA88ED1CA8D33300D4B872 /* Products */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 24BA88EC1CA8D33300D4B872 /* AMLocalizedStringBuilder.xcplugin */, 82 | ); 83 | name = Products; 84 | sourceTree = ""; 85 | }; 86 | 24BA88EE1CA8D33300D4B872 /* Frameworks */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | 24BA88EF1CA8D33300D4B872 /* AppKit.framework */, 90 | 24BA88F11CA8D33300D4B872 /* Foundation.framework */, 91 | ); 92 | name = Frameworks; 93 | sourceTree = ""; 94 | }; 95 | 24BA88F31CA8D33300D4B872 /* AMLocalizedStringBuilder */ = { 96 | isa = PBXGroup; 97 | children = ( 98 | 24BA88F71CA8D33300D4B872 /* AMLocalizedStringBuilder.h */, 99 | 24BA88F81CA8D33300D4B872 /* AMLocalizedStringBuilder.m */, 100 | 246ADFE91CA9203000A1D5B3 /* AMMenuGenerator.h */, 101 | 246ADFEA1CA9203000A1D5B3 /* AMMenuGenerator.m */, 102 | 24BFD8D31CA8E02000E4B2A4 /* NSObject_Extension.h */, 103 | 24BFD8D41CA8E02000E4B2A4 /* NSObject_Extension.m */, 104 | 246ADFEC1CA920DF00A1D5B3 /* AMConstString.h */, 105 | 246ADFED1CA920DF00A1D5B3 /* AMConstString.m */, 106 | 246ADFDF1CA9045800A1D5B3 /* ConfigurationWindowController.h */, 107 | 246ADFE01CA9045800A1D5B3 /* ConfigurationWindowController.m */, 108 | 246ADFE11CA9045800A1D5B3 /* ConfigurationWindowController.xib */, 109 | 24BA88FA1CA8D33300D4B872 /* XcodeHelper.h */, 110 | 24BA88FB1CA8D33300D4B872 /* XcodeHelper.m */, 111 | 24BA88F41CA8D33300D4B872 /* Supporting Files */, 112 | ); 113 | path = AMLocalizedStringBuilder; 114 | sourceTree = ""; 115 | }; 116 | 24BA88F41CA8D33300D4B872 /* Supporting Files */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | 246ADFE71CA91FD600A1D5B3 /* MenuItemData.plist */, 120 | 24BA88FD1CA8D33300D4B872 /* Info.plist */, 121 | 24BA89031CA8D3B400D4B872 /* AutoGenLocalizedString.sh */, 122 | 246ADFE41CA9109600A1D5B3 /* FindLocalizedStringFiles.sh */, 123 | 24BA88F51CA8D33300D4B872 /* AMLocalizedStringBuilder.xcscheme */, 124 | ); 125 | name = "Supporting Files"; 126 | sourceTree = ""; 127 | }; 128 | /* End PBXGroup section */ 129 | 130 | /* Begin PBXNativeTarget section */ 131 | 24BA88EB1CA8D33300D4B872 /* AMLocalizedStringBuilder */ = { 132 | isa = PBXNativeTarget; 133 | buildConfigurationList = 24BA89001CA8D33300D4B872 /* Build configuration list for PBXNativeTarget "AMLocalizedStringBuilder" */; 134 | buildPhases = ( 135 | 24BA88E81CA8D33300D4B872 /* Sources */, 136 | 24BA88E91CA8D33300D4B872 /* Resources */, 137 | 24BA88EA1CA8D33300D4B872 /* Frameworks */, 138 | ); 139 | buildRules = ( 140 | ); 141 | dependencies = ( 142 | ); 143 | name = AMLocalizedStringBuilder; 144 | productName = AMLocalizedStringBuilder; 145 | productReference = 24BA88EC1CA8D33300D4B872 /* AMLocalizedStringBuilder.xcplugin */; 146 | productType = "com.apple.product-type.bundle"; 147 | }; 148 | /* End PBXNativeTarget section */ 149 | 150 | /* Begin PBXProject section */ 151 | 24BA88E41CA8D33300D4B872 /* Project object */ = { 152 | isa = PBXProject; 153 | attributes = { 154 | LastUpgradeCheck = 0720; 155 | ORGANIZATIONNAME = tendencystudio; 156 | TargetAttributes = { 157 | 24BA88EB1CA8D33300D4B872 = { 158 | CreatedOnToolsVersion = 7.2.1; 159 | }; 160 | }; 161 | }; 162 | buildConfigurationList = 24BA88E71CA8D33300D4B872 /* Build configuration list for PBXProject "AMLocalizedStringBuilder" */; 163 | compatibilityVersion = "Xcode 3.2"; 164 | developmentRegion = English; 165 | hasScannedForEncodings = 0; 166 | knownRegions = ( 167 | en, 168 | ); 169 | mainGroup = 24BA88E31CA8D33300D4B872; 170 | productRefGroup = 24BA88ED1CA8D33300D4B872 /* Products */; 171 | projectDirPath = ""; 172 | projectRoot = ""; 173 | targets = ( 174 | 24BA88EB1CA8D33300D4B872 /* AMLocalizedStringBuilder */, 175 | ); 176 | }; 177 | /* End PBXProject section */ 178 | 179 | /* Begin PBXResourcesBuildPhase section */ 180 | 24BA88E91CA8D33300D4B872 /* Resources */ = { 181 | isa = PBXResourcesBuildPhase; 182 | buildActionMask = 2147483647; 183 | files = ( 184 | 24B27A651CA93F2700E4F632 /* LICENSE in Resources */, 185 | 246ADFE61CA919B000A1D5B3 /* FindLocalizedStringFiles.sh in Resources */, 186 | 246ADFE81CA91FD600A1D5B3 /* MenuItemData.plist in Resources */, 187 | 24BA88F61CA8D33300D4B872 /* AMLocalizedStringBuilder.xcscheme in Resources */, 188 | 246ADFE31CA9045800A1D5B3 /* ConfigurationWindowController.xib in Resources */, 189 | 24BA89041CA8D3B400D4B872 /* AutoGenLocalizedString.sh in Resources */, 190 | ); 191 | runOnlyForDeploymentPostprocessing = 0; 192 | }; 193 | /* End PBXResourcesBuildPhase section */ 194 | 195 | /* Begin PBXSourcesBuildPhase section */ 196 | 24BA88E81CA8D33300D4B872 /* Sources */ = { 197 | isa = PBXSourcesBuildPhase; 198 | buildActionMask = 2147483647; 199 | files = ( 200 | 24BA88F91CA8D33300D4B872 /* AMLocalizedStringBuilder.m in Sources */, 201 | 24BA88FC1CA8D33300D4B872 /* XcodeHelper.m in Sources */, 202 | 246ADFE51CA9109600A1D5B3 /* FindLocalizedStringFiles.sh in Sources */, 203 | 246ADFE21CA9045800A1D5B3 /* ConfigurationWindowController.m in Sources */, 204 | 246ADFEB1CA9203000A1D5B3 /* AMMenuGenerator.m in Sources */, 205 | 246ADFEE1CA920DF00A1D5B3 /* AMConstString.m in Sources */, 206 | 24B27A661CA93F2700E4F632 /* README.md in Sources */, 207 | 24BFD8D51CA8E02000E4B2A4 /* NSObject_Extension.m in Sources */, 208 | ); 209 | runOnlyForDeploymentPostprocessing = 0; 210 | }; 211 | /* End PBXSourcesBuildPhase section */ 212 | 213 | /* Begin XCBuildConfiguration section */ 214 | 24BA88FE1CA8D33300D4B872 /* Debug */ = { 215 | isa = XCBuildConfiguration; 216 | buildSettings = { 217 | ALWAYS_SEARCH_USER_PATHS = NO; 218 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 219 | CLANG_CXX_LIBRARY = "libc++"; 220 | CLANG_ENABLE_MODULES = YES; 221 | CLANG_ENABLE_OBJC_ARC = YES; 222 | CLANG_WARN_BOOL_CONVERSION = YES; 223 | CLANG_WARN_CONSTANT_CONVERSION = YES; 224 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 225 | CLANG_WARN_EMPTY_BODY = YES; 226 | CLANG_WARN_ENUM_CONVERSION = YES; 227 | CLANG_WARN_INT_CONVERSION = YES; 228 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 229 | CLANG_WARN_UNREACHABLE_CODE = YES; 230 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 231 | COPY_PHASE_STRIP = NO; 232 | DEBUG_INFORMATION_FORMAT = dwarf; 233 | ENABLE_STRICT_OBJC_MSGSEND = YES; 234 | ENABLE_TESTABILITY = YES; 235 | GCC_C_LANGUAGE_STANDARD = gnu99; 236 | GCC_DYNAMIC_NO_PIC = NO; 237 | GCC_NO_COMMON_BLOCKS = YES; 238 | GCC_OPTIMIZATION_LEVEL = 0; 239 | GCC_PREPROCESSOR_DEFINITIONS = ( 240 | "DEBUG=1", 241 | "$(inherited)", 242 | ); 243 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 244 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 245 | GCC_WARN_UNDECLARED_SELECTOR = YES; 246 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 247 | GCC_WARN_UNUSED_FUNCTION = YES; 248 | GCC_WARN_UNUSED_VARIABLE = YES; 249 | MTL_ENABLE_DEBUG_INFO = YES; 250 | ONLY_ACTIVE_ARCH = YES; 251 | }; 252 | name = Debug; 253 | }; 254 | 24BA88FF1CA8D33300D4B872 /* Release */ = { 255 | isa = XCBuildConfiguration; 256 | buildSettings = { 257 | ALWAYS_SEARCH_USER_PATHS = NO; 258 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 259 | CLANG_CXX_LIBRARY = "libc++"; 260 | CLANG_ENABLE_MODULES = YES; 261 | CLANG_ENABLE_OBJC_ARC = YES; 262 | CLANG_WARN_BOOL_CONVERSION = YES; 263 | CLANG_WARN_CONSTANT_CONVERSION = YES; 264 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 265 | CLANG_WARN_EMPTY_BODY = YES; 266 | CLANG_WARN_ENUM_CONVERSION = YES; 267 | CLANG_WARN_INT_CONVERSION = YES; 268 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 269 | CLANG_WARN_UNREACHABLE_CODE = YES; 270 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 271 | COPY_PHASE_STRIP = NO; 272 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 273 | ENABLE_NS_ASSERTIONS = NO; 274 | ENABLE_STRICT_OBJC_MSGSEND = YES; 275 | GCC_C_LANGUAGE_STANDARD = gnu99; 276 | GCC_NO_COMMON_BLOCKS = YES; 277 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 278 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 279 | GCC_WARN_UNDECLARED_SELECTOR = YES; 280 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 281 | GCC_WARN_UNUSED_FUNCTION = YES; 282 | GCC_WARN_UNUSED_VARIABLE = YES; 283 | MTL_ENABLE_DEBUG_INFO = NO; 284 | }; 285 | name = Release; 286 | }; 287 | 24BA89011CA8D33300D4B872 /* Debug */ = { 288 | isa = XCBuildConfiguration; 289 | buildSettings = { 290 | COMBINE_HIDPI_IMAGES = YES; 291 | DEPLOYMENT_LOCATION = YES; 292 | DSTROOT = "$(HOME)"; 293 | INFOPLIST_FILE = AMLocalizedStringBuilder/Info.plist; 294 | INSTALL_PATH = "/Library/Application Support/Developer/Shared/Xcode/Plug-ins"; 295 | MACOSX_DEPLOYMENT_TARGET = 10.10; 296 | PRODUCT_BUNDLE_IDENTIFIER = com.tendencystudio.AMLocalizedStringBuilder; 297 | PRODUCT_NAME = "$(TARGET_NAME)"; 298 | WRAPPER_EXTENSION = xcplugin; 299 | }; 300 | name = Debug; 301 | }; 302 | 24BA89021CA8D33300D4B872 /* Release */ = { 303 | isa = XCBuildConfiguration; 304 | buildSettings = { 305 | COMBINE_HIDPI_IMAGES = YES; 306 | DEPLOYMENT_LOCATION = YES; 307 | DSTROOT = "$(HOME)"; 308 | INFOPLIST_FILE = AMLocalizedStringBuilder/Info.plist; 309 | INSTALL_PATH = "/Library/Application Support/Developer/Shared/Xcode/Plug-ins"; 310 | MACOSX_DEPLOYMENT_TARGET = 10.10; 311 | PRODUCT_BUNDLE_IDENTIFIER = com.tendencystudio.AMLocalizedStringBuilder; 312 | PRODUCT_NAME = "$(TARGET_NAME)"; 313 | WRAPPER_EXTENSION = xcplugin; 314 | }; 315 | name = Release; 316 | }; 317 | /* End XCBuildConfiguration section */ 318 | 319 | /* Begin XCConfigurationList section */ 320 | 24BA88E71CA8D33300D4B872 /* Build configuration list for PBXProject "AMLocalizedStringBuilder" */ = { 321 | isa = XCConfigurationList; 322 | buildConfigurations = ( 323 | 24BA88FE1CA8D33300D4B872 /* Debug */, 324 | 24BA88FF1CA8D33300D4B872 /* Release */, 325 | ); 326 | defaultConfigurationIsVisible = 0; 327 | defaultConfigurationName = Release; 328 | }; 329 | 24BA89001CA8D33300D4B872 /* Build configuration list for PBXNativeTarget "AMLocalizedStringBuilder" */ = { 330 | isa = XCConfigurationList; 331 | buildConfigurations = ( 332 | 24BA89011CA8D33300D4B872 /* Debug */, 333 | 24BA89021CA8D33300D4B872 /* Release */, 334 | ); 335 | defaultConfigurationIsVisible = 0; 336 | defaultConfigurationName = Release; 337 | }; 338 | /* End XCConfigurationList section */ 339 | }; 340 | rootObject = 24BA88E41CA8D33300D4B872 /* Project object */; 341 | } 342 | -------------------------------------------------------------------------------- /AMLocalizedStringBuilder.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AMLocalizedStringBuilder.xcodeproj/xcshareddata/xcschemes/AMLocalizedStringBuilder.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 46 | 47 | 48 | 49 | 61 | 64 | 65 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /AMLocalizedStringBuilder/AMConstString.h: -------------------------------------------------------------------------------- 1 | // 2 | // AMConstString.h 3 | // AMLocalizedStringBuilder 4 | // 5 | // Created by Mellong 15/4/1. 6 | // Copyright (c) 2015年 Tendencystudio. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | extern NSString * const kMenuRootMenuTitle; 12 | extern NSString * const kMenuPluginTitle; 13 | extern NSString * const kMenuSubMenuItems; 14 | extern NSString * const kMenuTitle; 15 | extern NSString * const kMenuSelector; 16 | extern NSString * const kMenuShortcut; 17 | extern NSString * const kMenuKeyMask; 18 | extern NSString * const kMenuKeyEquivalent; 19 | 20 | extern NSString * const kMenuActionTitle; -------------------------------------------------------------------------------- /AMLocalizedStringBuilder/AMConstString.m: -------------------------------------------------------------------------------- 1 | // 2 | // AMConstString.m 3 | // AMLocalizedStringBuilder 4 | // 5 | // Created by Mellong 15/4/1. 6 | // Copyright (c) 2015年 Tendencystudio. All rights reserved. 7 | // 8 | 9 | #import "AMConstString.h" 10 | 11 | 12 | NSString * const kMenuRootMenuTitle = @"rootMenuTitle"; 13 | NSString * const kMenuPluginTitle = @"pluginTitle"; 14 | NSString * const kMenuSubMenuItems = @"subMenuItems"; 15 | NSString * const kMenuTitle = @"title"; 16 | NSString * const kMenuSelector = @"selector"; 17 | NSString * const kMenuShortcut = @"shortcut"; 18 | NSString * const kMenuKeyMask = @"keyMask"; 19 | NSString * const kMenuKeyEquivalent = @"keyEquivalent"; 20 | 21 | NSString * const kMenuActionTitle = @"AMLocalizedStringBuilderShotcut"; -------------------------------------------------------------------------------- /AMLocalizedStringBuilder/AMLocalizedStringBuilder.h: -------------------------------------------------------------------------------- 1 | // 2 | // AMLocalizedStringBuilder.h 3 | // AMLocalizedStringBuilder 4 | // 5 | // Created by Mellong on 16/3/28. 6 | // Copyright © 2016年 tendencystudio. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class AMLocalizedStringBuilder; 12 | 13 | static AMLocalizedStringBuilder *sharedPlugin; 14 | 15 | @interface AMLocalizedStringBuilder : NSObject 16 | 17 | + (instancetype)sharedPlugin; 18 | - (id)initWithBundle:(NSBundle *)plugin; 19 | 20 | @property (nonatomic, strong, readonly) NSBundle* bundle; 21 | @end -------------------------------------------------------------------------------- /AMLocalizedStringBuilder/AMLocalizedStringBuilder.m: -------------------------------------------------------------------------------- 1 | // 2 | // AMLocalizedStringBuilder.m 3 | // AMLocalizedStringBuilder 4 | // 5 | // Created by Mellong on 16/3/28. 6 | // Copyright © 2016年 tendencystudio. All rights reserved. 7 | // 8 | 9 | #import "AMLocalizedStringBuilder.h" 10 | #import "XcodeHelper.h" 11 | #import "ConfigurationWindowController.h" 12 | #import "AMMenuGenerator.h" 13 | 14 | @interface AMLocalizedStringBuilder() 15 | 16 | @property (nonatomic, strong, readwrite) NSBundle *bundle; 17 | @property (nonatomic, strong) ConfigurationWindowController * settingWindowController; 18 | 19 | @end 20 | 21 | @implementation AMLocalizedStringBuilder 22 | 23 | + (instancetype)sharedPlugin 24 | { 25 | return sharedPlugin; 26 | } 27 | 28 | - (id)initWithBundle:(NSBundle *)plugin 29 | { 30 | if (self = [super init]) { 31 | // reference to plugin's bundle, for resource access 32 | self.bundle = plugin; 33 | [[NSNotificationCenter defaultCenter] addObserver:self 34 | selector:@selector(didApplicationFinishLaunchingNotification:) 35 | name:NSApplicationDidFinishLaunchingNotification 36 | object:nil]; 37 | } 38 | return self; 39 | } 40 | 41 | - (void)didApplicationFinishLaunchingNotification:(NSNotification*)noti 42 | { 43 | [AMMenuGenerator generateMenuItems:self.bundle version:[self getBundleVersion] target:self]; 44 | 45 | [[NSNotificationCenter defaultCenter] removeObserver:self 46 | name:NSApplicationDidFinishLaunchingNotification 47 | object:nil]; 48 | } 49 | 50 | - (NSString *)getBundleVersion 51 | { 52 | NSString *bundleVersion = [[self.bundle infoDictionary] objectForKey:@"CFBundleShortVersionString"]; 53 | return bundleVersion; 54 | } 55 | 56 | - (void)buildLocalizedString 57 | { 58 | NSString* filePath = [[XcodeHelper currentWorkspaceDocument].workspace.representingFilePath.fileURL path]; 59 | NSString* projectDir = [filePath stringByDeletingLastPathComponent]; 60 | NSString* projectName = [[filePath lastPathComponent] stringByDeletingPathExtension]; 61 | NSString *path = [[NSUserDefaults standardUserDefaults] objectForKey:projectName]; 62 | if (path == nil) { 63 | NSArray *pathList = [XcodeHelper findLocalizedStringFilesPath:projectDir]; 64 | if (pathList.count > 0) { 65 | [[NSUserDefaults standardUserDefaults] setObject:pathList.firstObject forKey:projectName]; 66 | [[NSUserDefaults standardUserDefaults] synchronize]; 67 | }else { 68 | NSLog(@"Error: no localized string file found!"); 69 | return; 70 | } 71 | 72 | } 73 | 74 | NSTask* task = [[NSTask alloc] init]; 75 | [task setLaunchPath:@"/bin/bash"]; 76 | NSString* shellPath = 77 | [[NSBundle bundleForClass:[self class]] pathForResource:@"AutoGenLocalizedString" 78 | ofType:@"sh"]; 79 | NSString *localizedStringFilePath = [[NSUserDefaults standardUserDefaults] objectForKey:projectName]; 80 | [task setArguments:@[ shellPath , projectDir, localizedStringFilePath]]; 81 | 82 | [task launch]; 83 | } 84 | 85 | - (void)showSettingWindow 86 | { 87 | self.settingWindowController = [[ConfigurationWindowController alloc] initWithWindowNibName:@"ConfigurationWindowController"]; 88 | [self.settingWindowController showWindow:self.settingWindowController]; 89 | } 90 | 91 | - (void)dealloc 92 | { 93 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 94 | } 95 | 96 | @end 97 | -------------------------------------------------------------------------------- /AMLocalizedStringBuilder/AMMenuGenerator.h: -------------------------------------------------------------------------------- 1 | // 2 | // AMMenuGenerator.h 3 | // AMLocalizedStringBuilder 4 | // 5 | // Created by Mellong 15/4/1. 6 | // Copyright (c) 2015年 Tendencystudio. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "AMConstString.h" 12 | 13 | @interface AMMenuGenerator : NSObject 14 | 15 | + (void)generateMenuItems:(NSBundle *)bundle version:(NSString *)version target:(id)target; 16 | + (NSUInteger)getKeyEquivalentModifierMaskWithKey:(NSString *)key; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /AMLocalizedStringBuilder/AMMenuGenerator.m: -------------------------------------------------------------------------------- 1 | // 2 | // AMMenuGenerator.m 3 | // AMLocalizedStringBuilder 4 | // 5 | // Created by Mellong 15/4/1. 6 | // Copyright (c) 2015年 Tendencystudio. All rights reserved. 7 | // 8 | 9 | #import "AMMenuGenerator.h" 10 | 11 | @implementation AMMenuGenerator 12 | 13 | + (void)generateMenuItems:(NSBundle *)bundle version:(NSString *)version target:(id)target 14 | { 15 | NSString *dataPath = [bundle pathForResource:@"MenuItemData" ofType:@"plist"]; 16 | NSDictionary *menuData = [NSDictionary dictionaryWithContentsOfFile:dataPath]; 17 | NSMenuItem *menuItem = [[NSApp mainMenu] itemWithTitle:menuData[kMenuRootMenuTitle]]; 18 | 19 | if (menuItem) { 20 | 21 | [[menuItem submenu] addItem:[NSMenuItem separatorItem]]; 22 | NSString *title = menuData[kMenuPluginTitle]; 23 | NSMenuItem *actionMenuItem = [[NSMenuItem alloc] initWithTitle:title action:nil keyEquivalent:@""]; 24 | [[menuItem submenu] addItem:actionMenuItem]; 25 | NSMenu* submenu = [[NSMenu alloc] init]; 26 | [actionMenuItem setSubmenu:submenu]; 27 | for (NSDictionary *item in menuData[kMenuSubMenuItems]) { 28 | NSString *subMenuTitle = item[kMenuTitle]; 29 | if ([subMenuTitle rangeOfString:@"%@"].length > 0) { 30 | subMenuTitle = [NSString stringWithFormat:subMenuTitle, version]; 31 | } 32 | 33 | NSString *selectorString = item[kMenuSelector]; 34 | SEL selector = nil; 35 | if (selectorString != nil && selectorString.length > 0) { 36 | selector = NSSelectorFromString(selectorString); 37 | } 38 | NSString *keyEquivalent = @""; 39 | if (item[kMenuShortcut][kMenuKeyEquivalent] != nil) { 40 | keyEquivalent = item[kMenuShortcut][kMenuKeyEquivalent]; 41 | } 42 | 43 | NSArray *maskArray = item[kMenuShortcut][kMenuKeyMask]; 44 | NSDictionary *userMenu = [[NSUserDefaults standardUserDefaults] objectForKey:kMenuActionTitle]; 45 | if (userMenu != nil) { 46 | keyEquivalent = userMenu[kMenuKeyEquivalent]; 47 | maskArray = userMenu[kMenuShortcut]; 48 | } 49 | 50 | NSMenuItem *subMenuItem = [[NSMenuItem alloc] initWithTitle:subMenuTitle action:selector keyEquivalent:keyEquivalent]; 51 | 52 | if (maskArray.count == 1) { 53 | subMenuItem.keyEquivalentModifierMask = [AMMenuGenerator getKeyEquivalentModifierMaskWithKey:maskArray[0]]; 54 | }else if(maskArray.count == 2) { 55 | subMenuItem.keyEquivalentModifierMask = [AMMenuGenerator getKeyEquivalentModifierMaskWithKey:maskArray[0]] | 56 | [AMMenuGenerator getKeyEquivalentModifierMaskWithKey:maskArray[1]]; 57 | } 58 | subMenuItem.target = target; 59 | [submenu addItem:subMenuItem]; 60 | } 61 | 62 | } 63 | } 64 | 65 | + (NSUInteger)getKeyEquivalentModifierMaskWithKey:(NSString *)key 66 | { 67 | NSDictionary *keyMaskMap = @{@"ctrl":@(NSControlKeyMask), 68 | @"shift":@(NSShiftKeyMask), 69 | @"cmd":@(NSCommandKeyMask), 70 | @"alt":@(NSAlternateKeyMask)}; 71 | return [keyMaskMap[key] integerValue]; 72 | } 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /AMLocalizedStringBuilder/AutoGenLocalizedString.sh: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | # 3 | # AMLocalizedStringBuilder 4 | # 5 | # Created by Mellong on 16/3/28. 6 | # Copyright © 2016年 tendencystudio. All rights reserved. 7 | 8 | PROJECT_DIR=$1 9 | STRING_FILE=$2 10 | 11 | H_FILE="${PROJECT_DIR}/temple.h" 12 | M_FILE="${PROJECT_DIR}/temple.m" 13 | RESULT_H_FILE="${PROJECT_DIR}/AMLocalizedString.h" 14 | RESULT_M_FILE="${PROJECT_DIR}/AMLocalizedString.m" 15 | 16 | #h file 17 | cat $STRING_FILE | grep -E "\".*?\"\s*=\s*\".*?\"\s*;" | perl -n -e'/\"(.*?)\"\s*=\s*\"(.*?)\"\s*;/ && print "/**\n * $2\n */\n\@property (nonatomic, copy, readonly) NSString *am_$1;\n\n"' > $H_FILE; 18 | # echo `cat $H_FILE` 19 | cat $H_FILE | sed '1 i\ 20 | \ 21 | //\ 22 | // AMLocalizedString.h\ 23 | // AMLocalizedString\ 24 | //\ 25 | // Created by Mellong on 16/03/01.\ 26 | // Copyright © 2016年 tendencystudio. All rights reserved.\ 27 | //\ 28 | \ 29 | #import \ 30 | \ 31 | #define R_String [AMLocalizedString shareInstance]\ 32 | \ 33 | @interface AMLocalizedString : NSObject\ 34 | \ 35 | ' | sed '$ a\ 36 | + (instancetype)shareInstance;\ 37 | \ 38 | \ 39 | @end\ 40 | ' > $RESULT_H_FILE; 41 | 42 | 43 | 44 | #m file 45 | cat $STRING_FILE | grep -E "\".*?\"\s*=\s*\".*?\"\s*;" | perl -n -e'/\"(.*?)\"\s*=\s*\"(.*?)\"\s*;/ && print "\n/**\n * $2\n */\n- (NSString *)am_$1\n{\n return NSLocalizedString(@\"$1\" ,nil);\n}\n"' > $M_FILE; 46 | 47 | cat $M_FILE | sed '1 i\ 48 | \ 49 | //\ 50 | // AMLocalizedString.m\ 51 | // AMLocalizedString\ 52 | //\ 53 | // Created by Mellong on 16/03/01.\ 54 | // Copyright © 2016年 tendencystudio. All rights reserved.\ 55 | //\ 56 | \ 57 | \ 58 | #import "AMLocalizedString.h"\ 59 | \ 60 | \ 61 | @implementation AMLocalizedString\ 62 | \ 63 | + (instancetype)shareInstance\ 64 | {\ 65 | \ \ static id instance = nil;\ 66 | \ \ static dispatch_once_t onceToken;\ 67 | \ \ dispatch_once(&onceToken, ^{\ 68 | \ \ \ \ instance = [[self alloc] init];\ 69 | \ \ });\ 70 | \ \ return instance;\ 71 | }\ 72 | \ 73 | ' | sed '$ a\ 74 | \ 75 | @end' > $RESULT_M_FILE; 76 | 77 | rm $H_FILE 78 | rm $M_FILE -------------------------------------------------------------------------------- /AMLocalizedStringBuilder/ConfigurationWindowController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ConfigruationWindowController.h 3 | // AMLocalizedStringBuilder 4 | // 5 | // Created by Mellong on 16/3/28. 6 | // Copyright © 2016年 tendencystudio. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ConfigurationWindowController : NSWindowController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /AMLocalizedStringBuilder/ConfigurationWindowController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ConfigruationWindowController.m 3 | // AMLocalizedStringBuilder 4 | // 5 | // Created by Mellong on 16/3/28. 6 | // Copyright © 2016年 tendencystudio. All rights reserved. 7 | // 8 | 9 | #import "ConfigurationWindowController.h" 10 | #import "XcodeHelper.h" 11 | #import "AMConstString.h" 12 | 13 | @interface ConfigurationWindowController () 14 | 15 | @property (weak) IBOutlet NSTableView *tableView; 16 | @property (nonatomic, strong) NSArray *dataList; 17 | @property (nonatomic, strong) NSString *projectName; 18 | 19 | 20 | @end 21 | 22 | @implementation ConfigurationWindowController 23 | 24 | 25 | - (void)windowDidLoad { 26 | [super windowDidLoad]; 27 | 28 | NSString* filePath = [[XcodeHelper currentWorkspaceDocument].workspace.representingFilePath.fileURL path]; 29 | NSString* projectDir = [filePath stringByDeletingLastPathComponent]; 30 | _projectName = [[filePath lastPathComponent] stringByDeletingPathExtension]; 31 | 32 | self.window.title = [NSString stringWithFormat:@"AMLocalizedStringBuilder-%@", _projectName]; 33 | 34 | self.dataList = [XcodeHelper findLocalizedStringFilesPath:projectDir]; 35 | [self.tableView reloadData]; 36 | 37 | } 38 | 39 | - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView 40 | { 41 | return self.dataList.count; 42 | } 43 | 44 | - (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row 45 | { 46 | if ([tableColumn.title isEqualToString:@"Selection"]) { 47 | NSString *path = [[NSUserDefaults standardUserDefaults] objectForKey:_projectName]; 48 | if (path) { 49 | return @([self.dataList[row] isEqualToString:path]); 50 | } 51 | return nil; 52 | } 53 | NSArray *result = [self.dataList[row] componentsSeparatedByString:@"/"]; 54 | return [NSString stringWithFormat:@".../%@/%@", result[result.count-2], result.lastObject]; 55 | } 56 | 57 | - (void)tableView:(NSTableView *)tableView setObjectValue:(id)anObject forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row 58 | { 59 | [self.tableView reloadData]; 60 | [[NSUserDefaults standardUserDefaults] setObject:self.dataList[row] forKey:_projectName]; 61 | [[NSUserDefaults standardUserDefaults] synchronize]; 62 | } 63 | 64 | - (IBAction)onCloseButtonClicked:(NSButton *)sender { 65 | [self close]; 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /AMLocalizedStringBuilder/ConfigurationWindowController.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 | 77 | 81 | 82 | 83 | 84 | 85 | 86 | 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 | -------------------------------------------------------------------------------- /AMLocalizedStringBuilder/FindLocalizedStringFiles.sh: -------------------------------------------------------------------------------- 1 | #/bin/bash 2 | # 3 | # AMLocalizedStringBuilder 4 | # 5 | # Created by Mellong on 16/3/28. 6 | # Copyright © 2016年 tendencystudio. All rights reserved. 7 | 8 | PROJECT_DIR=$1 9 | 10 | find $PROJECT_DIR -name "Localizable.strings" -------------------------------------------------------------------------------- /AMLocalizedStringBuilder/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 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 | BNDL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | $(MACOSX_DEPLOYMENT_TARGET) 27 | DVTPlugInCompatibilityUUIDs 28 | 29 | C4A681B0-4A26-480E-93EC-1218098B9AA0 30 | F41BD31E-2683-44B8-AE7F-5F09E919790E 31 | AD68E85B-441B-4301-B564-A45E4919A6AD 32 | A16FF353-8441-459E-A50C-B071F53F51B7 33 | 9F75337B-21B4-4ADC-B558-F9CADF7073A7 34 | E969541F-E6F9-4D25-8158-72DC3545A6C6 35 | 8DC44374-2B35-4C57-A6FE-2AD66A36AAD9 36 | AABB7188-E14E-4433-AD3B-5CD791EAD9A3 37 | 8DC44374-2B35-4C57-A6FE-2AD66A36AAD9 38 | AABB7188-E14E-4433-AD3B-5CD791EAD9A3 39 | 7FDF5C7A-131F-4ABB-9EDC-8C5F8F0B8A90 40 | 0420B86A-AA43-4792-9ED0-6FE0F2B16A13 41 | 7265231C-39B4-402C-89E1-16167C4CC990 42 | ACA8656B-FEA8-4B6D-8E4A-93F4C95C362C 43 | 44 | NSPrincipalClass 45 | AMLocalizedStringBuilder 46 | XC4Compatible 47 | 48 | XCPluginHasUI 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /AMLocalizedStringBuilder/MenuItemData.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | rootMenuTitle 6 | Product 7 | pluginTitle 8 | AMLocalizedStringBuilder 9 | subMenuItems 10 | 11 | 12 | title 13 | Build Localized String 14 | selector 15 | buildLocalizedString 16 | shortcut 17 | 18 | keyMask 19 | 20 | ctrl 21 | 22 | keyEquivalent 23 | f 24 | 25 | 26 | 27 | title 28 | Setting 29 | selector 30 | showSettingWindow 31 | shortcut 32 | 33 | keyMask 34 | 35 | ctrl 36 | cmd 37 | 38 | keyEquivalent 39 | s 40 | 41 | 42 | 43 | title 44 | Plugin version %@ 45 | selector 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /AMLocalizedStringBuilder/NSObject_Extension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject_Extension.h 3 | // AMLocalizedStringBuilder 4 | // 5 | // Created by Mellong on 16/2/16. 6 | // Copyright © 2016年 tendencystudio. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSObject (Xcode_Plugin_Template_Extension) 12 | 13 | + (void)pluginDidLoad:(NSBundle *)plugin; 14 | 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /AMLocalizedStringBuilder/NSObject_Extension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject_Extension.m 3 | // AMLocalizedStringBuilder 4 | // 5 | // Created by Mellong on 16/2/16. 6 | // Copyright © 2016年 tendencystudio. All rights reserved. 7 | // 8 | 9 | 10 | #import "NSObject_Extension.h" 11 | #import "AMLocalizedStringBuilder.h" 12 | 13 | @implementation NSObject (Xcode_Plugin_Template_Extension) 14 | 15 | + (void)pluginDidLoad:(NSBundle *)plugin 16 | { 17 | static dispatch_once_t onceToken; 18 | NSString *currentApplicationName = [[NSBundle mainBundle] infoDictionary][@"CFBundleName"]; 19 | if ([currentApplicationName isEqual:@"Xcode"]) { 20 | dispatch_once(&onceToken, ^{ 21 | sharedPlugin = [[AMLocalizedStringBuilder alloc] initWithBundle:plugin]; 22 | }); 23 | } 24 | } 25 | @end 26 | -------------------------------------------------------------------------------- /AMLocalizedStringBuilder/XcodeHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // XcodeHelper.h 3 | // AMLocalizedStringBuilder 4 | // 5 | // Created by Mellong on 16/3/28. 6 | // Copyright © 2016年 tendencystudio. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | 13 | @interface DVTChoice : NSObject 14 | - (id)initWithTitle:(id)arg1 toolTip:(id)arg2 image:(id)arg3 representedObject:(id)arg4; 15 | @end 16 | 17 | @interface DVTTextDocumentLocation : NSObject 18 | @property (readonly) NSRange characterRange; 19 | @property (readonly) NSRange lineRange; 20 | @end 21 | 22 | @interface DVTTextPreferences : NSObject 23 | + (id)preferences; 24 | @property BOOL trimWhitespaceOnlyLines; 25 | @property BOOL trimTrailingWhitespace; 26 | @property BOOL useSyntaxAwareIndenting; 27 | @end 28 | 29 | @interface DVTSourceTextStorage : NSTextStorage 30 | - (void)replaceCharactersInRange:(NSRange)range withString:(NSString*)string withUndoManager:(id)undoManager; 31 | - (NSRange)lineRangeForCharacterRange:(NSRange)range; 32 | - (NSRange)characterRangeForLineRange:(NSRange)range; 33 | - (void)indentCharacterRange:(NSRange)range undoManager:(id)undoManager; 34 | @end 35 | 36 | @interface DVTFileDataType : NSObject 37 | @property (readonly) NSString* identifier; 38 | @end 39 | 40 | @interface DVTFilePath : NSObject 41 | @property (readonly) NSURL* fileURL; 42 | @property (readonly) DVTFileDataType* fileDataTypePresumed; 43 | @end 44 | 45 | @interface IDEContainerItem : NSObject 46 | @property (readonly) DVTFilePath* resolvedFilePath; 47 | @end 48 | 49 | @interface IDEGroup : IDEContainerItem 50 | 51 | @end 52 | 53 | @interface IDEFileReference : IDEContainerItem 54 | 55 | @end 56 | 57 | @interface IDENavigableItem : NSObject 58 | @property (readonly) IDENavigableItem* parentItem; 59 | @property (readonly) id representedObject; 60 | 61 | @end 62 | 63 | @interface IDEFileNavigableItem : IDENavigableItem 64 | @property (readonly) DVTFileDataType* documentType; 65 | @property (readonly) NSURL* fileURL; 66 | @end 67 | 68 | @interface IDEStructureNavigator : NSObject 69 | @property (retain) NSArray* selectedObjects; 70 | @end 71 | 72 | @interface IDENavigableItemCoordinator : NSObject 73 | - (id)structureNavigableItemForDocumentURL:(id)arg1 inWorkspace:(id)arg2 error:(id*)arg3; 74 | @end 75 | 76 | @interface IDENavigatorArea : NSObject 77 | @property NSArrayController* extensionsController; 78 | - (id)currentNavigator; 79 | @end 80 | 81 | @interface IDEWorkspaceTabController : NSObject 82 | @property (readonly) IDENavigatorArea* navigatorArea; 83 | @property (readonly) IDEWorkspaceTabController* structureEditWorkspaceTabController; 84 | @end 85 | 86 | @interface IDEDocumentController : NSDocumentController 87 | + (IDEDocumentController*)sharedDocumentController; 88 | + (id)editorDocumentForNavigableItem:(id)arg1; 89 | + (id)retainedEditorDocumentForNavigableItem:(id)arg1 error:(id*)arg2; 90 | + (void)releaseEditorDocument:(id)arg1; 91 | 92 | @end 93 | 94 | @interface IDESourceCodeDocument : NSDocument 95 | - (DVTSourceTextStorage*)textStorage; 96 | - (NSUndoManager*)undoManager; 97 | @end 98 | 99 | @interface IDESourceCodeComparisonEditor : NSObject 100 | @property (readonly) NSTextView* keyTextView; 101 | @property (retain) NSDocument* primaryDocument; 102 | @end 103 | 104 | @interface IDESourceCodeEditor : NSObject 105 | @property (retain) NSTextView* textView; 106 | - (IDESourceCodeDocument*)sourceCodeDocument; 107 | @end 108 | 109 | @interface IDEEditorContext : NSObject 110 | - (id)editor; // returns the current editor. If the editor is the code editor, the class is `IDESourceCodeEditor` 111 | @end 112 | 113 | @interface IDEEditorArea : NSObject 114 | - (IDEEditorContext*)lastActiveEditorContext; 115 | @end 116 | 117 | @interface IDEConsoleArea : NSObject 118 | - (IDEEditorContext*)lastActiveEditorContext; 119 | @end 120 | 121 | @interface IDEWorkspaceWindowController : NSObject 122 | @property (readonly) IDEWorkspaceTabController* activeWorkspaceTabController; 123 | - (IDEEditorArea*)editorArea; 124 | @end 125 | 126 | @interface IDEWorkspace : NSWorkspace 127 | @property (readonly) DVTFilePath* representingFilePath; 128 | @end 129 | 130 | @interface IDEWorkspaceDocument : NSDocument 131 | @property (readonly) IDEWorkspace* workspace; 132 | @end 133 | 134 | 135 | @interface XcodeHelper : NSObject 136 | 137 | + (IDEWorkspaceDocument*)currentWorkspaceDocument; 138 | + (NSArray *)findLocalizedStringFilesPath:(NSString *)projectDir; 139 | 140 | @end -------------------------------------------------------------------------------- /AMLocalizedStringBuilder/XcodeHelper.m: -------------------------------------------------------------------------------- 1 | // 2 | // XcodeHelper.m 3 | // AMLocalizedStringBuilder 4 | // 5 | // Created by Mellong on 16/3/28. 6 | // Copyright © 2016年 tendencystudio. All rights reserved. 7 | // 8 | 9 | 10 | #import "XcodeHelper.h" 11 | 12 | @implementation XcodeHelper 13 | 14 | + (IDEWorkspaceDocument*)currentWorkspaceDocument 15 | { 16 | NSWindowController* currentWindowController = 17 | [[NSApp mainWindow] windowController]; 18 | id document = [currentWindowController document]; 19 | if (currentWindowController && 20 | [document isKindOfClass:NSClassFromString(@"IDEWorkspaceDocument")]) { 21 | return (IDEWorkspaceDocument*)document; 22 | } 23 | return nil; 24 | } 25 | 26 | 27 | + (NSArray *)findLocalizedStringFilesPath:(NSString *)projectDir 28 | { 29 | NSTask* task = [[NSTask alloc] init]; 30 | [task setLaunchPath:@"/bin/bash"]; 31 | NSString* shellPath = 32 | [[NSBundle bundleForClass:[self class]] pathForResource:@"FindLocalizedStringFiles" 33 | ofType:@"sh"]; 34 | [task setArguments:@[ shellPath , projectDir]]; 35 | 36 | 37 | NSPipe * result = [NSPipe pipe]; 38 | NSFileHandle *file = result.fileHandleForReading; 39 | [task setStandardOutput:result]; 40 | 41 | [task launch]; 42 | 43 | NSMutableData *data = [NSMutableData dataWithCapacity:512]; 44 | while ([task isRunning]) { 45 | [data appendData:[file readDataToEndOfFile]]; 46 | } 47 | 48 | [file closeFile]; 49 | NSString * stringRead = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 50 | 51 | NSPredicate *predicate = [NSPredicate predicateWithFormat:@"self != ''"]; 52 | NSArray *pathList = [[stringRead componentsSeparatedByString:@"\n"] filteredArrayUsingPredicate:predicate]; 53 | return pathList; 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | AMLocalizedStringBuilder 3 | ================== 4 | 5 |

6 | 7 | Build Status 8 | Platform: Xcode 6+ 9 | License: MIT 10 | 11 |

12 | 13 | AMLocalizedStringBuilder is the localized string helper which help you build your loacalized string file `Localizable.strings` to object-c class `AMLocalizedString`, and you can use your localized string key by `R_String.am_<#your_localized_string_key#>`, the shortcut key is `ctrl+f`. 14 | 15 | > *AMLocalizedStringBuilder 是可以帮助你将语言本地化文件`Localizable.strings`生成object-c的类`AMLocalizedString`的Xcode插件,这样可以直接使用`R_String.am_<#你的本地化字符串key#>`获取对应key的值,还可以随时点击`Alt`或`Option`按键查看当前字符串的值。* 16 | **如果觉得这款插件不错的话请点击右上角的star和推荐给你的朋友,如果想即时了解到我的最新消息,请拉到底部扫描二维码关注我的公众号。** 17 | 18 | ## Usage 19 | 1. Click Xcode Menu `Product`->`AMLocalizedStringBuilder`->`Build Localized String` or use shortcut `ctrl+f` to build the `Localizable.strings` file. 20 | 2. Open your project folder will find these two files: `AMLocalizedString.h` and `AMLocalizedString.m`, add these two files reference to your project. 21 | 3. Import `AMLocalizedString.h` and use `R_String.am_<#your_localized_string_key#>` to get the localized string. 22 | 4. On the other hand, you can use shortcut `ctrl+cmd+s` to show the setting window, choose the target localizable string file you want to build, and click `ctrl+f` to build. 23 | 24 | > *1. 点击Xcode顶部菜单 `Product`->`AMLocalizedStringBuilder`->`Build Localized String` 或者直接用快捷键 `ctrl+f` 来把`Localizable.strings`生成为object-c类。* 25 | *2. 打开你当前项目文件夹,可以找到已经生成好的 `AMLocalizedString.h` and `AMLocalizedString.m` 这两个文件,把他们直接拉到项目中添加引用。* 26 | *3. 在要用到的地方先导入头文件 `AMLocalizedString.h`, 然后使用`R_String.am_<#your_localized_string_key#>`来获取对应本地化的文字。* 27 | *4. 另外,你还可以用快捷键`ctrl+cmd+s`打开设置窗口,在设置窗口里面选择你要进行转换的`Localizable.strings`文件。* 28 | 29 | ![screenshot.gif](https://raw.github.com/MellongLau/AMLocalizedStringBuilder-Xcode-Plugin/master/Screenshots/screenshot.gif) 30 | 31 | ## Install 32 | 33 | You can: 34 | 35 | Install from github. 36 | 37 | * Get the source code from github 38 | 39 | `$ git clone git@github.com:MellongLau/AMLocalizedStringBuilder-Xcode-Plugin.git` 40 | 41 | * Build the AMLocalizedStringBuilder target in the Xcode project and the plug-in will automatically be installed in `~/Library/Application Support/Developer/Shared/Xcode/Plug-ins`. 42 | * Relaunch Xcode. 43 | 44 | or 45 | 46 | Install via [Alcatraz](http://alcatraz.io/) 47 | 48 | In any case, relaunch Xcode to load it. 49 | 50 | 51 | ## Support 52 | 53 | Developed and tested against Xcode 6+. 54 | 55 | For Xcode7.1, you may need to run shell script: 56 | ```shell 57 | find ~/Library/Application\ Support/Developer/Shared/Xcode/Plug-ins -name Info.plist -maxdepth 3 | xargs -I{} defaults write {} DVTPlugInCompatibilityUUIDs -array-add defaults read /Applications/Xcode.app/Contents/Info DVTPlugInCompatibilityUUID 58 | 59 | sudo xcode-select --reset 60 | 61 | defaults delete com.apple.dt.Xcode DVTPlugInManagerNonApplePlugIns-Xcode-7.1 62 | 63 | ``` 64 | 65 | Or download and execute this [script](https://github.com/cielpy/RPAXU) to add your current Xcode DVTPlugInCompatibilityUUID to all the Xcode plugins. 66 | 67 | 68 | ## License 69 | 70 | MIT License 71 | 72 | Copyright (c) 2016 Mellong Lau 73 | 74 | Permission is hereby granted, free of charge, to any person obtaining a copy 75 | of this software and associated documentation files (the "Software"), to deal 76 | in the Software without restriction, including without limitation the rights 77 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 78 | copies of the Software, and to permit persons to whom the Software is 79 | furnished to do so, subject to the following conditions: 80 | 81 | The above copyright notice and this permission notice shall be included in all 82 | copies or substantial portions of the Software. 83 | 84 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 85 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 86 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 87 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 88 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 89 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 90 | SOFTWARE. 91 | -------------------------------------------------------------------------------- /Screenshots/screenshot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MellongLau/AMLocalizedStringBuilder-Xcode-Plugin/a6db3d1a2f66399bcf91307ad7666dcb4660ead5/Screenshots/screenshot.gif --------------------------------------------------------------------------------