Skip to content

Commit

Permalink
refactor: Setup translations (#69)
Browse files Browse the repository at this point in the history
* Update .gitignore

* Implement translation package & translate ErrorScreen

* Finish translations setup

* Minor lint fixes

* Update App/localization/languages/en.json

Co-Authored-By: lucienbl <[email protected]>

* Update .gitignore

* Remove unused string
  • Loading branch information
lucienbl authored and amaury1093 committed Apr 17, 2019
1 parent 26c6c88 commit 86919a9
Show file tree
Hide file tree
Showing 18 changed files with 158 additions and 68 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,7 @@ yarn-error.log*
.DS_Store

# secrets
app.json
app.json

# ide files
.idea/
41 changes: 15 additions & 26 deletions App/Screens/About/About.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Linking, ScrollView, StyleSheet, Text, View } from 'react-native';
import { Box } from './Box';
import * as theme from '../../utils/theme';
import { BackButton } from '../../components/BackButton';
import {i18n} from '../../localization';

export class About extends PureComponent {
handleOpenAmaury = () => Linking.openURL('https://twitter.com/amaurymartiny');
Expand All @@ -32,15 +33,14 @@ export class About extends PureComponent {

<View style={styles.section}>
<Text style={styles.h2}>
How do you calculate the number of cigarettes?
{i18n.t('about_how_do_you_calculate_the_number_of_cigarettes_title')}
</Text>
<Text style={theme.text}>
This app was inspired by Berkeley Earth’s findings about the{' '}
{i18n.t('about_how_do_you_calculate_the_number_of_cigarettes_message_1')}{' '}
<Text onPress={this.handleOpenArticle} style={theme.link}>
equivalence between air pollution and cigarette smoking
{i18n.t('about_how_do_you_calculate_the_number_of_cigarettes_link_1')}
</Text>
. The rule of thumb is simple: one cigarette per day is the rough
equivalent of a PM2.5 level of 22{' '}
{i18n.t('about_how_do_you_calculate_the_number_of_cigarettes_message_2')}{' '}
<Text style={styles.micro}>&micro;</Text>
g/m&sup3;
{' \u207D'}
Expand All @@ -57,46 +57,35 @@ export class About extends PureComponent {
</View>

<View style={styles.section}>
<Text style={styles.h2}>Where does the data come from?</Text>
<Text style={styles.h2}>{i18n.t('about_where_does_data_come_from_title')}</Text>
<Text style={theme.text}>
Air quality data comes from{' '}
{i18n.t('about_where_does_data_come_from_message_1')}{' '}
<Text onPress={this.handleOpenAqi} style={theme.link}>
WAQI
{i18n.t('about_where_does_data_come_from_link_1')}
</Text>{' '}
in the form of PM2.5 AQI levels which are usually updated every one
hour and converted to direct PM2.5 levels by the app.
{i18n.t('about_were_does_data_come_from_message_2')}
</Text>
</View>

<View style={styles.section}>
<Text style={styles.h2}>
Why is the station so far away from my current location?
{i18n.t('about_why_is_the_station_so_far_title')}
</Text>
<Text style={theme.text}>
Since stations that measure and communicate Air Quality results
every hour are expensive, the data is still limited to
well-developed regions and larger cities around the globe. If you
are far from a more prominent urban center, results will probably
not be so accurate. Chances are that your air is better in that case
at least!
{i18n.t('about_why_is_the_station_so_far_message')}
</Text>
</View>

<View style={styles.section}>
<Text style={styles.h2}>
The results are weird or inconsistent with other sources!
{i18n.t('about_weird_results_title')}
</Text>
<Text style={theme.text}>
We have also encountered a few surprising results: large cities with
better air than small villages; sudden huge increases in the number
of cigarettes; stations of the same town showing significantly
different numbers... The fact is air quality depends on several
factors such as temperature, pressure, humidity and even wind
direction and intensity. If the result seems weird for you, check{' '}
{i18n.t('about_weird_results_message_1')}{' '}
<Text onPress={this.handleOpenAqi} style={theme.link}>
WAQI
{i18n.t('about_weird_results_link_1')}
</Text>{' '}
for more information and history on your station.
{i18n.t('about_weird_results_message_2')}
</Text>
</View>

Expand Down
5 changes: 3 additions & 2 deletions App/Screens/Details/Details.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { Header } from './Header';
import homeIcon from '../../../assets/images/home.png';
import stationIcon from '../../../assets/images/station.png';
import * as theme from '../../utils/theme';
import {i18n} from '../../localization';

@inject('stores')
@observer
Expand Down Expand Up @@ -83,14 +84,14 @@ export class Details extends Component {
coordinate={station}
image={stationIcon}
ref={this.handleStationRef}
title='Air Quality Station'
title={i18n.t('details_air_quality_station_marker')}
description={truncate(station.description, 40)}
/>
<MapView.Marker
color='blue'
coordinate={currentLocation}
image={homeIcon}
title='Your position'
title={i18n.t('details_your_position_marker')}
/>
</MapView>
)}
Expand Down
3 changes: 2 additions & 1 deletion App/Screens/Details/Distance/Distance.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { StyleSheet, Text } from 'react-native';

import { Banner } from '../../../components/Banner';
import * as theme from '../../../utils/theme';
import {i18n} from '../../../localization';

@inject('stores')
@observer
Expand All @@ -19,7 +20,7 @@ export class Distance extends Component {
return (
<Banner elevated shadowPosition='top' style={styles.banner}>
<Text style={styles.distance}>
AQI STATION: {distanceToStation}KM AWAY
{i18n.t('details_distance_label', { distanceToStation }).toUpperCase()}
</Text>
</Banner>
);
Expand Down
5 changes: 3 additions & 2 deletions App/Screens/Details/Header/Header.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { BackButton } from '../../../components/BackButton';
import locationIcon from '../../../../assets/images/location.png';
import { CurrentLocation } from '../../../components/CurrentLocation';
import * as theme from '../../../utils/theme';
import {i18n} from '../../../localization';

const trackedPollutant = ['pm25', 'pm10', 'co', 'o3', 'no2', 'so2'];

Expand Down Expand Up @@ -37,11 +38,11 @@ export class Header extends Component {
<CurrentLocation style={styles.currentLocation} />
{lastUpdated &&
this.renderInfo(
'Latest Update:',
i18n.t('details_header_latest_update_label'),
formatRelative(lastUpdated, new Date())
)}
{dominentpol &&
this.renderInfo('Primary pollutant:', dominentpol.toUpperCase())}
this.renderInfo(i18n.t('details_header_primary_pollutant_label'), dominentpol.toUpperCase())}

<View style={styles.pollutants}>
{trackedPollutant.map(
Expand Down
15 changes: 6 additions & 9 deletions App/Screens/ErrorScreen/ErrorScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native';

import error from '../../../assets/images/error.png';
import * as theme from '../../utils/theme';
import { i18n } from '../../localization';

@inject('stores')
@observer
Expand All @@ -21,23 +22,19 @@ export class ErrorScreen extends Component {
<Image source={error} />
<View>
<Text style={styles.errorText}>
<Text style={styles.sorry}>Sorry!</Text>
{'\n'}
We cannot
{'\n'}
load your cigarettes.
<Text style={styles.sorry}>{i18n.t('error_screen_common_sorry')}</Text>
{i18n.t('error_screen_error_cannot_load_cigarettes')}
</Text>
</View>
<TouchableOpacity onPress={this.goToSearch}>
<View style={styles.chooseOther}>
<Text style={theme.bigButtonText}>CHOOSE OTHER LOCATION</Text>
<Text style={theme.bigButtonText}>{i18n.t('error_screen_choose_other_location').toUpperCase()}</Text>
</View>
</TouchableOpacity>
<Text style={theme.text}>
There's either a problem with our databases, or you don't have any Air
Monitoring Stations near you. Try again later!
{i18n.t('error_screen_error_description')}
</Text>
<Text style={styles.errorMessage}>Error: {errorText}</Text>
<Text style={styles.errorMessage}>{i18n.t('error_screen_error_message', { errorText })}</Text>
</View>
);
}
Expand Down
4 changes: 2 additions & 2 deletions App/Screens/Home/Header/Header.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import changeLocation from '../../../../assets/images/changeLocation.png';
import { CurrentLocation } from '../../../components/CurrentLocation';
import * as theme from '../../../utils/theme';
import warning from '../../../../assets/images/warning.png';
import {i18n} from '../../../localization';

@inject('stores')
@observer
Expand All @@ -33,8 +34,7 @@ export class Header extends Component {
<Image source={warning} style={styles.warning} />
)}
<Text style={theme.text}>
Air Quality Station: {distanceToStation}
km away
{i18n.t('home_header_air_quality_station_distance', { distanceToStation })}
</Text>
</View>
</View>
Expand Down
46 changes: 26 additions & 20 deletions App/Screens/Home/Home.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { SmallButton } from './SmallButton';
import { SmokeVideo } from './SmokeVideo';
import swearWords from './swearWords';
import * as theme from '../../utils/theme';
import {i18n} from '../../localization';

@inject('stores')
@observer
Expand All @@ -30,11 +31,8 @@ export class Home extends Component {

handleShare = () =>
Share.share({
title:
'Did you know that you may be smoking up to 20 cigarettes per day, just for living in a big city?',
message: `Shoot! I 'smoked' ${
this.props.stores.cigarettes
} cigarettes today by breathing urban air. And you? Find out here: https://shootismoke.github.io`
title: i18n.t('home_share_title'),
message: i18n.t('home_share_message', { cigarettes: this.props.stores.cigarettes })
});

render () {
Expand All @@ -57,8 +55,7 @@ export class Home extends Component {
<View style={styles.cta}>
{isStationTooFar && (
<Text style={styles.isStationTooFar}>
We couldn’t find a closer station to you.{'\n'}Results may be
inaccurate at this distance.
{i18n.t('home_station_too_far_message')}
</Text>
)}
{this.renderBigButton()}
Expand All @@ -77,7 +74,7 @@ export class Home extends Component {
return (
<TouchableOpacity onPress={this.goToAbout}>
<View style={theme.bigButton}>
<Text style={theme.bigButtonText}>WHY IS THE STATION SO FAR?</Text>
<Text style={theme.bigButtonText}>{i18n.t('home_btn_why_is_station_so_far').toUpperCase()}</Text>
</View>
</TouchableOpacity>
);
Expand All @@ -86,7 +83,7 @@ export class Home extends Component {
return (
<TouchableOpacity onPress={this.goToDetails}>
<View style={theme.bigButton}>
<Text style={theme.bigButtonText}>SEE DETAILED INFO</Text>
<Text style={theme.bigButtonText}>{i18n.t('home_btn_see_detailed_info').toUpperCase()}</Text>
</View>
</TouchableOpacity>
);
Expand All @@ -101,34 +98,34 @@ export class Home extends Component {
{isStationTooFar ? (
<SmallButton
icon='plus-circle'
text='MORE DETAILS'
text={i18n.t('home_btn_more_details').toUpperCase()}
onPress={this.goToDetails}
/>
) : (
<SmallButton
icon='question-circle'
text='FAQ/ABOUT'
text={i18n.t('home_btn_faq_about').toUpperCase()}
onPress={this.goToAbout}
/>
)}
<SmallButton icon='share-alt' text='SHARE' onPress={this.handleShare} />
<SmallButton icon='share-alt' text={i18n.t('home_btn_share').toUpperCase()} onPress={this.handleShare} />
</View>
);
};

renderPresentPast = () => {
const time = new Date().getHours();

if (time < 15) return "You'll smoke";
return 'You smoked';
if (time < 15) return i18n.t('home_common_you_ll_smoke');
return i18n.t('home_common_you_smoked');
};

renderShit = () => {
const {
stores: { cigarettes }
} = this.props;

if (cigarettes <= 1) return 'Oh';
if (cigarettes <= 1) return i18n.t('home_common_oh');

// Return a random swear word
return swearWords[Math.floor(Math.random() * swearWords.length)];
Expand All @@ -139,14 +136,23 @@ export class Home extends Component {
// Round to 1 decimal
const cigarettes = Math.round(stores.cigarettes * 10) / 10;

const text = i18n.t('home_smoked_cigarette_title', {
swearWord: this.renderShit(),
presentPast: this.renderPresentPast(),
singularPlural: cigarettes === 1 ? i18n.t('home_common_cigarette').toLowerCase() : i18n.t('home_common_cigarettes').toLowerCase(),
cigarettes
});

const firstPartText = text.split('<')[0];
const secondPartText = text.split('<')[1];

return (
<Text adjustsFontSizeToFit style={styles.shit}>
{this.renderShit()}! {this.renderPresentPast()}{' '}
{firstPartText}
<Text style={styles.cigarettesCount}>
{cigarettes} cigarette
{cigarettes === 1 ? '' : 's'}
</Text>{' '}
today.
{secondPartText.split('>')[0]}
</Text>
{secondPartText.split('>')[1]}
</Text>
);
};
Expand Down
11 changes: 11 additions & 0 deletions App/Screens/Home/swearWords.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { i18n } from '../../localization';

export default [
i18n.t('home_swear_word_shoot'),
i18n.t('home_swear_word_dang'),
i18n.t('home_swear_word_darn'),
i18n.t('home_swear_word_geez'),
i18n.t('home_swear_word_omg'),
i18n.t('home_swear_word_crap'),
i18n.t('home_swear_word_arrgh')
];
1 change: 0 additions & 1 deletion App/Screens/Home/swearWords.json

This file was deleted.

5 changes: 3 additions & 2 deletions App/Screens/Loading/Loading.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { StyleSheet, Text } from 'react-native';
import { Background } from './Background';
import * as dataSources from '../../utils/dataSources';
import * as theme from '../../utils/theme';
import {i18n} from '../../localization';

@inject('stores')
@observer
Expand Down Expand Up @@ -113,7 +114,7 @@ export class Loading extends Component {

renderCough = index => (
<Text key={index}>
Cough
{i18n.t('loading_title_cough')}
<Text style={styles.dots}>...</Text>
</Text>
);
Expand All @@ -133,7 +134,7 @@ export class Loading extends Component {

return (
<Text>
Loading
{i18n.t('loading_title_loading')}
<Text style={styles.dots}>...</Text>
{Array.from({ length: coughs }, (_, index) => index + 1).map(
// Create array 1..N and rendering Cough...
Expand Down
3 changes: 2 additions & 1 deletion App/Screens/Search/SearchHeader/SearchHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Image, StyleSheet, TextInput } from 'react-native';
import { Banner } from '../../../components/Banner';
import searchIcon from '../../../../assets/images/search.png';
import * as theme from '../../../utils/theme';
import {i18n} from '../../../localization';

export class SearchHeader extends PureComponent {
render () {
Expand All @@ -16,7 +17,7 @@ export class SearchHeader extends PureComponent {
<TextInput
autoFocus
onChangeText={onChangeSearch}
placeholder='Search for a city or address'
placeholder={i18n.t('search_header_input_placeholder')}
placeholderTextColor='rgba(255, 255, 255, 0.6)'
style={styles.input}
underlineColorAndroid='transparent'
Expand Down
Loading

0 comments on commit 86919a9

Please sign in to comment.