1
0
Fork 0

Commits vergleichen

...

12 Commits

Autor SHA1 Nachricht Datum
docjyJ
82f7af58bd Translate subtitle ans description key
(en.screens.proxiwash.tripodeB.*)
2020-09-12 12:06:58 +02:00
docjyJ
c5b6e128ee Bug Correction
- bad language display
- update 'maxWeight ' to maxWeight
2020-09-12 11:59:48 +02:00
docjyJ
5b6176a361 Update ui proxiwash settings go to general Settings
Remove proxiwash settings screen
move setings in setings screen
2020-09-11 09:22:31 +02:00
docjyJ
02e30f87cf Update ui to go to proxiwash Settings
Remove the header of proxiwash screen
Add a button on proxiwash screen tool bar
2020-09-11 09:22:31 +02:00
docjyJ
83a3354d1e Update tariff language key for washinsa and tripode B 2020-09-11 09:22:31 +02:00
docjyJ
ce1227901c Update Docs 2020-09-11 09:22:31 +02:00
docjyJ
5a92b5096a Update Proxiwash About Screen 2020-09-11 09:22:31 +02:00
docjyJ
115c90b712 Add new Screen to select wash 2020-09-11 09:22:31 +02:00
docjyJ
41a17a9a91 Update Language File 2020-09-11 09:22:31 +02:00
docjyJ
7867e12a49 Update Settigns Screen 2020-09-11 09:22:31 +02:00
docjyJ
f8f5749478 add settings selection 2020-09-11 09:22:31 +02:00
Arnaud Vergnet
3de49732b9 Improve local management
This allows fast refresh when working on locales
2020-09-10 18:51:34 +02:00
10 geänderte Dateien mit 229 neuen und 77 gelöschten Zeilen

4
App.js
Datei anzeigen

@ -7,7 +7,6 @@ import {Provider as PaperProvider} from 'react-native-paper';
import {setSafeBounceHeight} from 'react-navigation-collapsible';
import SplashScreen from 'react-native-splash-screen';
import {OverflowMenuProvider} from 'react-navigation-header-buttons';
import LocaleManager from './src/managers/LocaleManager';
import AsyncStorageManager from './src/managers/AsyncStorageManager';
import CustomIntroSlider from './src/components/Overrides/CustomIntroSlider';
import type {CustomThemeType} from './src/managers/ThemeManager';
@ -19,6 +18,7 @@ import ConnectionManager from './src/managers/ConnectionManager';
import type {ParsedUrlDataType} from './src/utils/URLHandler';
import URLHandler from './src/utils/URLHandler';
import {setupStatusBar} from './src/utils/Utils';
import initLocales from './src/utils/Locales';
// Native optimizations https://reactnavigation.org/docs/react-native-screens
// Crashes app when navigating away from webview on android 9+
@ -56,7 +56,7 @@ export default class App extends React.Component<null, StateType> {
showAprilFools: false,
currentTheme: null,
};
LocaleManager.initTranslations();
initLocales();
this.navigatorRef = React.createRef();
this.defaultHomeRoute = null;
this.defaultHomeData = {};

Datei anzeigen

