Skip to content

Commit

Permalink
Merge pull request #9 from daboigbae/enhancement/add-localization
Browse files Browse the repository at this point in the history
Added localization
  • Loading branch information
daboigbae authored Nov 30, 2022
2 parents 472f6a3 + eab9a07 commit 6c6f468
Show file tree
Hide file tree
Showing 11 changed files with 133 additions and 14 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@ Run this command to create a new project using the template

# 📦Installed packages
- [axios](https://github.com/axios/axios) for networking.
- [i18n-js](https://www.npmjs.com/package/i18n-js) small library to provide the i18n translations with JavaScript
- [lodash](https://lodash.com/) modern Javascript library delivering modularity and performance
- [lottie-react-native](https://github.com/lottie-react-native/lottie-react-native) an ecosystem of libraries for parsing Adobe After Effects animations exported as JSON
- [moment](https://momentjs.com/) library to parse, validate, manipulate and display date/time in JavaScript
- [Munchkin](https://munchkinreact.app/) a react native component library
- [nativewind](https://www.nativewind.dev/) a universal style system
- [react-native-localize](https://www.npmjs.com/package/react-native-localize) a toolbox for your React Native app localization
- [react-native-vector-icons](https://github.com/oblador/react-native-vector-icons) an icon library.
- [react-navigation](https://reactnavigation.org/) navigation library.
- [redux](https://redux.js.org/) for state management.
Expand Down
8 changes: 8 additions & 0 deletions template/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,18 @@ import { persistStore } from "redux-persist";
import Navigation from "./src/navigation/Navigation";

import store from "./src/redux/store";
import useLocalize from "./src/hooks/useLocalize";
import { useEffect } from "react";

const persistor = persistStore(store);

const App = () => {
const { setI18nConfig } = useLocalize();

useEffect(() => {
setI18nConfig();
}, [setI18nConfig]);

return (
<Provider store={store}>
<PersistGate persistor={persistor}>
Expand Down
6 changes: 6 additions & 0 deletions template/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,8 @@ PODS:
- React-Core
- RNGestureHandler (2.6.0):
- React-Core
- RNLocalize (2.2.4):
- React-Core
- RNReanimated (2.10.0):
- DoubleConversion
- FBLazyVector
Expand Down Expand Up @@ -461,6 +463,7 @@ DEPENDENCIES:
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
- "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
- 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`)
Expand Down Expand Up @@ -556,6 +559,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/@react-native-async-storage/async-storage"
RNGestureHandler:
:path: "../node_modules/react-native-gesture-handler"
RNLocalize:
:path: "../node_modules/react-native-localize"
RNReanimated:
:path: "../node_modules/react-native-reanimated"
RNScreens:
Expand Down Expand Up @@ -615,6 +620,7 @@ SPEC CHECKSUMS:
ReactCommon: 8f67bd7e0a6afade0f20718f859dc8c2275f2e83
RNCAsyncStorage: 0c357f3156fcb16c8589ede67cc036330b6698ca
RNGestureHandler: 920eb17f5b1e15dae6e5ed1904045f8f90e0b11e
RNLocalize: 0df7970cfc60389f00eb62fd7c097dc75af3fb4f
RNReanimated: 7faa787e8d4493fbc95fab2ad331fa7625828cfa
RNScreens: 0df01424e9e0ed7827200d6ed1087ddd06c493f9
RNVectorIcons: fcc2f6cb32f5735b586e66d14103a74ce6ad61f8
Expand Down
5 changes: 5 additions & 0 deletions template/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,17 @@
"@reduxjs/toolkit": "^1.8.5",
"add": "^2.0.6",
"axios": "^0.27.2",
"i18n-js": "3.9.2",
"lodash": "^4.17.21",
"lodash.memoize": "4.1.2",
"lottie-react-native": "^5.1.4",
"moment": "^2.29.4",
"nativewind": "^2.0.10",
"react": "18.0.0",
"react-native": "0.69.4",
"react-native-gesture-handler": "^2.6.0",
"react-native-keyboard-aware-scroll-view": "^0.9.5",
"react-native-localize": "^2.2.4",
"react-native-reanimated": "^2.10.0",
"react-native-safe-area-context": "^4.3.3",
"react-native-screens": "^3.16.0",
Expand Down
36 changes: 36 additions & 0 deletions template/src/hooks/useLocalize.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { I18nManager } from "react-native";
import * as RNLocalize from "react-native-localize";

import i18n from "i18n-js";
import memoize from "lodash.memoize";

const translationGetters = {
en: () => require("../utils/translations/en.json"),
es: () => require("../utils/translations/es.json")
// add lanugauges you want to support here
};

const translate = memoize(
(key, config) => i18n.t(key, config),
(key, config) => (config ? key + JSON.stringify(config) : key)
);

export default function useLocalize() {
const setI18nConfig = () => {
const fallback = { languageTag: "en", isRTL: false };

const { languageTag, isRTL } =
RNLocalize.findBestAvailableLanguage(Object.keys(translationGetters)) ||
fallback;

translate.cache.clear();

I18nManager.forceRTL(isRTL);

i18n.translations = { [languageTag]: translationGetters[languageTag]() };

i18n.locale = languageTag;
};

return { setI18nConfig, translate };
}
33 changes: 23 additions & 10 deletions template/src/navigation/BottomTabNavigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,33 @@ import React from "react";
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import PropTypes from "prop-types";

import { BOTTOM_TAB_SCREENS } from "../utils/screens";
import useLocalize from "../hooks/useLocalize";
import HomeScreen from "../screens/HomeScreen";
import { BOTTOM_TAB_SCREENS } from "../utils/screens";
import { TRANSLATIONS } from "../utils/translations/translations";

const Tab = createBottomTabNavigator();

const BottomTabNavigation = () => (
<Tab.Navigator
screenOptions={() => ({
drawerPosition: "right",
headerLeft: false
})}>
<Tab.Screen name={BOTTOM_TAB_SCREENS.HOME_SCREEN} component={HomeScreen} />
</Tab.Navigator>
);
const TAB_SCREEN_OPTIONS = {
drawerPosition: "right",
headerLeft: false
};

const BottomTabNavigation = () => {
const { translate } = useLocalize();

return (
<Tab.Navigator screenOptions={TAB_SCREEN_OPTIONS}>
<Tab.Screen
name={BOTTOM_TAB_SCREENS.HOME_SCREEN}
component={HomeScreen}
options={{
tabBarLabel: translate(TRANSLATIONS.MAIN)
}}
/>
</Tab.Navigator>
);
};

BottomTabNavigation.propTypes = {
navigation: PropTypes.object
Expand Down
26 changes: 23 additions & 3 deletions template/src/screens/HomeScreen.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,36 @@
import React from "react";
import { View } from "react-native";

import { Text, View } from "react-native";
import moment from "moment";
import { Button } from "@digital-art-dealers/react-native-component-lib";

import useLocalize from "../hooks/useLocalize";
import { TRANSLATIONS } from "../utils/translations/translations";
import { useLayoutEffect } from "react";
import { useNavigation } from "@react-navigation/native";

const HomeScreen = () => {
const navigation = useNavigation();
const { translate } = useLocalize();

// TODO: This can be removed or changed according to project needs
useLayoutEffect(() => {
navigation.setOptions({
headerTitle: translate(TRANSLATIONS.MAIN)
});
}, [navigation]);

return (
<View className="h-full w-full justify-center px-4">
<Button
buttonColor="bg-blue-600"
textColor="text-white"
onPress={() => {}}
label="Change this button"
label={translate(TRANSLATIONS.CHANGE_BUTTON)}
/>
<Text className="text-2xl font-bold text-center mt-8">Todays Date</Text>
<Text className="text-center text-lg">
{moment(new Date()).format("YYYY-MM-DD")}
</Text>
</View>
);
};
Expand Down
4 changes: 4 additions & 0 deletions template/src/utils/translations/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"changeButton": "Change this button",
"main": "Main"
}
4 changes: 4 additions & 0 deletions template/src/utils/translations/es.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"changeButton": "Cambiar este botón",
"main": "Principal"
}
4 changes: 4 additions & 0 deletions template/src/utils/translations/translations.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const TRANSLATIONS = {
CHANGE_BUTTON: "changeButton",
MAIN: "main"
};
17 changes: 16 additions & 1 deletion template/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4015,6 +4015,11 @@ human-signals@^3.0.1:
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-3.0.1.tgz#c740920859dafa50e5a3222da9d3bf4bb0e5eef5"
integrity sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==

[email protected]:
version "3.9.2"
resolved "https://registry.yarnpkg.com/i18n-js/-/i18n-js-3.9.2.tgz#4a015dcfabd4c9fc73115fc2d02d2627e4c15ca5"
integrity sha512-+Gm8h5HL0emzKhRx2avMKX+nKiVPXeaOZm7Euf2/pbbFcLQoJ3zZYiUykAzoRasijCoWos2Kl1tslmScTgAQKw==

ieee754@^1.1.13:
version "1.2.1"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
Expand Down Expand Up @@ -5140,6 +5145,11 @@ lodash.isequal@^4.5.0:
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==

[email protected]:
version "4.1.2"
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==

lodash.merge@^4.6.2:
version "4.6.2"
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
Expand Down Expand Up @@ -5604,7 +5614,7 @@ mkdirp@^0.5.1, mkdirp@~0.5.1:
dependencies:
minimist "^1.2.6"

moment@^2.19.3:
moment@^2.19.3, moment@^2.29.4:
version "2.29.4"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108"
integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==
Expand Down Expand Up @@ -6397,6 +6407,11 @@ react-native-keyboard-aware-scroll-view@^0.9.5:
prop-types "^15.6.2"
react-native-iphone-x-helper "^1.0.3"

react-native-localize@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/react-native-localize/-/react-native-localize-2.2.4.tgz#3bc46ade48499ab9df61bf17a9b66633a5ba9bb9"
integrity sha512-gVmbyAEQQnBQ8vKlAQchFfIISeId3qT6Lc7LHmKF39nsYWX9KN4PHuG6Hk+7gduMI6IHKeZGKcLsOdh6wvN6cg==

react-native-reanimated@^2.10.0:
version "2.10.0"
resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-2.10.0.tgz#ed53be66bbb553b5b5e93e93ef4217c87b8c73db"
Expand Down

0 comments on commit 6c6f468

Please sign in to comment.