This commit is contained in:
commit
a82ae4982b
|
@ -0,0 +1,44 @@
|
|||
node_modules/**/*
|
||||
|
||||
# Xcode
|
||||
#
|
||||
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
|
||||
|
||||
## Build generated
|
||||
build/
|
||||
DerivedData
|
||||
|
||||
## Various settings
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata
|
||||
|
||||
## Other
|
||||
*.xccheckout
|
||||
*.moved-aside
|
||||
*.xcuserstate
|
||||
|
||||
## Obj-C/Swift specific
|
||||
*.hmap
|
||||
*.ipa
|
||||
|
||||
# CocoaPods
|
||||
#
|
||||
# We recommend against adding the Pods directory to your .gitignore. However
|
||||
# you should judge for yourself, the pros and cons are mentioned at:
|
||||
# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
||||
#
|
||||
#Pods/
|
||||
|
||||
# Carthage
|
||||
#
|
||||
# Add this line if you want to avoid checking in source code from Carthage dependencies.
|
||||
# Carthage/Checkouts
|
||||
|
||||
Carthage/Build
|
|
@ -0,0 +1,391 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
CDD7BF7C1B2D5125006FDA75 /* RNI18n.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = CDD7BF7B1B2D5125006FDA75 /* RNI18n.h */; };
|
||||
CDD7BF7E1B2D5125006FDA75 /* RNI18n.m in Sources */ = {isa = PBXBuildFile; fileRef = CDD7BF7D1B2D5125006FDA75 /* RNI18n.m */; };
|
||||
CDD7BF841B2D5126006FDA75 /* libRNI18n.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CDD7BF781B2D5125006FDA75 /* libRNI18n.a */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
CDD7BF851B2D5126006FDA75 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = CDD7BF701B2D5125006FDA75 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = CDD7BF771B2D5125006FDA75;
|
||||
remoteInfo = RNI18n;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
CDD7BF761B2D5125006FDA75 /* CopyFiles */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "include/$(PRODUCT_NAME)";
|
||||
dstSubfolderSpec = 16;
|
||||
files = (
|
||||
CDD7BF7C1B2D5125006FDA75 /* RNI18n.h in CopyFiles */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
CDD7BF781B2D5125006FDA75 /* libRNI18n.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNI18n.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
CDD7BF7B1B2D5125006FDA75 /* RNI18n.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNI18n.h; sourceTree = "<group>"; };
|
||||
CDD7BF7D1B2D5125006FDA75 /* RNI18n.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNI18n.m; sourceTree = "<group>"; };
|
||||
CDD7BF831B2D5126006FDA75 /* RNI18nTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RNI18nTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
CDD7BF891B2D5126006FDA75 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
CDD7BF751B2D5125006FDA75 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
CDD7BF801B2D5126006FDA75 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
CDD7BF841B2D5126006FDA75 /* libRNI18n.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
CDD7BF6F1B2D5125006FDA75 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CDD7BF7A1B2D5125006FDA75 /* RNI18n */,
|
||||
CDD7BF871B2D5126006FDA75 /* RNI18nTests */,
|
||||
CDD7BF791B2D5125006FDA75 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CDD7BF791B2D5125006FDA75 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CDD7BF781B2D5125006FDA75 /* libRNI18n.a */,
|
||||
CDD7BF831B2D5126006FDA75 /* RNI18nTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CDD7BF7A1B2D5125006FDA75 /* RNI18n */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CDD7BF7B1B2D5125006FDA75 /* RNI18n.h */,
|
||||
CDD7BF7D1B2D5125006FDA75 /* RNI18n.m */,
|
||||
);
|
||||
path = RNI18n;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CDD7BF871B2D5126006FDA75 /* RNI18nTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CDD7BF881B2D5126006FDA75 /* Supporting Files */,
|
||||
);
|
||||
path = RNI18nTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
CDD7BF881B2D5126006FDA75 /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CDD7BF891B2D5126006FDA75 /* Info.plist */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
CDD7BF771B2D5125006FDA75 /* RNI18n */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = CDD7BF8C1B2D5126006FDA75 /* Build configuration list for PBXNativeTarget "RNI18n" */;
|
||||
buildPhases = (
|
||||
CDD7BF741B2D5125006FDA75 /* Sources */,
|
||||
CDD7BF751B2D5125006FDA75 /* Frameworks */,
|
||||
CDD7BF761B2D5125006FDA75 /* CopyFiles */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = RNI18n;
|
||||
productName = RNI18n;
|
||||
productReference = CDD7BF781B2D5125006FDA75 /* libRNI18n.a */;
|
||||
productType = "com.apple.product-type.library.static";
|
||||
};
|
||||
CDD7BF821B2D5126006FDA75 /* RNI18nTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = CDD7BF8F1B2D5126006FDA75 /* Build configuration list for PBXNativeTarget "RNI18nTests" */;
|
||||
buildPhases = (
|
||||
CDD7BF7F1B2D5126006FDA75 /* Sources */,
|
||||
CDD7BF801B2D5126006FDA75 /* Frameworks */,
|
||||
CDD7BF811B2D5126006FDA75 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
CDD7BF861B2D5126006FDA75 /* PBXTargetDependency */,
|
||||
);
|
||||
name = RNI18nTests;
|
||||
productName = RNI18nTests;
|
||||
productReference = CDD7BF831B2D5126006FDA75 /* RNI18nTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
CDD7BF701B2D5125006FDA75 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0630;
|
||||
ORGANIZATIONNAME = "Alexander Zaytsev";
|
||||
TargetAttributes = {
|
||||
CDD7BF771B2D5125006FDA75 = {
|
||||
CreatedOnToolsVersion = 6.3.2;
|
||||
};
|
||||
CDD7BF821B2D5126006FDA75 = {
|
||||
CreatedOnToolsVersion = 6.3.2;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = CDD7BF731B2D5125006FDA75 /* Build configuration list for PBXProject "RNI18n" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = CDD7BF6F1B2D5125006FDA75;
|
||||
productRefGroup = CDD7BF791B2D5125006FDA75 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
CDD7BF771B2D5125006FDA75 /* RNI18n */,
|
||||
CDD7BF821B2D5126006FDA75 /* RNI18nTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
CDD7BF811B2D5126006FDA75 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
CDD7BF741B2D5125006FDA75 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
CDD7BF7E1B2D5125006FDA75 /* RNI18n.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
CDD7BF7F1B2D5126006FDA75 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
CDD7BF861B2D5126006FDA75 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = CDD7BF771B2D5125006FDA75 /* RNI18n */;
|
||||
targetProxy = CDD7BF851B2D5126006FDA75 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
CDD7BF8A1B2D5126006FDA75 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
CDD7BF8B1B2D5126006FDA75 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
CDD7BF8D1B2D5126006FDA75 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../reach-native/React/**",
|
||||
"$(SRCROOT)/node_modules/react-native/React/**",
|
||||
);
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
CDD7BF8E1B2D5126006FDA75 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(SRCROOT)/../reach-native/React/**",
|
||||
"$(SRCROOT)/node_modules/react-native/React/**",
|
||||
);
|
||||
OTHER_LDFLAGS = "-ObjC";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
CDD7BF901B2D5126006FDA75 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = RNI18nTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
CDD7BF911B2D5126006FDA75 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = RNI18nTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
CDD7BF731B2D5125006FDA75 /* Build configuration list for PBXProject "RNI18n" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
CDD7BF8A1B2D5126006FDA75 /* Debug */,
|
||||
CDD7BF8B1B2D5126006FDA75 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
CDD7BF8C1B2D5126006FDA75 /* Build configuration list for PBXNativeTarget "RNI18n" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
CDD7BF8D1B2D5126006FDA75 /* Debug */,
|
||||
CDD7BF8E1B2D5126006FDA75 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
CDD7BF8F1B2D5126006FDA75 /* Build configuration list for PBXNativeTarget "RNI18nTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
CDD7BF901B2D5126006FDA75 /* Debug */,
|
||||
CDD7BF911B2D5126006FDA75 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = CDD7BF701B2D5125006FDA75 /* Project object */;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:RNI18n.xcodeproj">
|
||||
</FileRef>
|
||||
</Workspace>
|
|
@ -0,0 +1,13 @@
|
|||
//
|
||||
// RNI18n.h
|
||||
// RNI18n
|
||||
//
|
||||
// Created by Alexander Zaytsev on 14/06/15.
|
||||
// Copyright (c) 2015 Alexander Zaytsev. All rights reserved.
|
||||
//
|
||||
|
||||
#import "RCTBridgeModule.h"
|
||||
|
||||
@interface RNI18n : NSObject <RCTBridgeModule>
|
||||
|
||||
@end
|
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// RNI18n.m
|
||||
// RNI18n
|
||||
//
|
||||
// Created by Alexander Zaytsev on 14/06/15.
|
||||
// Copyright (c) 2015 Alexander Zaytsev. All rights reserved.
|
||||
//
|
||||
|
||||
#import "RNI18n.h"
|
||||
|
||||
@implementation RNI18n
|
||||
RCT_EXPORT_MODULE();
|
||||
|
||||
-(NSString*) getCurrentLocale{
|
||||
NSString *localeString=[[NSLocale currentLocale] localeIdentifier];
|
||||
return localeString;
|
||||
}
|
||||
|
||||
- (NSDictionary *)constantsToExport
|
||||
{
|
||||
return @{ @"locale": [self getCurrentLocale] };
|
||||
}
|
||||
@end
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>lookastic.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,868 @@
|
|||
// I18n.js
|
||||
// =======
|
||||
//
|
||||
// This small library provides the Rails I18n API on the Javascript.
|
||||
// You don't actually have to use Rails (or even Ruby) to use I18n.js.
|
||||
// Just make sure you export all translations in an object like this:
|
||||
//
|
||||
// I18n.translations.en = {
|
||||
// hello: "Hello World"
|
||||
// };
|
||||
//
|
||||
// See tests for specific formatting like numbers and dates.
|
||||
//
|
||||
|
||||
;(function(factory) {
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
// Node/CommonJS
|
||||
module.exports = factory(this);
|
||||
} else if (typeof define === 'function' && define.amd) {
|
||||
// AMD
|
||||
var global=this;
|
||||
define('i18n', function(){ return factory(global);});
|
||||
} else {
|
||||
// Browser globals
|
||||
this.I18n = factory(this);
|
||||
}
|
||||
}(function(global) {
|
||||
"use strict";
|
||||
|
||||
// Use previously defined object if exists in current scope
|
||||
var I18n = global && global.I18n || {};
|
||||
|
||||
// Just cache the Array#slice function.
|
||||
var slice = Array.prototype.slice;
|
||||
|
||||
// Apply number padding.
|
||||
var padding = function(number) {
|
||||
return ("0" + number.toString()).substr(-2);
|
||||
};
|
||||
|
||||
// Set default days/months translations.
|
||||
var DATE = {
|
||||
day_names: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
|
||||
, abbr_day_names: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
|
||||
, month_names: [null, "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
|
||||
, abbr_month_names: [null, "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
|
||||
, meridian: ["AM", "PM"]
|
||||
};
|
||||
|
||||
// Set default number format.
|
||||
var NUMBER_FORMAT = {
|
||||
precision: 3
|
||||
, separator: "."
|
||||
, delimiter: ","
|
||||
, strip_insignificant_zeros: false
|
||||
};
|
||||
|
||||
// Set default currency format.
|
||||
var CURRENCY_FORMAT = {
|
||||
unit: "$"
|
||||
, precision: 2
|
||||
, format: "%u%n"
|
||||
, sign_first: true
|
||||
, delimiter: ","
|
||||
, separator: "."
|
||||
};
|
||||
|
||||
// Set default percentage format.
|
||||
var PERCENTAGE_FORMAT = {
|
||||
unit: "%"
|
||||
, precision: 3
|
||||
, format: "%n%u"
|
||||
, separator: "."
|
||||
, delimiter: ""
|
||||
};
|
||||
|
||||
// Set default size units.
|
||||
var SIZE_UNITS = [null, "kb", "mb", "gb", "tb"];
|
||||
|
||||
// Other default options
|
||||
var DEFAULT_OPTIONS = {
|
||||
// Set default locale. This locale will be used when fallback is enabled and
|
||||
// the translation doesn't exist in a particular locale.
|
||||
defaultLocale: "en"
|
||||
// Set the current locale to `en`.
|
||||
, locale: "en"
|
||||
// Set the translation key separator.
|
||||
, defaultSeparator: "."
|
||||
// Set the placeholder format. Accepts `{placeholder}}` and `%{placeholder}`.}
|
||||
, placeholder: /(?:\{\{|%\{)(.*?)(?:\}\}?)/gm
|
||||
// Set if engine should fallback to the default locale when a translation
|
||||
// is missing.
|
||||
, fallbacks: false
|
||||
// Set the default translation object.
|
||||
, translations: {}
|
||||
// Set missing translation behavior. 'message' will display a message
|
||||
// that the translation is missing, 'guess' will try to guess the string
|
||||
, missingBehaviour: 'message'
|
||||
// if you use missingBehaviour with 'message', but want to know that the
|
||||
// string is actually missing for testing purposes, you can prefix the
|
||||
// guessed string by setting the value here. By default, no prefix!
|
||||
, missingTranslationPrefix: ''
|
||||
};
|
||||
|
||||
I18n.reset = function() {
|
||||
// Set default locale. This locale will be used when fallback is enabled and
|
||||
// the translation doesn't exist in a particular locale.
|
||||
this.defaultLocale = DEFAULT_OPTIONS.defaultLocale;
|
||||
|
||||
// Set the current locale to `en`.
|
||||
this.locale = DEFAULT_OPTIONS.locale;
|
||||
|
||||
// Set the translation key separator.
|
||||
this.defaultSeparator = DEFAULT_OPTIONS.defaultSeparator;
|
||||
|
||||
// Set the placeholder format. Accepts `{{placeholder}}` and `%{placeholder}`.
|
||||
this.placeholder = DEFAULT_OPTIONS.placeholder;
|
||||
|
||||
// Set if engine should fallback to the default locale when a translation
|
||||
// is missing.
|
||||
this.fallbacks = DEFAULT_OPTIONS.fallbacks;
|
||||
|
||||
// Set the default translation object.
|
||||
this.translations = DEFAULT_OPTIONS.translations;
|
||||
|
||||
// Set the default missing behaviour
|
||||
this.missingBehaviour = DEFAULT_OPTIONS.missingBehaviour;
|
||||
|
||||
// Set the default missing string prefix for guess behaviour
|
||||
this.missingTranslationPrefix = DEFAULT_OPTIONS.missingTranslationPrefix;
|
||||
|
||||
};
|
||||
|
||||
// Much like `reset`, but only assign options if not already assigned
|
||||
I18n.initializeOptions = function() {
|
||||
if (typeof(this.defaultLocale) === "undefined" && this.defaultLocale !== null)
|
||||
this.defaultLocale = DEFAULT_OPTIONS.defaultLocale;
|
||||
|
||||
if (typeof(this.locale) === "undefined" && this.locale !== null)
|
||||
this.locale = DEFAULT_OPTIONS.locale;
|
||||
|
||||
if (typeof(this.defaultSeparator) === "undefined" && this.defaultSeparator !== null)
|
||||
this.defaultSeparator = DEFAULT_OPTIONS.defaultSeparator;
|
||||
|
||||
if (typeof(this.placeholder) === "undefined" && this.placeholder !== null)
|
||||
this.placeholder = DEFAULT_OPTIONS.placeholder;
|
||||
|
||||
if (typeof(this.fallbacks) === "undefined" && this.fallbacks !== null)
|
||||
this.fallbacks = DEFAULT_OPTIONS.fallbacks;
|
||||
|
||||
if (typeof(this.translations) === "undefined" && this.translations !== null)
|
||||
this.translations = DEFAULT_OPTIONS.translations;
|
||||
};
|
||||
I18n.initializeOptions();
|
||||
|
||||
// Return a list of all locales that must be tried before returning the
|
||||
// missing translation message. By default, this will consider the inline option,
|
||||
// current locale and fallback locale.
|
||||
//
|
||||
// I18n.locales.get("de-DE");
|
||||
// // ["de-DE", "de", "en"]
|
||||
//
|
||||
// You can define custom rules for any locale. Just make sure you return a array
|
||||
// containing all locales.
|
||||
//
|
||||
// // Default the Wookie locale to English.
|
||||
// I18n.locales["wk"] = function(locale) {
|
||||
// return ["en"];
|
||||
// };
|
||||
//
|
||||
I18n.locales = {};
|
||||
|
||||
// Retrieve locales based on inline locale, current locale or default to
|
||||
// I18n's detection.
|
||||
I18n.locales.get = function(locale) {
|
||||
var result = this[locale] || this[I18n.locale] || this["default"];
|
||||
|
||||
if (typeof(result) === "function") {
|
||||
result = result(locale);
|
||||
}
|
||||
|
||||
if (result instanceof Array === false) {
|
||||
result = [result];
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
// The default locale list.
|
||||
I18n.locales["default"] = function(locale) {
|
||||
var locales = []
|
||||
, list = []
|
||||
, countryCode
|
||||
, count
|
||||
;
|
||||
|
||||
// Handle the inline locale option that can be provided to
|
||||
// the `I18n.t` options.
|
||||
if (locale) {
|
||||
locales.push(locale);
|
||||
}
|
||||
|
||||
// Add the current locale to the list.
|
||||
if (!locale && I18n.locale) {
|
||||
locales.push(I18n.locale);
|
||||
}
|
||||
|
||||
// Add the default locale if fallback strategy is enabled.
|
||||
if (I18n.fallbacks && I18n.defaultLocale) {
|
||||
locales.push(I18n.defaultLocale);
|
||||
}
|
||||
|
||||
// Compute each locale with its country code.
|
||||
// So this will return an array containing both
|
||||
// `de-DE` and `de` locales.
|
||||
locales.forEach(function(locale){
|
||||
countryCode = locale.split("-")[0];
|
||||
|
||||
if (!~list.indexOf(locale)) {
|
||||
list.push(locale);
|
||||
}
|
||||
|
||||
if (I18n.fallbacks && countryCode && countryCode !== locale && !~list.indexOf(countryCode)) {
|
||||
list.push(countryCode);
|
||||
}
|
||||
});
|
||||
|
||||
// No locales set? English it is.
|
||||
if (!locales.length) {
|
||||
locales.push("en");
|
||||
}
|
||||
|
||||
return list;
|
||||
};
|
||||
|
||||
// Hold pluralization rules.
|
||||
I18n.pluralization = {};
|
||||
|
||||
// Return the pluralizer for a specific locale.
|
||||
// If no specify locale is found, then I18n's default will be used.
|
||||
I18n.pluralization.get = function(locale) {
|
||||
return this[locale] || this[I18n.locale] || this["default"];
|
||||
};
|
||||
|
||||
// The default pluralizer rule.
|
||||
// It detects the `zero`, `one`, and `other` scopes.
|
||||
I18n.pluralization["default"] = function(count) {
|
||||
switch (count) {
|
||||
case 0: return ["zero", "other"];
|
||||
case 1: return ["one"];
|
||||
default: return ["other"];
|
||||
}
|
||||
};
|
||||
|
||||
// Return current locale. If no locale has been set, then
|
||||
// the current locale will be the default locale.
|
||||
I18n.currentLocale = function() {
|
||||
return this.locale || this.defaultLocale;
|
||||
};
|
||||
|
||||
// Check if value is different than undefined and null;
|
||||
I18n.isSet = function(value) {
|
||||
return value !== undefined && value !== null;
|
||||
};
|
||||
|
||||
// Find and process the translation using the provided scope and options.
|
||||
// This is used internally by some functions and should not be used as an
|
||||
// public API.
|
||||
I18n.lookup = function(scope, options) {
|
||||
options = this.prepareOptions(options);
|
||||
|
||||
var locales = this.locales.get(options.locale).slice()
|
||||
, requestedLocale = locales[0]
|
||||
, locale
|
||||
, scopes
|
||||
, translations
|
||||
;
|
||||
|
||||
scope = this.getFullScope(scope, options);
|
||||
|
||||
while (locales.length) {
|
||||
locale = locales.shift();
|
||||
scopes = scope.split(this.defaultSeparator);
|
||||
translations = this.translations[locale];
|
||||
|
||||
if (!translations) {
|
||||
continue;
|
||||
}
|
||||
|
||||
while (scopes.length) {
|
||||
translations = translations[scopes.shift()];
|
||||
|
||||
if (translations === undefined || translations === null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (translations !== undefined && translations !== null) {
|
||||
return translations;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isSet(options.defaultValue)) {
|
||||
return options.defaultValue;
|
||||
}
|
||||
};
|
||||
|
||||
// Rails changed the way the meridian is stored.
|
||||
// It started with `date.meridian` returning an array,
|
||||
// then it switched to `time.am` and `time.pm`.
|
||||
// This function abstracts this difference and returns
|
||||
// the correct meridian or the default value when none is provided.
|
||||
I18n.meridian = function() {
|
||||
var time = this.lookup("time");
|
||||
var date = this.lookup("date");
|
||||
|
||||
if (time && time.am && time.pm) {
|
||||
return [time.am, time.pm];
|
||||
} else if (date && date.meridian) {
|
||||
return date.meridian;
|
||||
} else {
|
||||
return DATE.meridian;
|
||||
}
|
||||
};
|
||||
|
||||
// Merge serveral hash options, checking if value is set before
|
||||
// overwriting any value. The precedence is from left to right.
|
||||
//
|
||||
// I18n.prepareOptions({name: "John Doe"}, {name: "Mary Doe", role: "user"});
|
||||
// #=> {name: "John Doe", role: "user"}
|
||||
//
|
||||
I18n.prepareOptions = function() {
|
||||
var args = slice.call(arguments)
|
||||
, options = {}
|
||||
, subject
|
||||
;
|
||||
|
||||
while (args.length) {
|
||||
subject = args.shift();
|
||||
|
||||
if (typeof(subject) != "object") {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var attr in subject) {
|
||||
if (!subject.hasOwnProperty(attr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this.isSet(options[attr])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
options[attr] = subject[attr];
|
||||
}
|
||||
}
|
||||
|
||||
return options;
|
||||
};
|
||||
|
||||
// Generate a list of translation options for default fallbacks.
|
||||
// `defaultValue` is also deleted from options as it is returned as part of
|
||||
// the translationOptions array.
|
||||
I18n.createTranslationOptions = function(scope, options) {
|
||||
var translationOptions = [{scope: scope}];
|
||||
|
||||
// Defaults should be an array of hashes containing either
|
||||
// fallback scopes or messages
|
||||
if (this.isSet(options.defaults)) {
|
||||
translationOptions = translationOptions.concat(options.defaults);
|
||||
}
|
||||
|
||||
// Maintain support for defaultValue. Since it is always a message
|
||||
// insert it in to the translation options as such.
|
||||
if (this.isSet(options.defaultValue)) {
|
||||
translationOptions.push({ message: options.defaultValue });
|
||||
delete options.defaultValue;
|
||||
}
|
||||
|
||||
return translationOptions;
|
||||
};
|
||||
|
||||
// Translate the given scope with the provided options.
|
||||
I18n.translate = function(scope, options) {
|
||||
options = this.prepareOptions(options);
|
||||
|
||||
var translationOptions = this.createTranslationOptions(scope, options);
|
||||
|
||||
var translation;
|
||||
// Iterate through the translation options until a translation
|
||||
// or message is found.
|
||||
var translationFound =
|
||||
translationOptions.some(function(translationOption) {
|
||||
if (this.isSet(translationOption.scope)) {
|
||||
translation = this.lookup(translationOption.scope, options);
|
||||
} else if (this.isSet(translationOption.message)) {
|
||||
translation = translationOption.message;
|
||||
}
|
||||
|
||||
if (translation !== undefined && translation !== null) {
|
||||
return true;
|
||||
}
|
||||
}, this);
|
||||
|
||||
if (!translationFound) {
|
||||
return this.missingTranslation(scope, options);
|
||||
}
|
||||
|
||||
if (typeof(translation) === "string") {
|
||||
translation = this.interpolate(translation, options);
|
||||
} else if (translation instanceof Object && this.isSet(options.count)) {
|
||||
translation = this.pluralize(options.count, translation, options);
|
||||
}
|
||||
|
||||
return translation;
|
||||
};
|
||||
|
||||
// This function interpolates the all variables in the given message.
|
||||
I18n.interpolate = function(message, options) {
|
||||
options = this.prepareOptions(options);
|
||||
var matches = message.match(this.placeholder)
|
||||
, placeholder
|
||||
, value
|
||||
, name
|
||||
, regex
|
||||
;
|
||||
|
||||
if (!matches) {
|
||||
return message;
|
||||
}
|
||||
|
||||
var value;
|
||||
|
||||
while (matches.length) {
|
||||
placeholder = matches.shift();
|
||||
name = placeholder.replace(this.placeholder, "$1");
|
||||
|
||||
if (this.isSet(options[name])) {
|
||||
value = options[name].toString().replace(/\$/gm, "_#$#_");
|
||||
} else if (name in options) {
|
||||
value = this.nullPlaceholder(placeholder, message);
|
||||
} else {
|
||||
value = this.missingPlaceholder(placeholder, message);
|
||||
}
|
||||
|
||||
regex = new RegExp(placeholder.replace(/\{/gm, "\\{").replace(/\}/gm, "\\}"));
|
||||
message = message.replace(regex, value);
|
||||
}
|
||||
|
||||
return message.replace(/_#\$#_/g, "$");
|
||||
};
|
||||
|
||||
// Pluralize the given scope using the `count` value.
|
||||
// The pluralized translation may have other placeholders,
|
||||
// which will be retrieved from `options`.
|
||||
I18n.pluralize = function(count, scope, options) {
|
||||
options = this.prepareOptions(options);
|
||||
var translations, pluralizer, keys, key, message;
|
||||
|
||||
if (scope instanceof Object) {
|
||||
translations = scope;
|
||||
} else {
|
||||
translations = this.lookup(scope, options);
|
||||
}
|
||||
|
||||
if (!translations) {
|
||||
return this.missingTranslation(scope, options);
|
||||
}
|
||||
|
||||
pluralizer = this.pluralization.get(options.locale);
|
||||
keys = pluralizer(count);
|
||||
|
||||
while (keys.length) {
|
||||
key = keys.shift();
|
||||
|
||||
if (this.isSet(translations[key])) {
|
||||
message = translations[key];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
options.count = String(count);
|
||||
return this.interpolate(message, options);
|
||||
};
|
||||
|
||||
// Return a missing translation message for the given parameters.
|
||||
I18n.missingTranslation = function(scope, options) {
|
||||
//guess intended string
|
||||
if(this.missingBehaviour == 'guess'){
|
||||
//get only the last portion of the scope
|
||||
var s = scope.split('.').slice(-1)[0];
|
||||
//replace underscore with space && camelcase with space and lowercase letter
|
||||
return (this.missingTranslationPrefix.length > 0 ? this.missingTranslationPrefix : '') +
|
||||
s.replace('_',' ').replace(/([a-z])([A-Z])/g,
|
||||
function(match, p1, p2) {return p1 + ' ' + p2.toLowerCase()} );
|
||||
}
|
||||
|
||||
var fullScope = this.getFullScope(scope, options);
|
||||
var fullScopeWithLocale = [this.currentLocale(), fullScope].join(this.defaultSeparator);
|
||||
|
||||
return '[missing "' + fullScopeWithLocale + '" translation]';
|
||||
};
|
||||
|
||||
// Return a missing placeholder message for given parameters
|
||||
I18n.missingPlaceholder = function(placeholder, message) {
|
||||
return "[missing " + placeholder + " value]";
|
||||
};
|
||||
|
||||
I18n.nullPlaceholder = function() {
|
||||
return I18n.missingPlaceholder.apply(I18n, arguments);
|
||||
};
|
||||
|
||||
// Format number using localization rules.
|
||||
// The options will be retrieved from the `number.format` scope.
|
||||
// If this isn't present, then the following options will be used:
|
||||
//
|
||||
// - `precision`: `3`
|
||||
// - `separator`: `"."`
|
||||
// - `delimiter`: `","`
|
||||
// - `strip_insignificant_zeros`: `false`
|
||||
//
|
||||
// You can also override these options by providing the `options` argument.
|
||||
//
|
||||
I18n.toNumber = function(number, options) {
|
||||
options = this.prepareOptions(
|
||||
options
|
||||
, this.lookup("number.format")
|
||||
, NUMBER_FORMAT
|
||||
);
|
||||
|
||||
var negative = number < 0
|
||||
, string = Math.abs(number).toFixed(options.precision).toString()
|
||||
, parts = string.split(".")
|
||||
, precision
|
||||
, buffer = []
|
||||
, formattedNumber
|
||||
, format = options.format || "%n"
|
||||
, sign = negative ? "-" : ""
|
||||
;
|
||||
|
||||
number = parts[0];
|
||||
precision = parts[1];
|
||||
|
||||
while (number.length > 0) {
|
||||
buffer.unshift(number.substr(Math.max(0, number.length - 3), 3));
|
||||
number = number.substr(0, number.length -3);
|
||||
}
|
||||
|
||||
formattedNumber = buffer.join(options.delimiter);
|
||||
|
||||
if (options.strip_insignificant_zeros && precision) {
|
||||
precision = precision.replace(/0+$/, "");
|
||||
}
|
||||
|
||||
if (options.precision > 0 && precision) {
|
||||
formattedNumber += options.separator + precision;
|
||||
}
|
||||
|
||||
if (options.sign_first) {
|
||||
format = "%s" + format;
|
||||
}
|
||||
else {
|
||||
format = format.replace("%n", "%s%n");
|
||||
}
|
||||
|
||||
formattedNumber = format
|
||||
.replace("%u", options.unit)
|
||||
.replace("%n", formattedNumber)
|
||||
.replace("%s", sign)
|
||||
;
|
||||
|
||||
return formattedNumber;
|
||||
};
|
||||
|
||||
// Format currency with localization rules.
|
||||
// The options will be retrieved from the `number.currency.format` and
|
||||
// `number.format` scopes, in that order.
|
||||
//
|
||||
// Any missing option will be retrieved from the `I18n.toNumber` defaults and
|
||||
// the following options:
|
||||
//
|
||||
// - `unit`: `"$"`
|
||||
// - `precision`: `2`
|
||||
// - `format`: `"%u%n"`
|
||||
// - `delimiter`: `","`
|
||||
// - `separator`: `"."`
|
||||
//
|
||||
// You can also override these options by providing the `options` argument.
|
||||
//
|
||||
I18n.toCurrency = function(number, options) {
|
||||
options = this.prepareOptions(
|
||||
options
|
||||
, this.lookup("number.currency.format")
|
||||
, this.lookup("number.format")
|
||||
, CURRENCY_FORMAT
|
||||
);
|
||||
|
||||
return this.toNumber(number, options);
|
||||
};
|
||||
|
||||
// Localize several values.
|
||||
// You can provide the following scopes: `currency`, `number`, or `percentage`.
|
||||
// If you provide a scope that matches the `/^(date|time)/` regular expression
|
||||
// then the `value` will be converted by using the `I18n.toTime` function.
|
||||
//
|
||||
// It will default to the value's `toString` function.
|
||||
//
|
||||
I18n.localize = function(scope, value, options) {
|
||||
options || (options = {});
|
||||
|
||||
switch (scope) {
|
||||
case "currency":
|
||||
return this.toCurrency(value);
|
||||
case "number":
|
||||
scope = this.lookup("number.format");
|
||||
return this.toNumber(value, scope);
|
||||
case "percentage":
|
||||
return this.toPercentage(value);
|
||||
default:
|
||||
var localizedValue;
|
||||
|
||||
if (scope.match(/^(date|time)/)) {
|
||||
localizedValue = this.toTime(scope, value);
|
||||
} else {
|
||||
localizedValue = value.toString();
|
||||
}
|
||||
|
||||
return this.interpolate(localizedValue, options);
|
||||
}
|
||||
};
|
||||
|
||||
// Parse a given `date` string into a JavaScript Date object.
|
||||
// This function is time zone aware.
|
||||
//
|
||||
// The following string formats are recognized:
|
||||
//
|
||||
// yyyy-mm-dd
|
||||
// yyyy-mm-dd[ T]hh:mm::ss
|
||||
// yyyy-mm-dd[ T]hh:mm::ss
|
||||
// yyyy-mm-dd[ T]hh:mm::ssZ
|
||||
// yyyy-mm-dd[ T]hh:mm::ss+0000
|
||||
// yyyy-mm-dd[ T]hh:mm::ss+00:00
|
||||
// yyyy-mm-dd[ T]hh:mm::ss.123Z
|
||||
//
|
||||
I18n.parseDate = function(date) {
|
||||
var matches, convertedDate, fraction;
|
||||
// we have a date, so just return it.
|
||||
if (typeof(date) == "object") {
|
||||
return date;
|
||||
};
|
||||
|
||||
matches = date.toString().match(/(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2}):(\d{2})([\.,]\d{1,3})?)?(Z|\+00:?00)?/);
|
||||
|
||||
if (matches) {
|
||||
for (var i = 1; i <= 6; i++) {
|
||||
matches[i] = parseInt(matches[i], 10) || 0;
|
||||
}
|
||||
|
||||
// month starts on 0
|
||||
matches[2] -= 1;
|
||||
|
||||
fraction = matches[7] ? 1000 * ("0" + matches[7]) : null;
|
||||
|
||||
if (matches[8]) {
|
||||
convertedDate = new Date(Date.UTC(matches[1], matches[2], matches[3], matches[4], matches[5], matches[6], fraction));
|
||||
} else {
|
||||
convertedDate = new Date(matches[1], matches[2], matches[3], matches[4], matches[5], matches[6], fraction);
|
||||
}
|
||||
} else if (typeof(date) == "number") {
|
||||
// UNIX timestamp
|
||||
convertedDate = new Date();
|
||||
convertedDate.setTime(date);
|
||||
} else if (date.match(/([A-Z][a-z]{2}) ([A-Z][a-z]{2}) (\d+) (\d+:\d+:\d+) ([+-]\d+) (\d+)/)) {
|
||||
// This format `Wed Jul 20 13:03:39 +0000 2011` is parsed by
|
||||
// webkit/firefox, but not by IE, so we must parse it manually.
|
||||
convertedDate = new Date();
|
||||
convertedDate.setTime(Date.parse([
|
||||
RegExp.$1, RegExp.$2, RegExp.$3, RegExp.$6, RegExp.$4, RegExp.$5
|
||||
].join(" ")));
|
||||
} else if (date.match(/\d+ \d+:\d+:\d+ [+-]\d+ \d+/)) {
|
||||
// a valid javascript format with timezone info
|
||||
convertedDate = new Date();
|
||||
convertedDate.setTime(Date.parse(date));
|
||||
} else {
|
||||
// an arbitrary javascript string
|
||||
convertedDate = new Date();
|
||||
convertedDate.setTime(Date.parse(date));
|
||||
}
|
||||
|
||||
return convertedDate;
|
||||
};
|
||||
|
||||
// Formats time according to the directives in the given format string.
|
||||
// The directives begins with a percent (%) character. Any text not listed as a
|
||||
// directive will be passed through to the output string.
|
||||
//
|
||||
// The accepted formats are:
|
||||
//
|
||||
// %a - The abbreviated weekday name (Sun)
|
||||
// %A - The full weekday name (Sunday)
|
||||
// %b - The abbreviated month name (Jan)
|
||||
// %B - The full month name (January)
|
||||
// %c - The preferred local date and time representation
|
||||
// %d - Day of the month (01..31)
|
||||
// %-d - Day of the month (1..31)
|
||||
// %H - Hour of the day, 24-hour clock (00..23)
|
||||
// %-H - Hour of the day, 24-hour clock (0..23)
|
||||
// %I - Hour of the day, 12-hour clock (01..12)
|
||||
// %-I - Hour of the day, 12-hour clock (1..12)
|
||||
// %m - Month of the year (01..12)
|
||||
// %-m - Month of the year (1..12)
|
||||
// %M - Minute of the hour (00..59)
|
||||
// %-M - Minute of the hour (0..59)
|
||||
// %p - Meridian indicator (AM or PM)
|
||||
// %S - Second of the minute (00..60)
|
||||
// %-S - Second of the minute (0..60)
|
||||
// %w - Day of the week (Sunday is 0, 0..6)
|
||||
// %y - Year without a century (00..99)
|
||||
// %-y - Year without a century (0..99)
|
||||
// %Y - Year with century
|
||||
// %z - Timezone offset (+0545)
|
||||
//
|
||||
I18n.strftime = function(date, format) {
|
||||
var options = this.lookup("date")
|
||||
, meridianOptions = I18n.meridian()
|
||||
;
|
||||
|
||||
if (!options) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
options = this.prepareOptions(options, DATE);
|
||||
|
||||
var weekDay = date.getDay()
|
||||
, day = date.getDate()
|
||||
, year = date.getFullYear()
|
||||
, month = date.getMonth() + 1
|
||||
, hour = date.getHours()
|
||||
, hour12 = hour
|
||||
, meridian = hour > 11 ? 1 : 0
|
||||
, secs = date.getSeconds()
|
||||
, mins = date.getMinutes()
|
||||
, offset = date.getTimezoneOffset()
|
||||
, absOffsetHours = Math.floor(Math.abs(offset / 60))
|
||||
, absOffsetMinutes = Math.abs(offset) - (absOffsetHours * 60)
|
||||
, timezoneoffset = (offset > 0 ? "-" : "+") +
|
||||
(absOffsetHours.toString().length < 2 ? "0" + absOffsetHours : absOffsetHours) +
|
||||
(absOffsetMinutes.toString().length < 2 ? "0" + absOffsetMinutes : absOffsetMinutes)
|
||||
;
|
||||
|
||||
if (hour12 > 12) {
|
||||
hour12 = hour12 - 12;
|
||||
} else if (hour12 === 0) {
|
||||
hour12 = 12;
|
||||
}
|
||||
|
||||
format = format.replace("%a", options.abbr_day_names[weekDay]);
|
||||
format = format.replace("%A", options.day_names[weekDay]);
|
||||
format = format.replace("%b", options.abbr_month_names[month]);
|
||||
format = format.replace("%B", options.month_names[month]);
|
||||
format = format.replace("%d", padding(day));
|
||||
format = format.replace("%e", day);
|
||||
format = format.replace("%-d", day);
|
||||
format = format.replace("%H", padding(hour));
|
||||
format = format.replace("%-H", hour);
|
||||
format = format.replace("%I", padding(hour12));
|
||||
format = format.replace("%-I", hour12);
|
||||
format = format.replace("%m", padding(month));
|
||||
format = format.replace("%-m", month);
|
||||
format = format.replace("%M", padding(mins));
|
||||
format = format.replace("%-M", mins);
|
||||
format = format.replace("%p", meridianOptions[meridian]);
|
||||
format = format.replace("%S", padding(secs));
|
||||
format = format.replace("%-S", secs);
|
||||
format = format.replace("%w", weekDay);
|
||||
format = format.replace("%y", padding(year));
|
||||
format = format.replace("%-y", padding(year).replace(/^0+/, ""));
|
||||
format = format.replace("%Y", year);
|
||||
format = format.replace("%z", timezoneoffset);
|
||||
|
||||
return format;
|
||||
};
|
||||
|
||||
// Convert the given dateString into a formatted date.
|
||||
I18n.toTime = function(scope, dateString) {
|
||||
var date = this.parseDate(dateString)
|
||||
, format = this.lookup(scope)
|
||||
;
|
||||
|
||||
if (date.toString().match(/invalid/i)) {
|
||||
return date.toString();
|
||||
}
|
||||
|
||||
if (!format) {
|
||||
return date.toString();
|
||||
}
|
||||
|
||||
return this.strftime(date, format);
|
||||
};
|
||||
|
||||
// Convert a number into a formatted percentage value.
|
||||
I18n.toPercentage = function(number, options) {
|
||||
options = this.prepareOptions(
|
||||
options
|
||||
, this.lookup("number.percentage.format")
|
||||
, this.lookup("number.format")
|
||||
, PERCENTAGE_FORMAT
|
||||
);
|
||||
|
||||
return this.toNumber(number, options);
|
||||
};
|
||||
|
||||
// Convert a number into a readable size representation.
|
||||
I18n.toHumanSize = function(number, options) {
|
||||
var kb = 1024
|
||||
, size = number
|
||||
, iterations = 0
|
||||
, unit
|
||||
, precision
|
||||
;
|
||||
|
||||
while (size >= kb && iterations < 4) {
|
||||
size = size / kb;
|
||||
iterations += 1;
|
||||
}
|
||||
|
||||
if (iterations === 0) {
|
||||
unit = this.t("number.human.storage_units.units.byte", {count: size});
|
||||
precision = 0;
|
||||
} else {
|
||||
unit = this.t("number.human.storage_units.units." + SIZE_UNITS[iterations]);
|
||||
precision = (size - Math.floor(size) === 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
options = this.prepareOptions(
|
||||
options
|
||||
, {unit: unit, precision: precision, format: "%n%u", delimiter: ""}
|
||||
);
|
||||
|
||||
return this.toNumber(size, options);
|
||||
};
|
||||
|
||||
I18n.getFullScope = function(scope, options) {
|
||||
options = this.prepareOptions(options);
|
||||
|
||||
// Deal with the scope as an array.
|
||||
if (scope.constructor === Array) {
|
||||
scope = scope.join(this.defaultSeparator);
|
||||
}
|
||||
|
||||
// Deal with the scope option provided through the second argument.
|
||||
//
|
||||
// I18n.t('hello', {scope: 'greetings'});
|
||||
//
|
||||
if (options.scope) {
|
||||
scope = [options.scope, scope].join(this.defaultSeparator);
|
||||
}
|
||||
|
||||
return scope;
|
||||
}
|
||||
|
||||
// Set aliases, so we can save some typing.
|
||||
I18n.t = I18n.translate;
|
||||
I18n.l = I18n.localize;
|
||||
I18n.p = I18n.pluralize;
|
||||
|
||||
return I18n;
|
||||
}));
|
|
@ -0,0 +1,7 @@
|
|||
var React = require('react-native');
|
||||
var I18n = require('i18n');
|
||||
var { NativeI18n } = require('react-native').NativeModules;
|
||||
|
||||
I18n.locale = NativeI18n.locale;
|
||||
|
||||
module.exports = I18n;
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"name": "react-native-i18n",
|
||||
"version": "0.0.1",
|
||||
"description": "React Native and I18n.js integration",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "github.com:AlexanderZaytsev/react-native-i18n.git"
|
||||
},
|
||||
"keywords": [
|
||||
"react-native",
|
||||
"i18n"
|
||||
],
|
||||
"author": "Alexander Zaytsev",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"react-native": "^0.5.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react-native": "^0.5.0"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue