Internationalize remaining TODO-marked UI text in Expo app
This commit is contained in:
@@ -4,6 +4,7 @@ import { StyleSheet, SafeAreaView, FlatList, View, ActivityIndicator } from 'rea
|
||||
import API from "../API";
|
||||
import GroupCard from "../components/GroupCard";
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import i18n from "../i18nMessages.js";
|
||||
|
||||
const GROUPS_CACHE_KEY = 'groups_following';
|
||||
|
||||
@@ -113,7 +114,7 @@ const Groups = ({navigation}) => {
|
||||
}} />
|
||||
</View> :
|
||||
<Searchbar
|
||||
placeholder="Search Groups"
|
||||
placeholder={i18n.t("message.searchGroups")}
|
||||
onChangeText={onChangeSearch}
|
||||
value={searchQuery}
|
||||
clearButtonMode="while-editing"
|
||||
@@ -125,7 +126,7 @@ const Groups = ({navigation}) => {
|
||||
/>
|
||||
}
|
||||
</View>
|
||||
<Title style={styles.title} >{searchQuery ? "Results:" : "Your Groups:"}</Title>
|
||||
<Title style={styles.title} >{searchQuery ? i18n.t("message.results") : i18n.t("message.yourGroups")}</Title>
|
||||
</>
|
||||
}
|
||||
style={{backgroundColor: "#edf2f7",}}
|
||||
|
||||
@@ -72,10 +72,12 @@ let InviteView = ()=>{
|
||||
onPress={()=>{setChecked(!checked)}}
|
||||
/>
|
||||
<Divider />
|
||||
<Button mode="outlined" onPress={sendInvite}>Invite</Button>
|
||||
<Button mode="outlined" onPress={sendInvite}>
|
||||
{i18n.t("message.invite")}
|
||||
</Button>
|
||||
</ImageBackground>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default InviteView;
|
||||
export default InviteView;
|
||||
|
||||
@@ -30,7 +30,7 @@ export default function App({ navigation, route }) {
|
||||
style={styles.logo}
|
||||
source={require('./../assets/icon.png')}
|
||||
/>
|
||||
<Text style={styles.header}>EMI Fellowship</Text>
|
||||
<Text style={styles.header}>{i18n.t("message.appName")}</Text>
|
||||
<View style={{ flexDirection: "row", justifyContent: "center", width: "100%" }}>
|
||||
<Button disabled={isLogin} onPress={() => setIsLogin(true)}>
|
||||
{i18n.t("message.login")}
|
||||
|
||||
@@ -71,33 +71,33 @@ let MenuView = ({ navigation }) => {
|
||||
>
|
||||
<ProfileCardHorizontal profileObj={viewer} skipFollow={true} skiptOnPress={true} key={viewer._id} />
|
||||
<List.Accordion
|
||||
title="Change Active Profile"
|
||||
title={i18n.t("message.changeActiveProfile")}
|
||||
left={props => <List.Icon {...props} icon="published-with-changes" />}
|
||||
|
||||
>
|
||||
{profileLists}
|
||||
</List.Accordion>
|
||||
<List.Section title="User Actions">
|
||||
<List.Section title={i18n.t("message.userActions")}>
|
||||
<List.Item key='ProfileEditor' title={i18n.t('message.profile')} onPress={() => { navigation.navigate("ProfileSettings") }} left={props => <List.Icon {...props} icon="person" />} />
|
||||
<List.Item key='Settings' title={i18n.t('message.settings')} left={props => <List.Icon {...props} icon="settings" />} />
|
||||
<List.Item key="Logout" title={i18n.t('message.logout')} onPress={() => { navigation.navigate("Logout") }} left={props => <List.Icon {...props} icon="logout" />} />
|
||||
</List.Section>
|
||||
<List.Section title="Fellowship App">
|
||||
<List.Section title={i18n.t("message.fellowshipApp")}>
|
||||
<List.Item key='Invite' title={i18n.t('message.invite')} onPress={() => { navigation.navigate("Invite") }} left={props => <List.Icon {...props} icon="person-add" />} />
|
||||
<List.Item key='About' title={i18n.t('message.about')} left={props => <List.Icon {...props} icon="more" />} />
|
||||
</List.Section>
|
||||
<View style={{ padding: 10 }}>
|
||||
<Text>App Language:</Text>
|
||||
<Text>{i18n.t("message.appLanguage")}:</Text>
|
||||
<RadioButton.Group onValueChange={newValue => changeLang(newValue)} value={value}>
|
||||
<RadioButton.Item value="es" label="Español" />
|
||||
<RadioButton.Item value="en" label="English" />
|
||||
<RadioButton.Item value="da" label="Danish" />
|
||||
<RadioButton.Item value="fr" label="French" />
|
||||
<RadioButton.Item value="es" label={i18n.t("message.languageSpanish")} />
|
||||
<RadioButton.Item value="en" label={i18n.t("message.languageEnglish")} />
|
||||
<RadioButton.Item value="da" label={i18n.t("message.languageDanish")} />
|
||||
<RadioButton.Item value="fr" label={i18n.t("message.languageFrench")} />
|
||||
</RadioButton.Group>
|
||||
</View>
|
||||
<View style={{ padding: 10, alignContent: "center", flex: 1 }}>
|
||||
<Text>Version: {Updates.runtimeVersion}</Text>
|
||||
<Text>Channel: {Updates.Channel}</Text>
|
||||
<Text>{i18n.t("message.version")}: {Updates.runtimeVersion}</Text>
|
||||
<Text>{i18n.t("message.channel")}: {Updates.Channel}</Text>
|
||||
</View>
|
||||
</ImageBackground>
|
||||
</ScrollView>
|
||||
|
||||
@@ -3,6 +3,7 @@ import { StyleSheet, SafeAreaView, ImageBackground, View, ScrollView, Alert, Ima
|
||||
import { Title, TextInput, Button, Text, Switch } from 'react-native-paper';
|
||||
import API from "../API";
|
||||
import * as ImagePicker from 'expo-image-picker';
|
||||
import i18n from "../i18nMessages.js";
|
||||
|
||||
const DefaultPhoto = "https://social.emmint.com/uploads/e6f9be6d665dc43417701bf16a90122c.png";
|
||||
|
||||
@@ -108,33 +109,33 @@ const NewGroup = ({ navigation }) => {
|
||||
imageStyle={styles.backgroundImage}
|
||||
>
|
||||
<ScrollView contentContainerStyle={styles.container}>
|
||||
<Title style={styles.title}>New Group</Title>
|
||||
<Title style={styles.title}>{i18n.t("message.newGroup")}</Title>
|
||||
<View style={styles.photoRow}>
|
||||
<Image
|
||||
source={{ uri: selectedPhoto?.uri || DefaultPhoto }}
|
||||
style={styles.photoPreview}
|
||||
/>
|
||||
<Button mode="outlined" icon="photo" onPress={pickImage} disabled={isSubmitting}>
|
||||
{selectedPhoto ? "Change image" : "Add group image"}
|
||||
{selectedPhoto ? i18n.t("message.changeImage") : i18n.t("message.addGroupImage")}
|
||||
</Button>
|
||||
</View>
|
||||
<TextInput
|
||||
mode="outlined"
|
||||
label="Group name"
|
||||
label={i18n.t("message.groupName")}
|
||||
value={title}
|
||||
onChangeText={setTitle}
|
||||
style={styles.input}
|
||||
/>
|
||||
<TextInput
|
||||
mode="outlined"
|
||||
label="Subtitle (optional)"
|
||||
label={i18n.t("message.subtitleOptional")}
|
||||
value={subtitle}
|
||||
onChangeText={setSubtitle}
|
||||
style={styles.input}
|
||||
/>
|
||||
<TextInput
|
||||
mode="outlined"
|
||||
label="Description"
|
||||
label={i18n.t("message.description")}
|
||||
value={description}
|
||||
onChangeText={setDescription}
|
||||
multiline
|
||||
@@ -143,8 +144,8 @@ const NewGroup = ({ navigation }) => {
|
||||
/>
|
||||
<View style={styles.switchRow}>
|
||||
<View style={styles.switchTextWrap}>
|
||||
<Text style={styles.switchTitle}>Private group</Text>
|
||||
<Text style={styles.switchSubtitle}>Require approval before people can join.</Text>
|
||||
<Text style={styles.switchTitle}>{i18n.t("message.privateGroup")}</Text>
|
||||
<Text style={styles.switchSubtitle}>{i18n.t("message.requireApprovalBeforeJoin")}</Text>
|
||||
</View>
|
||||
<Switch value={isPrivate} onValueChange={setIsPrivate} />
|
||||
</View>
|
||||
@@ -155,7 +156,7 @@ const NewGroup = ({ navigation }) => {
|
||||
disabled={isSubmitting}
|
||||
style={styles.button}
|
||||
>
|
||||
Create Group
|
||||
{i18n.t("message.createGroupAction")}
|
||||
</Button>
|
||||
</ScrollView>
|
||||
</ImageBackground>
|
||||
|
||||
@@ -170,7 +170,7 @@ let NewPostView = (props) => {
|
||||
{
|
||||
toProfile._id ?
|
||||
<Text style={{ paddingLeft: 10, paddingBottom: 5 }}>
|
||||
Posting on: {toProfile.profile?.firstName} {toProfile.profile?.lastName}
|
||||
{i18n.t("message.postingOn")}: {toProfile.profile?.firstName} {toProfile.profile?.lastName}
|
||||
</Text> : null
|
||||
}
|
||||
<Divider bold={true} />
|
||||
@@ -178,7 +178,7 @@ let NewPostView = (props) => {
|
||||
<TextInput
|
||||
value={postContent}
|
||||
onChangeText={setPostContent}
|
||||
placeholder="What is on your mind today?"
|
||||
placeholder={i18n.t("message.whatIsOnYourMindToday")}
|
||||
multiline={true}
|
||||
numberOfLines={8}
|
||||
style={{
|
||||
@@ -194,18 +194,18 @@ let NewPostView = (props) => {
|
||||
{/* Button to pick images from the gallery */}
|
||||
<View style={{ flexDirection: "row", marginTop: 10, justifyContent: "space-around" }}>
|
||||
<Button icon="add-a-photo" mode="outlined" onPress={pickImage}>
|
||||
Add Photos
|
||||
{i18n.t("message.addPhotos")}
|
||||
</Button>
|
||||
{isUploading && (
|
||||
<Button icon="cancel" mode="outlined" onPress={handleCancelUpload}>
|
||||
Cancel Upload
|
||||
{i18n.t("message.cancelUpload")}
|
||||
</Button>
|
||||
)}
|
||||
</View>
|
||||
{/* Display uploading state and selected image preview */}
|
||||
{photo && (
|
||||
<View>
|
||||
<Text>Uploading...</Text>
|
||||
<Text>{i18n.t("message.uploading")}</Text>
|
||||
<Image
|
||||
source={{ uri: photo.uri }}
|
||||
style={{ width: 100, height: 100 }}
|
||||
@@ -215,7 +215,7 @@ let NewPostView = (props) => {
|
||||
{/* Display upload progress if in progress */}
|
||||
{
|
||||
uploadProgress > 0 && uploadProgress < 100 && (
|
||||
<Text>Upload Progress: {uploadProgress.toFixed(2)}%</Text>
|
||||
<Text>{i18n.t("message.uploadProgress")}: {uploadProgress.toFixed(2)}%</Text>
|
||||
)
|
||||
}
|
||||
{/* Display media content if extra content is available */}
|
||||
@@ -229,4 +229,4 @@ let NewPostView = (props) => {
|
||||
)
|
||||
}
|
||||
|
||||
export default NewPostView;
|
||||
export default NewPostView;
|
||||
|
||||
@@ -9,6 +9,7 @@ import ProfileHeader from '../components/ProfileHeader.js';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import { useSnapshot } from 'valtio';
|
||||
import GlobalState from '../contexts/GlobalState.js';
|
||||
import i18n from "../i18nMessages.js";
|
||||
|
||||
const PROFILE_LOG_PREFIX = '[Profile]';
|
||||
const logProfile = (...args) => {
|
||||
@@ -203,18 +204,18 @@ let Profile = ({ navigation, route }) => {
|
||||
navigation.navigate('NewPost', {toProfile: profile._id})
|
||||
}} />
|
||||
</View>
|
||||
<Button style={{paddingLeft:12, backgroundColor:"#fff"}} title="Images" icon={tag == 'images' ? 'remove' : "image"} mode="outlined" onPress={()=>{
|
||||
<Button style={{paddingLeft:12, backgroundColor:"#fff"}} title={i18n.t("message.images")} icon={tag == 'images' ? 'remove' : "image"} mode="outlined" onPress={()=>{
|
||||
if(tag == 'images') return setTag('');
|
||||
setTag('images');
|
||||
}}>{tag == 'images' ? "Images" : ''}</Button>
|
||||
<Button style={{paddingLeft:12, backgroundColor:"#fff"}} title="Media" icon={tag == 'media' ? 'remove' : "subscriptions"} mode="outlined" onPress={()=>{
|
||||
}}>{tag == 'images' ? i18n.t("message.images") : ''}</Button>
|
||||
<Button style={{paddingLeft:12, backgroundColor:"#fff"}} title={i18n.t("message.media")} icon={tag == 'media' ? 'remove' : "subscriptions"} mode="outlined" onPress={()=>{
|
||||
if(tag == 'media') return setTag('');
|
||||
setTag('media');
|
||||
}}>{tag == 'media' ? "Media" : ''}</Button>
|
||||
<Button style={{paddingLeft:12, backgroundColor:"#fff"}} title="Embedded" icon={tag == 'embedded' ? 'remove' : "folder"} mode="outlined" onPress={()=>{
|
||||
}}>{tag == 'media' ? i18n.t("message.media") : ''}</Button>
|
||||
<Button style={{paddingLeft:12, backgroundColor:"#fff"}} title={i18n.t("message.embedded")} icon={tag == 'embedded' ? 'remove' : "folder"} mode="outlined" onPress={()=>{
|
||||
if(tag == 'embedded') return setTag('');
|
||||
setTag('embedded');
|
||||
}}>{tag == 'embedded' ? "Files" : ''}</Button>
|
||||
}}>{tag == 'embedded' ? i18n.t("message.files") : ''}</Button>
|
||||
</View>
|
||||
{isOwnedGroup ? (
|
||||
<View style={styles.deleteGroupRow}>
|
||||
@@ -226,7 +227,7 @@ let Profile = ({ navigation, route }) => {
|
||||
disabled={isDeletingGroup}
|
||||
onPress={handleDeleteGroup}
|
||||
>
|
||||
Delete Group
|
||||
{i18n.t("message.deleteGroup")}
|
||||
</Button>
|
||||
</View>
|
||||
) : <></>}
|
||||
|
||||
@@ -41,12 +41,12 @@ let ProfileSettings = () => {
|
||||
};
|
||||
|
||||
const languageOptions = [
|
||||
{ value: "es", label: "Español" },
|
||||
{ value: "en", label: "English" },
|
||||
{ value: "da", label: "Danish" },
|
||||
{ value: "fr", label: "French" },
|
||||
{ value: "es", label: i18n.t("message.languageSpanish") },
|
||||
{ value: "en", label: i18n.t("message.languageEnglish") },
|
||||
{ value: "da", label: i18n.t("message.languageDanish") },
|
||||
{ value: "fr", label: i18n.t("message.languageFrench") },
|
||||
];
|
||||
const currentLanguageLabel = languageOptions.find((opt) => opt.value === language)?.label || "English";
|
||||
const currentLanguageLabel = languageOptions.find((opt) => opt.value === language)?.label || i18n.t("message.languageEnglish");
|
||||
|
||||
const pickImage = async () => {
|
||||
if (uploading) return;
|
||||
@@ -176,8 +176,10 @@ let ProfileSettings = () => {
|
||||
<View style={{ paddingTop: 10 }}>
|
||||
<ProfileCardHorizontal profileObj={previewProfile} skipFollow={true} skiptOnPress={true} key={updateKey} />
|
||||
</View>
|
||||
<Text style={{ marginBottom: 10, marginTop: 10, fontSize: 20 }}>Profile Setting</Text>
|
||||
<Button icon="photo" mode="outlined" onPress={pickImage}>{!uploading ? i18n.t("message.updatePhoto") : "uploading"}</Button>
|
||||
<Text style={{ marginBottom: 10, marginTop: 10, fontSize: 20 }}>{i18n.t("message.profileSetting")}</Text>
|
||||
<Button icon="photo" mode="outlined" onPress={pickImage}>
|
||||
{!uploading ? i18n.t("message.updatePhoto") : i18n.t("message.uploading")}
|
||||
</Button>
|
||||
<Divider />
|
||||
<View style={{ flexDirection: "row", justifyContent: "space-between" }}>
|
||||
<TextInput
|
||||
@@ -201,7 +203,7 @@ let ProfileSettings = () => {
|
||||
value={description}
|
||||
onChangeText={text => setDescription(text)}
|
||||
/>
|
||||
<Text style={{ marginBottom: 4 }}>Language:</Text>
|
||||
<Text style={{ marginBottom: 4 }}>{i18n.t("message.language")}:</Text>
|
||||
<View style={{ marginBottom: 10 }}>
|
||||
<Menu
|
||||
visible={languageMenuVisible}
|
||||
|
||||
@@ -6,6 +6,7 @@ import ProfileCardHorizontal from "../components/ProfileCardHorizontal";
|
||||
import { useSnapshot } from 'valtio';
|
||||
import GlobalState from '../contexts/GlobalState.js';
|
||||
import ProfileHeader from "../components/ProfileHeader";
|
||||
import i18n from "../i18nMessages.js";
|
||||
|
||||
const Search = () => {
|
||||
const viewer = useSnapshot(GlobalState).me;
|
||||
@@ -47,7 +48,7 @@ const Search = () => {
|
||||
return (
|
||||
<SafeAreaView style={{ flex: 1, backgroundColor: "#edf2f7", }}>
|
||||
<Searchbar
|
||||
placeholder="Search Users"
|
||||
placeholder={i18n.t("message.searchUsers")}
|
||||
onChangeText={onChangeSearch}
|
||||
value={searchQuery}
|
||||
/>
|
||||
@@ -66,7 +67,7 @@ const Search = () => {
|
||||
data={followers}
|
||||
renderItem={renderFollowing}
|
||||
keyExtractor={item => item}
|
||||
ListHeaderComponent={<Text style={{fontSize:20, padding:10, alignSelf: "center"}}>Recently Following</Text>}
|
||||
ListHeaderComponent={<Text style={{fontSize:20, padding:10, alignSelf: "center"}}>{i18n.t("message.recentlyFollowing")}</Text>}
|
||||
/>
|
||||
}
|
||||
</SafeAreaView>
|
||||
|
||||
@@ -43,23 +43,23 @@ let MenuView = ({ navigation }) => {
|
||||
style={{ paddingTop: 10 }}
|
||||
imageStyle={{ resizeMode: "contain", opacity: 0.05 }}
|
||||
>
|
||||
<List.Section title="Current Profile">
|
||||
<List.Section title={i18n.t("message.currentProfile")}>
|
||||
<ProfileCardHorizontal profileObj={viewer} skipFollow={true} skiptOnPress={true} />
|
||||
</List.Section>
|
||||
<List.Section title="User Actions">
|
||||
<List.Section title={i18n.t("message.userActions")}>
|
||||
<List.Item title={i18n.t('message.profile')} onPress={() => { navigation.navigate("ProfileSettings") }} left={props => <List.Icon {...props} icon="person" />} />
|
||||
<List.Item title={i18n.t('message.settings')} left={props => <List.Icon {...props} icon="settings" />} />
|
||||
<List.Item title={i18n.t('message.logout')} onPress={() => { navigation.navigate("Logout") }} left={props => <List.Icon {...props} icon="logout" />} />
|
||||
</List.Section>
|
||||
<List.Section title="Fellowship App">
|
||||
<List.Section title={i18n.t("message.fellowshipApp")}>
|
||||
<List.Item title={i18n.t('message.invite')} onPress={() => { navigation.navigate("Invite") }} left={props => <List.Icon {...props} icon="person-add" />} />
|
||||
<List.Item title={i18n.t('message.about')} left={props => <List.Icon {...props} icon="more" />} />
|
||||
</List.Section>
|
||||
<View style={{ padding: 10 }}>
|
||||
<Text>Language:</Text>
|
||||
<Text>{i18n.t("message.language")}:</Text>
|
||||
<RadioButton.Group onValueChange={newValue => changeLang(newValue)} value={value}>
|
||||
<RadioButton.Item value="es" label="Español" />
|
||||
<RadioButton.Item value="en" label="English" />
|
||||
<RadioButton.Item value="es" label={i18n.t("message.languageSpanish")} />
|
||||
<RadioButton.Item value="en" label={i18n.t("message.languageEnglish")} />
|
||||
</RadioButton.Group>
|
||||
</View>
|
||||
</ImageBackground>
|
||||
@@ -67,4 +67,4 @@ let MenuView = ({ navigation }) => {
|
||||
)
|
||||
}
|
||||
|
||||
export default MenuView;
|
||||
export default MenuView;
|
||||
|
||||
Reference in New Issue
Block a user