Merge branch '162-Prepare-localization' into 'master'

Resolve "Prepare localization"

Closes #162

See merge request bloodyhealth/drip!361
This commit is contained in:
bl00dymarie
2021-06-18 11:11:28 +00:00
10 changed files with 17909 additions and 201 deletions
+155
View File
@@ -0,0 +1,155 @@
import React from 'react'
import { ScrollView, StyleSheet, View } from 'react-native'
import PropTypes from 'prop-types'
import moment from 'moment'
import { connect } from 'react-redux'
import { navigate } from '../slices/navigation'
import { getDate, setDate } from '../slices/date'
import AppText from './common/app-text'
import Button from './common/button'
import cycleModule from '../lib/cycle'
import { getFertilityStatusForDay } from '../lib/sympto-adapter'
import { determinePredictionText, formatWithOrdinalSuffix } from './helpers/home'
import { Colors, Fonts, Sizes, Spacing } from '../styles'
import { LocalDate } from 'js-joda'
import { useTranslation } from 'react-i18next'
const Home = ({ navigate, setDate }) => {
const { t } = useTranslation()
function navigateToCycleDayView() {
setDate(todayDateString)
navigate('CycleDay')
}
const todayDateString = LocalDate.now().toString()
const { getCycleDayNumber, getPredictedMenses } = cycleModule()
const cycleDayNumber = getCycleDayNumber(todayDateString)
const { status, phase, statusText } =
getFertilityStatusForDay(todayDateString)
const prediction = determinePredictionText(getPredictedMenses(), t)
const cycleDayText = cycleDayNumber ? formatWithOrdinalSuffix(cycleDayNumber) : ''
return (
<ScrollView
style={styles.container}
contentContainerStyle={styles.contentContainer}
>
<AppText style={styles.title}>{moment().format("MMM Do YYYY")}</AppText>
{cycleDayNumber &&
<View style={styles.line}>
<AppText style={styles.whiteSubtitle}>{cycleDayText}</AppText>
<AppText style={styles.turquoiseText}>{t('labels.home.cycleDay')}</AppText>
</View>
}
{phase &&
<View style={styles.line}>
<AppText style={styles.whiteSubtitle}>
{formatWithOrdinalSuffix(phase)}
</AppText>
<AppText style={styles.turquoiseText}>
{t('labels.home.cyclePhase')}
</AppText>
<AppText style={styles.turquoiseText}>{status}</AppText>
<Asterisk />
</View>
}
<View style={styles.line}>
<AppText style={styles.turquoiseText}>{prediction}</AppText>
</View>
<Button isCTA isSmall={false} onPress={navigateToCycleDayView}>
{t('labels.home.addDataForToday')}
</Button>
{phase && (
<View style={styles.asteriskLine}>
<Asterisk />
<AppText linkStyle={styles.whiteText} style={styles.greyText}>
{statusText}
</AppText>
</View>
)}
</ScrollView>
)
}
const Asterisk = () => {
return <AppText style={styles.asterisk}>*</AppText>
}
const styles = StyleSheet.create({
asterisk: {
color: Colors.orange,
},
container: {
backgroundColor: Colors.purple,
flex: 1,
},
contentContainer: {
padding: Spacing.base,
paddingTop: 0,
},
line: {
flexDirection: 'row',
flexWrap: 'wrap',
alignContent: 'flex-start',
marginBottom: Spacing.tiny,
marginTop: Spacing.small,
},
asteriskLine: {
flexDirection: 'row',
alignContent: 'flex-start',
marginBottom: Spacing.tiny,
marginTop: Spacing.small,
},
title: {
color: Colors.purpleLight,
fontFamily: Fonts.bold,
fontSize: Sizes.huge,
marginVertical: Spacing.small,
},
turquoiseText: {
color: Colors.turquoise,
fontSize: Sizes.subtitle,
},
whiteSubtitle: {
color: 'white',
fontSize: Sizes.subtitle,
},
whiteText: {
color: 'white',
},
greyText: {
color: Colors.greyLight,
paddingLeft: Spacing.base,
}
})
const mapStateToProps = (state) => {
return ({
date: getDate(state),
})
}
const mapDispatchToProps = (dispatch) => {
return ({
navigate: (page) => dispatch(navigate(page)),
setDate: (date) => dispatch(setDate(date)),
})
}
Home.propTypes = {
navigate: PropTypes.func,
setDate: PropTypes.func
}
export default connect(
mapStateToProps,
mapDispatchToProps,
)(Home)
+2 -2
View File
@@ -17,8 +17,8 @@ function getTimes(prediction) {
return { todayDate, predictedBleedingStart, predictedBleedingEnd, daysToEnd }
}
export function determinePredictionText(bleedingPrediction) {
if (!bleedingPrediction.length) return predictLabels.noPrediction
export function determinePredictionText(bleedingPrediction, t) {
if (!bleedingPrediction.length) return t('labels.bleedingPrediction.noPrediction')
const {
todayDate,
predictedBleedingStart,
-180
View File
@@ -1,180 +0,0 @@
import React, { Component } from 'react'
import { ScrollView, StyleSheet, View } from 'react-native'
import PropTypes from 'prop-types'
import { LocalDate } from 'js-joda'
import { connect } from 'react-redux'
import { navigate } from '../slices/navigation'
import { getDate, setDate } from '../slices/date'
import AppText from './common/app-text'
import Button from './common/button'
import cycleModule from '../lib/cycle'
import { getFertilityStatusForDay } from '../lib/sympto-adapter'
import { determinePredictionText, formatWithOrdinalSuffix } from './helpers/home'
import { Colors, Fonts, Sizes, Spacing } from '../styles'
import { home as labels } from '../i18n/en/labels'
class Home extends Component {
static propTypes = {
navigate: PropTypes.func,
setDate: PropTypes.func
}
constructor(props) {
super(props)
const today = LocalDate.now()
this.todayDateString = today.toString()
const { getCycleDayNumber, getPredictedMenses } = cycleModule()
this.cycleDayNumber = getCycleDayNumber(this.todayDateString)
const { status, phase, statusText } =
getFertilityStatusForDay(this.todayDateString)
const prediction = getPredictedMenses()
this.prediction = determinePredictionText(prediction)
this.title = `${today.dayOfMonth()} ${today.month()} ${today.year()}`
if (this.cycleDayNumber) {
this.cycleDayText = formatWithOrdinalSuffix(this.cycleDayNumber)
}
if (phase) {
this.phase = phase
this.phaseText = formatWithOrdinalSuffix(phase)
this.status = status
this.statusText = statusText
}
}
navigateToCycleDayView = () => {
this.props.setDate(this.todayDateString)
this.props.navigate('CycleDay')
}
render() {
const {
cycleDayNumber,
cycleDayText,
phase,
phaseText,
prediction,
status,
statusText,
title
} = this
return (
<ScrollView
style={styles.container}
contentContainerStyle={styles.contentContainer}
>
<AppText style={styles.title}>{title}</AppText>
{cycleDayNumber &&
<View style={styles.line}>
<AppText style={styles.whiteSubtitle}>{cycleDayText}</AppText>
<AppText style={styles.turquoiseText}>{labels.cycleDay}</AppText>
</View>
}
{phase &&
<View style={styles.line}>
<AppText style={styles.whiteSubtitle}>{phaseText}</AppText>
<AppText style={styles.turquoiseText}>
{labels.cyclePhase}
</AppText>
<AppText style={styles.turquoiseText}>{status}</AppText>
<Asterisk />
</View>
}
<View style={styles.line}>
<AppText style={styles.turquoiseText}>{prediction}</AppText>
</View>
<Button isCTA isSmall={false} onPress={this.navigateToCycleDayView}>
{labels.addData}
</Button>
{phase && (
<View style={styles.asteriskLine}>
<Asterisk />
<AppText linkStyle={styles.whiteText} style={styles.greyText}>
{statusText}
</AppText>
</View>
)}
</ScrollView>
)
}
}
const Asterisk = () => {
return <AppText style={styles.asterisk}>*</AppText>
}
const styles = StyleSheet.create({
asterisk: {
color: Colors.orange,
},
container: {
backgroundColor: Colors.purple,
flex: 1,
},
contentContainer: {
padding: Spacing.base,
paddingTop: 0,
},
line: {
flexDirection: 'row',
flexWrap: 'wrap',
alignContent: 'flex-start',
marginBottom: Spacing.tiny,
marginTop: Spacing.small,
},
asteriskLine: {
flexDirection: 'row',
alignContent: 'flex-start',
marginBottom: Spacing.tiny,
marginTop: Spacing.small,
},
title: {
color: Colors.purpleLight,
fontFamily: Fonts.bold,
fontSize: Sizes.huge,
marginVertical: Spacing.small,
},
turquoiseText: {
color: Colors.turquoise,
fontSize: Sizes.subtitle,
},
whiteSubtitle: {
color: 'white',
fontSize: Sizes.subtitle,
},
whiteText: {
color: 'white',
},
greyText: {
color: Colors.greyLight,
paddingLeft: Spacing.base,
}
})
const mapStateToProps = (state) => {
return ({
date: getDate(state),
})
}
const mapDispatchToProps = (dispatch) => {
return ({
navigate: (page) => dispatch(navigate(page)),
setDate: (date) => dispatch(setDate(date)),
})
}
export default connect(
mapStateToProps,
mapDispatchToProps,
)(Home)
+1 -1
View File
@@ -1,4 +1,4 @@
import Home from './home'
import Home from './Home'
import Calendar from './calendar'
import CycleDay from './cycle-day/cycle-day-overview'
import Chart from './chart/chart'
+12
View File
@@ -0,0 +1,12 @@
{
"labels": {
"home": {
"cycleDay": " day of your cycle",
"cyclePhase": " cycle phase - ",
"addDataForToday": "add data for today"
},
"bleedingPrediction": {
"noPrediction": "As soon as you have tracked 3 menstrual cycles, drip will make predictions for the next ones."
}
}
}
-4
View File
@@ -4,9 +4,6 @@ const settingsTitles = labels.menuItems
export const home = {
unknown: '?',
phase: n => `${['1st', '2nd', '3rd'][n - 1]} cycle phase`,
cycleDay: ' day of your cycle',
cyclePhase: ' cycle phase - ',
addData: 'add data for today'
}
export const chart = {
@@ -69,7 +66,6 @@ export const stats = {
}
export const bleedingPrediction = {
noPrediction: `As soon as you have tracked 3 menstrual cycles, drip will make predictions for the next ones.`,
predictionInFuture: (startDays, endDays) => `Your next period is likely to start in ${startDays} to ${endDays} days.`,
predictionStartedXDaysLeft: (numberOfDays) => `Your period is likely to start today or within the next ${numberOfDays} days.`,
predictionStarted1DayLeft: 'Your period is likely to start today or tomorrow.',
+28
View File
@@ -0,0 +1,28 @@
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
// translation files
import en from './en.json';
const resources = {
en: { translation: en },
};
i18n
// pass the i18n instance to react-i18next.
.use(initReactI18next)
// init i18next
// for all options read: https://www.i18next.com/overview/configuration-options
.init({
resources,
fallbackLng: 'en',
debug: true,
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
}
});
export default i18n;
+1
View File
@@ -1,4 +1,5 @@
import { AppRegistry } from 'react-native'
import AppWrapper from './components/app-wrapper'
import './i18n/i18n';
AppRegistry.registerComponent('drip', () => AppWrapper)
+17708 -14
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -33,6 +33,7 @@
"@react-native-community/push-notification-ios": "^1.8.0",
"assert": "^1.4.1",
"csvtojson": "^2.0.8",
"i18next": "^20.2.2",
"isobject": "^3.0.1",
"js-joda": "^1.8.2",
"moment": "^2.22.2",
@@ -41,6 +42,7 @@
"obv": "0.0.1",
"prop-types": "^15.6.2",
"react": "16.9.0",
"react-i18next": "^11.8.15",
"react-native": "0.61.0",
"react-native-calendars": "^1.19.3",
"react-native-document-picker": "^4.2.0",