@ -41,14 +41,10 @@
"washer": "Washer",
"washers": "Washers",
"min": "min",
"description": "This is the washing service operated by Promologis for INSA's residences (We don't mind if you do not live on the campus and you do your laundry here). The room is right next to the R2, with 3 dryers and 9 washers, is open 7d/7 24h/24 ! Here you can check their availability ! You can bring your own detergent, use the one given on site or buy it at the Proximo (cheaper than the one given by the machines ). You can pay by credit card or cash.",
"informationTab": "Information",
"paymentTab": "Payment",
"tariffs": "Tariffs",
"washersTariff": "3€ the washer + 0.80€ with detergent.",
"dryersTariff": "0.35€ for 5min of dryer usage.",
"paymentMethods": "Payment Methods",
"paymentMethodsDescription": "Cash up until 10€.\nCredit Card also accepted.",
"washerProcedure": "Put your laundry in the tumble without tamping it and by respecting charge limits.\n\nClose the machine's door.\n\nChoose a program using one of the four favorite program buttons.\n\nPay to the command central, then press the START button on the machine.\n\nWhen the program is finished, the screen indicates 'Programme terminé', press the yellow button to open the lid and retrieve your laundry.",
"washerTips": "Program 'blanc/couleur': 6kg of dry laundry (cotton linen, linen, underwear, sheets, jeans, towels).\n\nProgram 'non repassable': 3,5 kg of dry laundry (synthetic fibre linen, cotton and polyester mixed).\n\nProgram 'fin 30°C': 2,5 kg of dry laundry (delicate linen in synthetic fibres).\n\nProgram 'laine 30°C': 2,5 kg of dry laundry (wool textiles).",
"dryerProcedure": "Put your laundry in the tumble without tamping it and by respecting charge limits.\n\nClose the machine's door.\n\nChoose a program using one of the four favorite program buttons.\n\nPay to the command central, then press the START button on the machine.",
@ -57,6 +53,20 @@
"tips": "Tips",
"numAvailable": "available",
"numAvailablePlural": "available",
"washinsa": {
"title": "INSA laundromat",
"subtitle": "Your favorite laundromat !!",
"description": "This is the washing service operated by Promologis for INSA's residences (We don't mind if you do not live on the campus and you do your laundry here). The room is right next to the R2, with 3 dryers and 9 washers, is open 7d/7 24h/24 ! You can bring your own detergent, use the one given on site or buy it at the Proximo (cheaper than the one given by the machines ).",
"tariff": "Washers 6kg: 3€ the washer + 0.80€ with detergent.\nDryers 14kg: 0.35€ for 5min of dryer usage.",
"paymentMethods": "Cash up until 10€.\nCredit Card also accepted."
},
"tripodeB": {
"title": "Tripode B laundromat",
"subtitle": "That of those who live near the metro.",
"description": "This is the washing service operated by the CROUS for the Tripode B and C residences as well as Thalès and Pythagore. The room is at the foot of Tripod B in front of the Pythagore residence, with 2 dryers and 6 washers, is open 7d/7 from 7am to 11pm. In addition to the 6kg washers there is one 10kg washers",
"tariff": "Washers 6kg: 2.60€ the washer + 0.90€ with detergent.\nWashers 10kg: 4.90€ the washer + 1.50€ with detergent.\nDryers 14kg: 0.40€ for 5min of dryer usage.",
"paymentMethods": "Carte bancaire acceptée."
},
"modal": {
"enableNotifications": "Notify me",
"disableNotifications": "Stop notifications",
@ -197,7 +207,6 @@
"message": "An Amicale account allows you to take part in several activities around campus. You can join a club, or even create your own!\n\nLogging into your Amicale account on the app will allow you to see all available clubs on the campus, vote for the upcoming elections, and more to come!\n\nNo Account? Go to the Amicale's building during open hours to create one.",
"button": "OK"
}
},
"profile": {
"title": "Profile",

Datei anzeigen

@ -41,14 +41,10 @@
"washer": "Lave-Linge",
"washers": "Lave-Linges",
"min": "min",
"description": "C'est le service de laverie proposé par Promologis pour les résidences INSA (On t'en voudra pas si tu loges pas sur le campus et que tu fais ta machine ici). Le local situé au pied du R2 avec ses 3 sèche-linges et 9 machines est ouvert 7J/7 24h/24 ! Ici tu peux vérifier leur disponibilité ! Tu peux amener ta lessive, la prendre sur place ou encore mieux l'acheter au Proximo (moins chère qu'à la laverie directement). Tu peux payer par CB ou espèces.",
"informationTab": "Informations",
"paymentTab": "Paiement",
"tariffs": "Tarifs",
"washersTariff": "3€ la machine + 0.80€ avec la lessive.",
"dryersTariff": "0.35€ pour 5min de sèche linge.",
"paymentMethods": "Moyens de Paiement",
"paymentMethodsDescription": "Toute monnaie jusqu'à 10€.\nCarte bancaire acceptée.",
"washerProcedure": "Déposer le linge dans le tambour sans le tasser et en respectant les charges.\n\nFermer la porte de l'appareil.\n\nSélectionner un programme avec l'une des quatre touches de programme favori standard.\n\nAprès avoir payé à la centrale de commande, appuyer sur le bouton marqué START du lave-linge.\n\nDès que le programme est terminé, lafficheur indique 'Programme terminé', appuyer sur le bouton jaune douverture du hublot pour récupérer le linge.",
"washerTips": "Programme blanc/couleur : 6kg de linge sec (textiles en coton, lin, linge de corps, draps, jeans,serviettes de toilettes).\n\nProgramme non repassable : 3,5 kg de linge sec (textiles en fibres synthétiques, coton et polyester mélangés).\n\nProgramme fin 30°C : 2,5 kg de linge sec (textiles délicats en fibres synthétiques, rayonne).\n\nProgramme laine 30°C : 2,5 kg de linge sec (textiles en laine et lainages lavables).",
"dryerProcedure": "Déposer le linge dans le tambour sans le tasser et en respectant les charges.\n\nFermer la porte de l'appareil.\n\nSélectionner un programme avec l'une des quatre touches de programme favori standard.\n\nAprès avoir payé à la centrale de commande, appuyer sur le bouton marqué START du lave-linge.",
@ -57,6 +53,20 @@
"tips": "Conseils",
"numAvailable": "disponible",
"numAvailablePlural": "disponibles",
"washinsa": {
"title": "Laverie INSA",
"subtitle": "Ta laverie préférer !!",
"description": "C'est le service de laverie proposé par Promologis pour les résidences INSA (On t'en voudra pas si tu loges pas sur le campus et que tu fais ta machine ici). Le local situé au pied du R2 avec ses 3 sèche-linges et 9 machines est ouvert 7J/7 24h/24 ! Tu peux amener ta lessive, la prendre sur place ou encore mieux l'acheter au Proximo (moins chère qu'à la laverie directement).",
"tariff": "Lave-Linges 6kg: 3€ la machine + 0.80€ avec la lessive.\nSèche-Linges 14kg: 0.35€ pour 5min de sèche linge.",
"paymentMethods": "Toute monnaie jusqu'à 10€.\nCarte bancaire acceptée."
},
"tripodeB": {
"title": "Laverie Tripode B",
"subtitle": "Celle de ceux qui habite prés du métro.",
"description": "C'est le service de laverie proposé par le CROUS pour les résidences Tripode B et C ainsi que Thalès et Pythagore. Le local situé au pied du Tripode B en face de de la résidence Pythagore avec ses 2 sèche-linges et 6 machines est ouvert 7J/7 de 7h à 23h. En plus des machine 6kg il y as une machine de 10kg.",
"tariff": "Lave-Linges 6kg: 2.60€ la machine + 0.90€ avec la lessive.\nLave-Linges 10kg: 4.90€ la machine + 1.50€ avec la lessive.\nSèche-Linges 14kg: 0.40€ pour 5min de sèche linge.",
"paymentMethods": "Carte bancaire acceptée."
},
"modal": {
"enableNotifications": "Me Notifier",
"disableNotifications": "Désactiver les notifications",

Datei anzeigen

@ -59,6 +59,8 @@ class ProxiwashListItem extends React.Component<PropsType> {
title: string;
titlePopUp: string;
constructor(props: PropsType) {
super(props);
this.stateColors = {};
@ -67,6 +69,7 @@ class ProxiwashListItem extends React.Component<PropsType> {
this.updateStateStrings();
let displayNumber = props.item.number;
const displayMaxWeight = props.item.maxWeight;
if (AprilFoolsManager.getInstance().isAprilFoolsEnabled())
displayNumber = AprilFoolsManager.getProxiwashMachineDisplayNumber(
parseInt(props.item.number, 10),
@ -76,6 +79,7 @@ class ProxiwashListItem extends React.Component<PropsType> {
? i18n.t('screens.proxiwash.dryer')
: i18n.t('screens.proxiwash.washer');
this.title += `${displayNumber}`;
this.titlePopUp = `${this.title} - ${displayMaxWeight} kg`;
}
shouldComponentUpdate(nextProps: PropsType): boolean {
@ -90,7 +94,7 @@ class ProxiwashListItem extends React.Component<PropsType> {
onListItemPress = () => {
const {props} = this;
props.onPress(this.title, props.item, props.isDryer);
props.onPress(this.titlePopUp, props.item, props.isDryer);
};
updateStateStrings() {

Datei anzeigen

@ -107,6 +107,10 @@ export default class AsyncStorageManager {
key: 'gameScores',
default: '[]',
},
selectedWash: {
key: 'selectedWash',
default: 'washinsa',
},
};
#currentPreferences: {[key: string]: string};

Datei anzeigen

@ -1,24 +0,0 @@
// @flow
import i18n from 'i18n-js';
import * as RNLocalize from 'react-native-localize';
import en from '../../locales/en.json';
import fr from '../../locales/fr.json';
/**
* Static class used to manage locales
*/
export default class LocaleManager {
/**
* Initialize translations using language files
*/
static initTranslations() {
i18n.fallbacks = true;
i18n.translations = {fr, en};
i18n.locale = RNLocalize.findBestAvailableLanguage([
'en',
'fr',
]).languageTag;
}
}

Datei anzeigen

@ -3,7 +3,14 @@
import * as React from 'react';
import {View} from 'react-native';
import i18n from 'i18n-js';
import {Card, List, Switch, ToggleButton, withTheme} from 'react-native-paper';
import {
RadioButton,
Card,
List,
Switch,
ToggleButton,
withTheme,
} from 'react-native-paper';
import {Appearance} from 'react-native-appearance';
import {StackNavigationProp} from '@react-navigation/stack';
import type {CustomThemeType} from '../../../managers/ThemeManager';
@ -22,6 +29,7 @@ type StateType = {
nightMode: boolean,
nightModeFollowSystem: boolean,
startScreenPickerSelected: string,
selectedWash: string,
isDebugUnlocked: boolean,
};
@ -52,6 +60,9 @@ class SettingsScreen extends React.Component<PropsType, StateType> {
startScreenPickerSelected: AsyncStorageManager.getString(
AsyncStorageManager.PREFERENCES.defaultStartScreen.key,
),
selectedWash: AsyncStorageManager.getString(
AsyncStorageManager.PREFERENCES.selectedWash.key,
),
isDebugUnlocked: AsyncStorageManager.getBool(
AsyncStorageManager.PREFERENCES.debugUnlocked.key,
),
@ -106,6 +117,29 @@ class SettingsScreen extends React.Component<PropsType, StateType> {
);
}
/**
* Returns a radio picker allowing the user to select the proxiwash
*
* @returns {React.Node}
*/
getProxiwashChangePicker(): React.Node {
const {selectedWash} = this.state;
return (
<RadioButton.Group
onValueChange={this.onSelectWashValueChange}
value={selectedWash}>
<RadioButton.Item
label={i18n.t('screens.proxiwash.washinsa.title')}
value="washinsa"
/>
<RadioButton.Item
label={i18n.t('screens.proxiwash.tripodeB.title')}
value="tripodeB"
/>
</RadioButton.Group>
);
}
/**
* Returns a picker allowing the user to select the start screen
*
@ -212,6 +246,21 @@ class SettingsScreen extends React.Component<PropsType, StateType> {
);
}
/**
* Saves the value for the proxiwash selected wash
*
* @param value The value to store
*/
onSelectWashValueChange = (value: string) => {
if (value != null) {
this.setState({selectedWash: value});
AsyncStorageManager.set(
AsyncStorageManager.PREFERENCES.selectedWash.key,
value,
);
}
};
/**
* Unlocks debug mode and saves its state to user preferences
*/
@ -288,6 +337,20 @@ class SettingsScreen extends React.Component<PropsType, StateType> {
<View style={{marginLeft: 30}}>
{this.getProxiwashNotifPicker()}
</View>
<List.Item
title="Test"
description="Test"
left={(props: ListIconPropsType): React.Node => (
<List.Icon
color={props.color}
style={props.style}
icon="washing-machine"
/>
)}
/>
<View style={{marginLeft: 30}}>
{this.getProxiwashChangePicker()}
</View>
</List.Section>
</Card>
<Card style={{margin: 5}}>

Datei anzeigen

@ -3,18 +3,73 @@
import * as React from 'react';
import {Image, View} from 'react-native';
import i18n from 'i18n-js';
import {Card, Avatar, Paragraph, Text, Title} from 'react-native-paper';
import CustomTabBar from '../../components/Tabbar/CustomTabBar';
import {Card, Avatar, Paragraph, Title} from 'react-native-paper';
import CollapsibleScrollView from '../../components/Collapsible/CollapsibleScrollView';
import type {CardTitleIconPropsType} from '../../constants/PaperStyles';
const LOGO = 'https://etud.insa-toulouse.fr/~amicale_app/images/Proxiwash.png';
export type LaverieType = {
id: string,
title: string,
subtitle: string,
description: string,
tarif: string,
paymentMethods: string,
icon: string,
url: string,
};
export const PROXIWASH_DATA = {
washinsa: {
id: 'washinsa',
title: 'screens.proxiwash.washinsa.title',
subtitle: 'screens.proxiwash.washinsa.subtitle',
description: 'screens.proxiwash.washinsa.description',
tarif: 'screens.proxiwash.washinsa.tariff',
paymentMethods: 'screens.proxiwash.washinsa.paymentMethods',
icon: 'school-outline',
url:
'https://etud.insa-toulouse.fr/~amicale_app/v2/washinsa/washinsa_data.json',
},
tripodeB: {
id: 'tripodeB',
title: 'screens.proxiwash.tripodeB.title',
subtitle: 'screens.proxiwash.tripodeB.subtitle',
description: 'screens.proxiwash.tripodeB.description',
tarif: 'screens.proxiwash.tripodeB.tariff',
paymentMethods: 'screens.proxiwash.tripodeB.paymentMethods',
icon: 'domain',
url:
'https://etud.insa-toulouse.fr/~amicale_app/v2/washinsa/tripode_b_data.json',
},
};
/**
* Class defining the proxiwash about screen.
*/
// eslint-disable-next-line react/prefer-stateless-function
export default class ProxiwashAboutScreen extends React.Component<null> {
static getCardItem(item: LaverieType): React.Node {
return (
<Card style={{margin: 5}}>
<Card.Title
title={i18n.t(item.title)}
subtitle={i18n.t(item.subtitle)}
left={(iconProps: CardTitleIconPropsType): React.Node => (
<Avatar.Icon size={iconProps.size} icon={item.icon} />
)}
/>
<Card.Content>
<Paragraph>{i18n.t(item.description)}</Paragraph>
<Title>{i18n.t('screens.proxiwash.tariffs')}</Title>
<Paragraph>{i18n.t(item.tarif)}</Paragraph>
<Title>{i18n.t('screens.proxiwash.paymentMethods')}</Title>
<Paragraph>{i18n.t(item.paymentMethods)}</Paragraph>
</Card.Content>
</Card>
);
}
render(): React.Node {
return (
<CollapsibleScrollView style={{padding: 5}} hasTab>
@ -32,7 +87,11 @@ export default class ProxiwashAboutScreen extends React.Component<null> {
style={{height: '100%', width: '100%', resizeMode: 'contain'}}
/>
</View>
<Text>{i18n.t('screens.proxiwash.description')}</Text>
{ProxiwashAboutScreen.getCardItem(PROXIWASH_DATA.washinsa)}
{ProxiwashAboutScreen.getCardItem(PROXIWASH_DATA.tripodeB)}
<Card style={{margin: 5}}>
<Card.Title
title={i18n.t('screens.proxiwash.dryer')}
@ -62,33 +121,6 @@ export default class ProxiwashAboutScreen extends React.Component<null> {
<Paragraph>{i18n.t('screens.proxiwash.washerTips')}</Paragraph>
</Card.Content>
</Card>
<Card style={{margin: 5}}>
<Card.Title
title={i18n.t('screens.proxiwash.tariffs')}
left={(iconProps: CardTitleIconPropsType): React.Node => (
<Avatar.Icon size={iconProps.size} icon="circle-multiple" />
)}
/>
<Card.Content>
<Paragraph>{i18n.t('screens.proxiwash.washersTariff')}</Paragraph>
<Paragraph>{i18n.t('screens.proxiwash.dryersTariff')}</Paragraph>
</Card.Content>
</Card>
<Card
style={{margin: 5, marginBottom: CustomTabBar.TAB_BAR_HEIGHT + 20}}>
<Card.Title
title={i18n.t('screens.proxiwash.paymentMethods')}
left={(iconProps: CardTitleIconPropsType): React.Node => (
<Avatar.Icon size={iconProps.size} icon="cash" />
)}
/>
<Card.Content>
<Paragraph>
{i18n.t('screens.proxiwash.paymentMethodsDescription')}
</Paragraph>
</Card.Content>
</Card>
</CollapsibleScrollView>
);
}

Datei anzeigen

@ -3,7 +3,7 @@
import * as React from 'react';
import {Alert, View} from 'react-native';
import i18n from 'i18n-js';
import {Avatar, Button, Card, Text, withTheme} from 'react-native-paper';
import {Avatar, Button, Card, List, Text, withTheme} from 'react-native-paper';
import {StackNavigationProp} from '@react-navigation/stack';
import {Modalize} from 'react-native-modalize';
import WebSectionList from '../../components/Screens/WebSectionList';
@ -26,9 +26,8 @@ import {
import {MASCOT_STYLE} from '../../components/Mascot/Mascot';
import MascotPopup from '../../components/Mascot/MascotPopup';
import type {SectionListDataType} from '../../components/Screens/WebSectionList';
const DATA_URL =
'https://etud.insa-toulouse.fr/~amicale_app/v2/washinsa/washinsa_data.json';
import type {ListIconPropsType} from '../../constants/PaperStyles';
import {PROXIWASH_DATA} from './ProxiwashAboutScreen';
const modalStateStrings = {};
@ -38,6 +37,7 @@ const LIST_ITEM_HEIGHT = 64;
export type ProxiwashMachineType = {
number: string,
state: string,
maxWeight: number,
startTime: string,
endTime: string,
donePercent: string,
@ -53,6 +53,7 @@ type PropsType = {
type StateType = {
modalCurrentDisplayItem: React.Node,
machinesWatched: Array<ProxiwashMachineType>,
selectedWash: string,
};
/**
@ -87,6 +88,9 @@ class ProxiwashScreen extends React.Component<PropsType, StateType> {
machinesWatched: AsyncStorageManager.getObject(
AsyncStorageManager.PREFERENCES.proxiwashWatchedMachines.key,
),
selectedWash: AsyncStorageManager.getString(
AsyncStorageManager.PREFERENCES.selectedWash.key,
),
};
modalStateStrings[ProxiwashConstants.machineStates.AVAILABLE] = i18n.t(
'screens.proxiwash.modal.ready',
@ -198,9 +202,6 @@ class ProxiwashScreen extends React.Component<PropsType, StateType> {
remaining: remainingTime,
program: item.program,
});
} else if (item.state === ProxiwashConstants.machineStates.AVAILABLE) {
if (isDryer) message += `\n${i18n.t('screens.proxiwash.dryersTariff')}`;
else message += `\n${i18n.t('screens.proxiwash.washersTariff')}`;
}
return (
<View
@ -342,6 +343,31 @@ class ProxiwashScreen extends React.Component<PropsType, StateType> {
return count;
}
/**
* Gets a chevron icon
*
* @param props
* @return {*}
*/
static getChevronIcon(props: ListIconPropsType): React.Node {
return (
<List.Icon color={props.color} style={props.style} icon="chevron-right" />
);
}
/**
* Gets a custom list item icon
*
* @param item The item to show the icon for
* @param props
* @return {*}
*/
static getItemIcon(item: ListItemType, props: ListIconPropsType): React.Node {
return (
<List.Icon color={props.color} style={props.style} icon={item.icon} />
);
}
/**
* Creates the dataset to be used by the FlatList
*
@ -437,8 +463,19 @@ class ProxiwashScreen extends React.Component<PropsType, StateType> {
render(): React.Node {
const {state} = this;
const {navigation} = this.props;
let data: LaverieType;
switch (state.selectedWash) {
case 'tripodeB':
data = PROXIWASH_DATA.tripodeB;
break;
default:
data = PROXIWASH_DATA.washinsa;
}
return (
<View style={{flex: 1}}>
<View
style={{
flex: 1,
}}>
<View
style={{
position: 'absolute',
@ -448,7 +485,7 @@ class ProxiwashScreen extends React.Component<PropsType, StateType> {
<WebSectionList
createDataset={this.createDataset}
navigation={navigation}
fetchUrl={DATA_URL}
fetchUrl={data.url}
renderItem={this.getRenderItem}
renderSectionHeader={this.getRenderSectionHeader}
autoRefreshTime={REFRESH_TIME}

17
src/utils/Locales.js Normale Datei
Datei anzeigen

@ -0,0 +1,17 @@
// @flow
import i18n from 'i18n-js';
import * as RNLocalize from 'react-native-localize';
import en from '../../locales/en.json';
import fr from '../../locales/fr.json';
const initLocales = () => {
i18n.fallbacks = true;
i18n.translations = {fr, en};
i18n.locale = RNLocalize.findBestAvailableLanguage([
'en',
'fr',
]).languageTag;
}
export default initLocales;