Phecda

feat: add RNLocalize

... ... @@ -12,6 +12,7 @@ import React from 'react';
import { DarkModeProvider } from 'react-native-dark-mode';
import { enableScreens } from 'react-native-screens';
import AppNavigationContainer from './src/screen/AppNavigationContainer';
import { I18NProvider } from './src/i18n';
if (__DEV__) {
const whyDidYouRender = require('@welldone-software/why-did-you-render');
... ... @@ -24,9 +25,11 @@ enableScreens();
const App = () => {
return (
<I18NProvider>
<DarkModeProvider>
<AppNavigationContainer />
</DarkModeProvider>
</I18NProvider>
);
};
... ...
... ... @@ -64,6 +64,7 @@
8362A23EE219E5DDEC7EAE08 /* libPods-NGPlay-tvOSTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-NGPlay-tvOSTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
B9229FB3695E83651E4D11D5 /* Pods-NGPlay-tvOSTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NGPlay-tvOSTests.release.xcconfig"; path = "Target Support Files/Pods-NGPlay-tvOSTests/Pods-NGPlay-tvOSTests.release.xcconfig"; sourceTree = "<group>"; };
C4732ECC7CC9112665571B01 /* libPods-NGPlay-NGPlayTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-NGPlay-NGPlayTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
CE18667F24480E4200FBDC7A /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/LaunchScreen.strings"; sourceTree = "<group>"; };
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
ED2971642150620600B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS12.0.sdk/System/Library/Frameworks/JavaScriptCore.framework; sourceTree = DEVELOPER_DIR; };
F63897AFB5B07795089F34F9 /* Pods-NGPlay-tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NGPlay-tvOS.release.xcconfig"; path = "Target Support Files/Pods-NGPlay-tvOS/Pods-NGPlay-tvOS.release.xcconfig"; sourceTree = "<group>"; };
... ... @@ -314,6 +315,7 @@
knownRegions = (
en,
Base,
"zh-Hans",
);
mainGroup = 83CBB9F61A601CBA00E9B192;
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
... ... @@ -670,6 +672,7 @@
isa = PBXVariantGroup;
children = (
13B07FB21A68108700A75B9A /* Base */,
CE18667F24480E4200FBDC7A /* zh-Hans */,
);
name = LaunchScreen.xib;
path = NGPlay;
... ...
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7702" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="16096" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7701"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16086"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
... ... @@ -12,20 +13,20 @@
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Powered by React Native" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="Powered by React Native" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
<rect key="frame" x="20" y="439" width="441" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="NGPlay" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="NGPlay" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
<rect key="frame" x="20" y="140" width="441" height="43"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
<constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
... ...
/* Class = "UILabel"; text = "Powered by React Native"; ObjectID = "8ie-xW-0ye"; */
"8ie-xW-0ye.text" = "React Native";
/* Class = "UILabel"; text = "NGPlay"; ObjectID = "kId-c2-rCX"; */
"kId-c2-rCX.text" = "NGPlay";
... ...
... ... @@ -306,6 +306,8 @@ PODS:
- React
- RNGestureHandler (1.6.1):
- React
- RNLocalize (1.4.0):
- React
- RNReanimated (1.7.1):
- React
- RNScreens (2.4.0):
... ... @@ -356,6 +358,7 @@ DEPENDENCIES:
- "RNCMaskedView (from `../node_modules/@react-native-community/masked-view`)"
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
- RNLocalize (from `../node_modules/react-native-localize`)
- RNReanimated (from `../node_modules/react-native-reanimated`)
- RNScreens (from `../node_modules/react-native-screens`)
- RNVectorIcons (from `../node_modules/react-native-vector-icons`)
... ... @@ -439,6 +442,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-device-info"
RNGestureHandler:
:path: "../node_modules/react-native-gesture-handler"
RNLocalize:
:path: "../node_modules/react-native-localize"
RNReanimated:
:path: "../node_modules/react-native-reanimated"
RNScreens:
... ... @@ -491,6 +496,7 @@ SPEC CHECKSUMS:
RNCMaskedView: 76c40a1d41c3e2535df09246a2b5487f04de0814
RNDeviceInfo: 6a3d16fce033f6979c4a6a41e62244d183e8c765
RNGestureHandler: 8f09cd560f8d533eb36da5a6c5a843af9f056b38
RNLocalize: b6df30cc25ae736d37874f9bce13351db2f56796
RNReanimated: 4e102df74a9674fa943e05f97f3362b6e44d0b48
RNScreens: b5c0e1b2b04512919e78bd3898e144a157ce2363
RNVectorIcons: 0bb4def82230be1333ddaeee9fcba45f0b288ed4
... ...
... ... @@ -27,6 +27,7 @@
"react-native-device-info": "^5.5.4",
"react-native-elements": "^1.2.7",
"react-native-gesture-handler": "^1.6.1",
"react-native-localize": "^1.4.0",
"react-native-progress": "^4.1.2",
"react-native-reanimated": "^1.7.1",
"react-native-safe-area-context": "^0.7.3",
... ...
import React, { useState, useEffect, FC, useContext, useCallback } from 'react';
import * as RNLocalize from 'react-native-localize';
import { I18NStrings, en } from './en';
import { zh } from './zh';
import { I18nManager } from 'react-native';
const availableTranslations = { en, zh };
const I18NContext = React.createContext<I18NStrings>(en);
export const I18NProvider: FC = ({ children }) => {
const [translation, setTranslation] = useState(en);
const updateTranslation = useCallback(() => {
const fallback = { languageTag: 'en', isRTL: false } as const;
const { languageTag, isRTL } =
RNLocalize.findBestAvailableLanguage(['en', 'zh']) || fallback;
I18nManager.forceRTL(isRTL);
setTranslation(availableTranslations[languageTag]);
}, []);
useEffect(() => {
updateTranslation();
RNLocalize.addEventListener('change', updateTranslation);
return () => {
RNLocalize.removeEventListener('change', updateTranslation);
};
}, [updateTranslation]);
return (
<I18NContext.Provider value={translation}>{children}</I18NContext.Provider>
);
};
export function useI18nStrings() {
return useContext(I18NContext);
}
... ...
export const en = {
name: 'English',
navigation: {
back: 'Back',
},
};
export type I18NStrings = typeof en;
... ...
export * from './I18NContext';
... ...
import { I18NStrings } from './en';
export const zh: I18NStrings = {
name: '中文',
navigation: {
back: '返回',
},
};
... ...
... ... @@ -18,6 +18,8 @@ import { themeForNav } from '../design';
import RNDeviceInfoList from './RNDeviceInfo';
import WebviewScreen from './WebviewScreen';
import { Platform } from 'react-native';
import RNLocalize from './RNLocalize';
import { useI18nStrings } from '../i18n';
const MainTab = createBottomTabNavigator<MainTabParamList>();
... ... @@ -78,6 +80,7 @@ const MainStack = createStackNavigator<MainStackParamList>();
const Container = () => {
const inDarkMode = useDarkMode();
const strings = useI18nStrings();
return (
<NavigationContainer
theme={inDarkMode ? themeForNav.dark : themeForNav.light}
... ... @@ -85,6 +88,7 @@ const Container = () => {
<MainStack.Navigator
screenOptions={{
headerStyleInterpolator: HeaderStyleInterpolators.forUIKit,
headerTruncatedBackTitle: strings.navigation.back,
}}
>
<MainStack.Screen
... ... @@ -106,6 +110,7 @@ const Container = () => {
animationEnabled: Platform.OS === 'ios',
})}
/>
<MainStack.Screen name="RNLocalize" component={RNLocalize} />
</MainStack.Navigator>
</NavigationContainer>
);
... ...
import React from 'react';
import * as LocalizeModule from 'react-native-localize';
import { BGList, ListItem } from '../component/View';
const keys = [
'getCalendar',
'getCountry',
'getCurrencies',
'getLocales',
'getNumberFormatSettings',
'getTemperatureUnit',
'getTimeZone',
'uses24HourClock',
'usesMetricSystem',
'usesAutoDateAndTime',
'usesAutoTimeZone',
] as const;
const RNLocalize = () => {
return (
<BGList
data={keys}
renderItem={({ item }) => (
<ListItem
title={item}
rightTitle={JSON.stringify(LocalizeModule[item]())}
/>
)}
/>
);
};
export default RNLocalize;
... ...
... ... @@ -3,6 +3,7 @@ import { useWindowDimensions } from 'react-native';
import { screensEnabled } from 'react-native-screens';
import { ListItem, BGScroll, Card, Divider } from '../component/View';
import { MainTabScreenProps } from '../type/Navigation';
import { useI18nStrings } from '../i18n';
declare var global: { HermesInternal: null | {} };
... ... @@ -10,6 +11,7 @@ const SystemInfo = ({
navigation,
route,
}: MainTabScreenProps<'SystemInfo'>) => {
const strings = useI18nStrings();
const { width, height, fontScale, scale } = useWindowDimensions();
return (
<BGScroll white>
... ... @@ -56,6 +58,14 @@ const SystemInfo = ({
uri: 'https://www.baidu.com',
})
}
chevron
/>
<Divider />
<ListItem
title={'RNLocalize'}
onPress={() => navigation.navigate('RNLocalize')}
rightTitle={strings.name}
chevron
/>
</Card>
</BGScroll>
... ...
... ... @@ -11,6 +11,7 @@ export type MainStackParamList = {
MainTab: undefined;
RNDeviceInfoList: undefined;
WebviewScreen: { uri: string } | undefined;
RNLocalize: undefined;
};
export type MainTabScreenProps<RouteName extends keyof MainTabParamList> = {
... ...
... ... @@ -6920,6 +6920,11 @@ react-native-iphone-x-helper@^1.2.1:
resolved "https://registry.npm.taobao.org/react-native-iphone-x-helper/download/react-native-iphone-x-helper-1.2.1.tgz#645e2ffbbb49e80844bb4cbbe34a126fda1e6772"
integrity sha1-ZF4v+7tJ6AhEu0y740oSb9oeZ3I=
react-native-localize@^1.4.0:
version "1.4.0"
resolved "https://registry.npm.taobao.org/react-native-localize/download/react-native-localize-1.4.0.tgz#4653596d066d0941c48f5404dc1c0d08b6950443"
integrity sha1-RlNZbQZtCUHEj1QE3BwNCLaVBEM=
react-native-progress@^4.1.2:
version "4.1.2"
resolved "https://registry.npm.taobao.org/react-native-progress/download/react-native-progress-4.1.2.tgz#ffb2264ddfeba409c730e36a9791bb7bbe07a00d"
... ...