diff --git a/android/app/build.gradle b/android/app/build.gradle
index 8179f8603..8c3ef1d6d 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -172,6 +172,7 @@ repositories {
}
dependencies {
+ compile project(':react-native-i18n')
compile project(':react-native-fabric')
compile project(':react-native-audio')
compile project(":reactnativekeyboardinput")
diff --git a/android/app/src/main/java/chat/rocketchat/reactnative/CustomTabsAndroid.java b/android/app/src/main/java/chat/rocket/reactnative/CustomTabsAndroid.java
similarity index 100%
rename from android/app/src/main/java/chat/rocketchat/reactnative/CustomTabsAndroid.java
rename to android/app/src/main/java/chat/rocket/reactnative/CustomTabsAndroid.java
diff --git a/android/app/src/main/java/chat/rocketchat/reactnative/CustomTabsHelper.java b/android/app/src/main/java/chat/rocket/reactnative/CustomTabsHelper.java
similarity index 100%
rename from android/app/src/main/java/chat/rocketchat/reactnative/CustomTabsHelper.java
rename to android/app/src/main/java/chat/rocket/reactnative/CustomTabsHelper.java
diff --git a/android/app/src/main/java/chat/rocketchat/reactnative/MainActivity.java b/android/app/src/main/java/chat/rocket/reactnative/MainActivity.java
similarity index 100%
rename from android/app/src/main/java/chat/rocketchat/reactnative/MainActivity.java
rename to android/app/src/main/java/chat/rocket/reactnative/MainActivity.java
diff --git a/android/app/src/main/java/chat/rocketchat/reactnative/MainApplication.java b/android/app/src/main/java/chat/rocket/reactnative/MainApplication.java
similarity index 95%
rename from android/app/src/main/java/chat/rocketchat/reactnative/MainApplication.java
rename to android/app/src/main/java/chat/rocket/reactnative/MainApplication.java
index 7883ed1b2..c6fbea41c 100644
--- a/android/app/src/main/java/chat/rocketchat/reactnative/MainApplication.java
+++ b/android/app/src/main/java/chat/rocket/reactnative/MainApplication.java
@@ -20,6 +20,7 @@ import com.wix.reactnativekeyboardinput.KeyboardInputPackage;
import com.rnim.rn.audio.ReactNativeAudioPackage;
import com.smixx.fabric.FabricPackage;
import com.dylanvann.fastimage.FastImageViewPackage;
+import com.AlexanderZaytsev.RNI18n.RNI18nPackage;
import java.util.Arrays;
import java.util.List;
@@ -51,7 +52,8 @@ public class MainApplication extends Application implements ReactApplication {
new KeyboardInputPackage(MainApplication.this),
new RocketChatNativePackage(),
new FabricPackage(),
- new FastImageViewPackage()
+ new FastImageViewPackage(),
+ new RNI18nPackage()
);
}
};
diff --git a/android/app/src/main/java/chat/rocketchat/reactnative/RocketChatNativePackage.java b/android/app/src/main/java/chat/rocket/reactnative/RocketChatNativePackage.java
similarity index 100%
rename from android/app/src/main/java/chat/rocketchat/reactnative/RocketChatNativePackage.java
rename to android/app/src/main/java/chat/rocket/reactnative/RocketChatNativePackage.java
diff --git a/android/settings.gradle b/android/settings.gradle
index 1259f2ba9..ffb155c5c 100644
--- a/android/settings.gradle
+++ b/android/settings.gradle
@@ -1,4 +1,6 @@
rootProject.name = 'RocketChatRN'
+include ':react-native-i18n'
+project(':react-native-i18n').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-i18n/android')
include ':react-native-fast-image'
project(':react-native-fast-image').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fast-image/android')
include ':react-native-fabric'
diff --git a/app/containers/Banner.js b/app/containers/Banner.js
deleted file mode 100644
index ae7b75d1f..000000000
--- a/app/containers/Banner.js
+++ /dev/null
@@ -1,69 +0,0 @@
-import { StyleSheet, View, Text } from 'react-native';
-import PropTypes from 'prop-types';
-import React from 'react';
-
-import { connect } from 'react-redux';
-
-const styles = StyleSheet.create({
- bannerContainer: {
- backgroundColor: '#ddd'
- },
- bannerText: {
- textAlign: 'center',
- margin: 5
- }
-});
-
-@connect(state => ({
- connecting: state.meteor.connecting,
- authenticating: state.login.isFetching,
- offline: !state.meteor.connected,
- logged: !!state.login.token
-}))
-
-export default class Banner extends React.PureComponent {
- static propTypes = {
- connecting: PropTypes.bool,
- authenticating: PropTypes.bool,
- offline: PropTypes.bool
- }
- render() {
- const {
- connecting, authenticating, offline, logged
- } = this.props;
-
- if (offline) {
- return (
-
- offline...
-
- );
- }
-
- if (connecting) {
- return (
-
- Connecting...
-
- );
- }
-
- if (authenticating) {
- return (
-
- Authenticating...
-
- );
- }
-
- if (logged) {
- return this.props.children;
- }
-
- return (
-
- Not logged...
-
- );
- }
-}
diff --git a/app/containers/MessageActions.js b/app/containers/MessageActions.js
index d126600df..ee63c6ad9 100644
--- a/app/containers/MessageActions.js
+++ b/app/containers/MessageActions.js
@@ -18,6 +18,7 @@ import {
} from '../actions/messages';
import { showToast } from '../utils/info';
import RocketChat from '../lib/rocketchat';
+import I18n from '../i18n';
@connect(
state => ({
@@ -86,50 +87,50 @@ export default class MessageActions extends React.Component {
if (nextProps.showActions !== this.props.showActions && nextProps.showActions) {
const { actionMessage } = nextProps;
// Cancel
- this.options = ['Cancel'];
+ this.options = [I18n.t('Cancel')];
this.CANCEL_INDEX = 0;
// Reply
if (!this.isRoomReadOnly()) {
- this.options.push('Reply');
+ this.options.push(I18n.t('Reply'));
this.REPLY_INDEX = this.options.length - 1;
}
// Edit
if (this.allowEdit(nextProps)) {
- this.options.push('Edit');
+ this.options.push(I18n.t('Edit'));
this.EDIT_INDEX = this.options.length - 1;
}
// Permalink
- this.options.push('Copy Permalink');
+ this.options.push(I18n.t('Copy_Permalink'));
this.PERMALINK_INDEX = this.options.length - 1;
// Copy
- this.options.push('Copy Message');
+ this.options.push(I18n.t('Copy_Message'));
this.COPY_INDEX = this.options.length - 1;
// Share
- this.options.push('Share Message');
+ this.options.push(I18n.t('Share_Message'));
this.SHARE_INDEX = this.options.length - 1;
// Quote
if (!this.isRoomReadOnly()) {
- this.options.push('Quote');
+ this.options.push(I18n.t('Quote'));
this.QUOTE_INDEX = this.options.length - 1;
}
// Star
if (this.props.Message_AllowStarring) {
- this.options.push(actionMessage.starred ? 'Unstar' : 'Star');
+ this.options.push(I18n.t(actionMessage.starred ? 'Unstar' : 'Star'));
this.STAR_INDEX = this.options.length - 1;
}
// Pin
if (this.props.Message_AllowPinning) {
- this.options.push(actionMessage.pinned ? 'Unpin' : 'Pin');
+ this.options.push(I18n.t(actionMessage.pinned ? 'Unpin' : 'Pin'));
this.PIN_INDEX = this.options.length - 1;
}
// Reaction
if (!this.isRoomReadOnly() || this.canReactWhenReadOnly()) {
- this.options.push('Add Reaction');
+ this.options.push(I18n.t('Add_Reaction'));
this.REACTION_INDEX = this.options.length - 1;
}
// Delete
if (this.allowDelete(nextProps)) {
- this.options.push('Delete');
+ this.options.push(I18n.t('Delete'));
this.DELETE_INDEX = this.options.length - 1;
}
setTimeout(() => {
@@ -141,7 +142,7 @@ export default class MessageActions extends React.Component {
if (this.state.copyPermalink) {
this.setState({ copyPermalink: false });
await Clipboard.setString(nextProps.permalink);
- showToast('Permalink copied to clipboard!');
+ showToast(I18n.t('Permalink_copied_to_clipboard'));
this.props.permalinkClear();
// quote
} else if (this.state.quote) {
@@ -234,15 +235,15 @@ export default class MessageActions extends React.Component {
handleDelete() {
Alert.alert(
- 'Are you sure?',
- 'You will not be able to recover this message!',
+ I18n.t('Are_you_sure_question_mark'),
+ I18n.t('You_will_not_be_able_to_recover_this_message'),
[
{
- text: 'Cancel',
+ text: I18n.t('Cancel'),
style: 'cancel'
},
{
- text: 'Yes, delete it!',
+ text: I18n.t('Yes_action_it', { action: 'delete' }),
style: 'destructive',
onPress: () => this.props.deleteRequest(this.props.actionMessage)
}
@@ -258,7 +259,7 @@ export default class MessageActions extends React.Component {
handleCopy = async() => {
await Clipboard.setString(this.props.actionMessage.msg);
- showToast('Copied to clipboard!');
+ showToast(I18n.t('Copied_to_clipboard'));
}
handleShare = async() => {
@@ -336,7 +337,7 @@ export default class MessageActions extends React.Component {
return (
this.ActionSheet = o}
- title='Messages actions'
+ title={I18n.t('Message_actions')}
testID='message-actions'
options={this.options}
cancelButtonIndex={this.CANCEL_INDEX}
diff --git a/app/containers/MessageBox/Recording.js b/app/containers/MessageBox/Recording.js
index 713564a19..5396fb671 100644
--- a/app/containers/MessageBox/Recording.js
+++ b/app/containers/MessageBox/Recording.js
@@ -4,6 +4,7 @@ import { View, SafeAreaView, Platform, PermissionsAndroid, Text } from 'react-na
import { AudioRecorder, AudioUtils } from 'react-native-audio';
import Icon from 'react-native-vector-icons/MaterialIcons';
import styles from './styles';
+import I18n from '../../i18n';
export const _formatTime = function(seconds) {
let minutes = Math.floor(seconds / 60);
@@ -24,8 +25,8 @@ export default class extends React.PureComponent {
}
const rationale = {
- title: 'Microphone Permission',
- message: 'Rocket Chat needs access to your microphone so you can send audio message.'
+ title: I18n.t('Microphone_Permission'),
+ message: I18n.t('Microphone_Permission_Message')
};
const result = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.RECORD_AUDIO, rationale);
@@ -118,7 +119,7 @@ export default class extends React.PureComponent {
style={[styles.actionButtons, { color: 'red' }]}
name='clear'
key='clear'
- accessibilityLabel='Cancel recording'
+ accessibilityLabel={I18n.t('Cancel_recording')}
accessibilityTraits='button'
onPress={this.cancelAudioMessage}
/>
@@ -127,7 +128,7 @@ export default class extends React.PureComponent {
style={[styles.actionButtons, { color: 'green' }]}
name='check'
key='check'
- accessibilityLabel='Finish recording'
+ accessibilityLabel={I18n.t('Finish_recording')}
accessibilityTraits='button'
onPress={this.finishAudioMessage}
/>
diff --git a/app/containers/MessageBox/index.js b/app/containers/MessageBox/index.js
index 113ce2dbe..fea1c26b6 100644
--- a/app/containers/MessageBox/index.js
+++ b/app/containers/MessageBox/index.js
@@ -19,6 +19,7 @@ import { emojis } from '../../emojis';
import Recording from './Recording';
import './EmojiKeyboard';
import log from '../../utils/log';
+import I18n from '../../i18n';
const MENTIONS_TRACKING_TYPE_USERS = '@';
const MENTIONS_TRACKING_TYPE_EMOJIS = ':';
@@ -107,7 +108,7 @@ export default class MessageBox extends React.PureComponent {
return ( this.editCancel()}
testID='messagebox-cancel-editing'
@@ -116,14 +117,14 @@ export default class MessageBox extends React.PureComponent {
return !this.state.showEmojiKeyboard ? ( this.openEmoji()}
- accessibilityLabel='Open emoji selector'
+ accessibilityLabel={I18n.t('Open_emoji_selector')}
accessibilityTraits='button'
name='mood'
testID='messagebox-open-emoji'
/>) : ( this.closeEmoji()}
style={styles.actionButtons}
- accessibilityLabel='Close emoji selector'
+ accessibilityLabel={I18n.t('Close_emoji_selector')}
accessibilityTraits='button'
name='keyboard'
testID='messagebox-close-emoji'
@@ -137,7 +138,7 @@ export default class MessageBox extends React.PureComponent {
style={[styles.actionButtons, { color: '#1D74F5' }]}
name='send'
key='sendIcon'
- accessibilityLabel='Send message'
+ accessibilityLabel={I18n.t('Send message')}
accessibilityTraits='button'
onPress={() => this.submit(this.state.text)}
testID='messagebox-send-message'
@@ -148,7 +149,7 @@ export default class MessageBox extends React.PureComponent {
style={[styles.actionButtons, { color: '#1D74F5', paddingHorizontal: 10 }]}
name='mic'
key='micIcon'
- accessibilityLabel='Send audio message'
+ accessibilityLabel={I18n.t('Send audio message')}
accessibilityTraits='button'
onPress={() => this.recordAudioMessage()}
testID='messagebox-send-audio'
@@ -157,7 +158,7 @@ export default class MessageBox extends React.PureComponent {
style={[styles.actionButtons, { color: '#2F343D', fontSize: 16 }]}
name='plus'
key='fileIcon'
- accessibilityLabel='Message actions'
+ accessibilityLabel={I18n.t('Message actions')}
accessibilityTraits='button'
onPress={() => this.addFile()}
testID='messagebox-actions'
@@ -169,18 +170,13 @@ export default class MessageBox extends React.PureComponent {
const options = {
maxHeight: 1960,
maxWidth: 1960,
- quality: 0.8,
- customButtons: [{
- name: 'import', title: 'Import File From'
- }]
+ quality: 0.8
};
ImagePicker.showImagePicker(options, (response) => {
if (response.didCancel) {
console.warn('User cancelled image picker');
} else if (response.error) {
log('ImagePicker Error', response.error);
- } else if (response.customButton) {
- console.warn('User tapped custom button: ', response.customButton);
} else {
const fileInfo = {
name: response.fileName,
@@ -250,10 +246,10 @@ export default class MessageBox extends React.PureComponent {
_getFixedMentions(keyword) {
if ('all'.indexOf(keyword) !== -1) {
- this.users = [{ _id: -1, username: 'all', desc: 'all' }, ...this.users];
+ this.users = [{ _id: -1, username: 'all' }, ...this.users];
}
if ('here'.indexOf(keyword) !== -1) {
- this.users = [{ _id: -2, username: 'here', desc: 'active users' }, ...this.users];
+ this.users = [{ _id: -2, username: 'here' }, ...this.users];
}
}
@@ -419,7 +415,7 @@ export default class MessageBox extends React.PureComponent {
onPress={() => this._onPressMention(item)}
>
{item.username}
- Notify {item.desc} in this room
+ {item.username === 'here' ? I18n.t('Notify_active_in_this_room') : I18n.t('Notify_all_in_this_room')}
)
renderMentionEmoji = (item) => {
@@ -507,7 +503,7 @@ export default class MessageBox extends React.PureComponent {
returnKeyType='default'
keyboardType='twitter'
blurOnSubmit={false}
- placeholder='New Message'
+ placeholder={I18n.t('New_Message')}
onChangeText={text => this.onChangeText(text)}
value={this.state.text}
underlineColorAndroid='transparent'
diff --git a/app/containers/MessageErrorActions.js b/app/containers/MessageErrorActions.js
index a65c016d7..4a8a9eeb5 100644
--- a/app/containers/MessageErrorActions.js
+++ b/app/containers/MessageErrorActions.js
@@ -7,6 +7,7 @@ import { errorActionsHide } from '../actions/messages';
import RocketChat from '../lib/rocketchat';
import database from '../lib/realm';
import protectedFunction from '../lib/methods/helpers/protectedFunction';
+import I18n from '../i18n';
@connect(
state => ({
@@ -27,7 +28,7 @@ export default class MessageErrorActions extends React.Component {
constructor(props) {
super(props);
this.handleActionPress = this.handleActionPress.bind(this);
- this.options = ['Cancel', 'Delete', 'Resend'];
+ this.options = [I18n.t('Cancel'), I18n.t('Delete'), I18n.t('Resend')];
this.CANCEL_INDEX = 0;
this.DELETE_INDEX = 1;
this.RESEND_INDEX = 2;
@@ -66,7 +67,7 @@ export default class MessageErrorActions extends React.Component {
return (
this.ActionSheet = o}
- title='Messages actions'
+ title={I18n.t('Message_actions')}
options={this.options}
cancelButtonIndex={this.CANCEL_INDEX}
destructiveButtonIndex={this.DELETE_INDEX}
diff --git a/app/containers/Sidebar.js b/app/containers/Sidebar.js
index df34b7ff1..655338416 100644
--- a/app/containers/Sidebar.js
+++ b/app/containers/Sidebar.js
@@ -7,6 +7,7 @@ import { DrawerActions } from 'react-navigation';
import database from '../lib/realm';
import { setServer } from '../actions/server';
import { logout } from '../actions/login';
+import I18n from '../i18n';
const styles = StyleSheet.create({
scrollView: {
@@ -115,9 +116,7 @@ export default class Sidebar extends Component {
testID='sidebar-logout'
>
-
- Logout
-
+ {I18n.t('Logout')}
-
- Add Server
-
+ {I18n.t('Add_Server')}
diff --git a/app/containers/Typing.js b/app/containers/Typing.js
index eb667093b..162d462f0 100644
--- a/app/containers/Typing.js
+++ b/app/containers/Typing.js
@@ -2,6 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { View, StyleSheet, Text, Keyboard, LayoutAnimation } from 'react-native';
import { connect } from 'react-redux';
+import I18n from '../i18n';
const styles = StyleSheet.create({
typing: {
@@ -31,7 +32,7 @@ export default class Typing extends React.Component {
}
get usersTyping() {
const users = this.props.usersTyping.filter(_username => this.props.username !== _username);
- return users.length ? `${ users.join(' ,') } ${ users.length > 1 ? 'are' : 'is' } typing` : '';
+ return users.length ? `${ users.join(' ,') } ${ users.length > 1 ? I18n.t('are_typing') : I18n.t('is_typing') }` : '';
}
render() {
const { usersTyping } = this;
diff --git a/app/containers/message/ReactionsModal.js b/app/containers/message/ReactionsModal.js
index 8f3f5620f..cde604260 100644
--- a/app/containers/message/ReactionsModal.js
+++ b/app/containers/message/ReactionsModal.js
@@ -5,6 +5,7 @@ import Modal from 'react-native-modal';
import Icon from 'react-native-vector-icons/MaterialIcons';
import { connect } from 'react-redux';
import Emoji from './Emoji';
+import I18n from '../../i18n';
const styles = StyleSheet.create({
titleContainer: {
@@ -68,11 +69,11 @@ export default class ReactionsModal extends React.PureComponent {
renderItem = (item) => {
const count = item.usernames.length;
let usernames = item.usernames.slice(0, 3)
- .map(username => (username.value === this.props.user.username ? 'you' : username.value)).join(', ');
+ .map(username => (username.value === this.props.user.username ? I18n.t('you') : username.value)).join(', ');
if (count > 3) {
- usernames = `${ usernames } and more ${ count - 3 }`;
+ usernames = `${ usernames } ${ I18n.t('and_more') } ${ count - 3 }`;
} else {
- usernames = usernames.replace(/,(?=[^,]*$)/, ' and');
+ usernames = usernames.replace(/,(?=[^,]*$)/, ` ${ I18n.t('and') }`);
}
return (
@@ -86,7 +87,7 @@ export default class ReactionsModal extends React.PureComponent {
- {count === 1 ? '1 person' : `${ count } people`} reacted
+ {count === 1 ? I18n.t('1_person_reacted') : I18n.t('N_people_reacted', { n: count })}
{ usernames }
@@ -113,7 +114,7 @@ export default class ReactionsModal extends React.PureComponent {
size={20}
onPress={onClose}
/>
- Reactions
+ {I18n.t('Reactions')}
diff --git a/app/containers/message/index.js b/app/containers/message/index.js
index 3aac53d5f..54c31aa49 100644
--- a/app/containers/message/index.js
+++ b/app/containers/message/index.js
@@ -21,6 +21,7 @@ import styles from './styles';
import { actionsShow, errorActionsShow, toggleReactionPicker, replyBroadcast } from '../../actions/messages';
import messagesStatus from '../../constants/messagesStatus';
import Touch from '../../utils/touch';
+import I18n from '../../i18n';
const SYSTEM_MESSAGES = [
'r',
@@ -44,35 +45,35 @@ const getInfoMessage = ({
t, role, msg, u
}) => {
if (t === 'rm') {
- return 'Message removed';
+ return I18n.t('Message_removed');
} else if (t === 'uj') {
- return 'Has joined the channel.';
+ return I18n.t('Has_joined_the_channel');
} else if (t === 'r') {
- return `Room name changed to: ${ msg } by ${ u.username }`;
+ return I18n.t('Room_name_changed', { name: msg, userBy: u.username });
} else if (t === 'message_pinned') {
- return 'Message pinned';
+ return I18n.t('Message_pinned');
} else if (t === 'ul') {
- return 'Has left the channel.';
+ return I18n.t('Has_left_the_channel');
} else if (t === 'ru') {
- return `User ${ msg } removed by ${ u.username }`;
+ return I18n.t('User_removed_by', { userRemoved: msg, userBy: u.username });
} else if (t === 'au') {
- return `User ${ msg } added by ${ u.username }`;
+ return I18n.t('User_added_by', { userAdded: msg, userBy: u.username });
} else if (t === 'user-muted') {
- return `User ${ msg } muted by ${ u.username }`;
+ return I18n.t('User_muted_by', { userMuted: msg, userBy: u.username });
} else if (t === 'user-unmuted') {
- return `User ${ msg } unmuted by ${ u.username }`;
+ return I18n.t('User_unmuted_by', { userUnmuted: msg, userBy: u.username });
} else if (t === 'subscription-role-added') {
return `${ msg } was set ${ role } by ${ u.username }`;
} else if (t === 'subscription-role-removed') {
return `${ msg } is no longer ${ role } by ${ u.username }`;
} else if (t === 'room_changed_description') {
- return `Room description changed to: ${ msg } by ${ u.username }`;
+ return I18n.t('Room_changed_description', { description: msg, userBy: u.username });
} else if (t === 'room_changed_announcement') {
- return `Room announcement changed to: ${ msg } by ${ u.username }`;
+ return I18n.t('Room_changed_announcement', { announcement: msg, userBy: u.username });
} else if (t === 'room_changed_topic') {
- return `Room topic changed to: ${ msg } by ${ u.username }`;
+ return I18n.t('Room_changed_topic', { topic: msg, userBy: u.username });
} else if (t === 'room_changed_privacy') {
- return `Room type changed to: ${ msg } by ${ u.username }`;
+ return I18n.t('Room_changed_privacy', { type: msg, userBy: u.username });
}
return '';
};
@@ -334,7 +335,7 @@ export default class Message extends React.Component {
} = this.props;
const username = item.alias || item.u.username;
const isEditing = message._id === item._id && editing;
- const accessibilityLabel = `Message from ${ username } at ${ moment(item.ts).format(this.timeFormat) }, ${ this.props.item.msg }`;
+ const accessibilityLabel = I18n.t('Message_accessibility', { user: username, time: moment(item.ts).format(this.timeFormat), message: this.props.item.msg });
return (
{
const db = database.databases.serversDB.objects('servers');
@@ -24,12 +25,12 @@ const ServerStack = createStackNavigator({
screen: ListServerView,
navigationOptions({ navigation }) {
return {
- title: 'Servers',
+ title: I18n.t('Servers'),
headerRight: (
navigation.navigate({ key: 'AddServer', routeName: 'AddServer' })}
style={{ width: 50, alignItems: 'center' }}
- accessibilityLabel='Add server'
+ accessibilityLabel={I18n.t('Add_Server')}
accessibilityTraits='button'
>
@@ -65,7 +66,7 @@ const LoginStack = createStackNavigator({
ForgotPassword: {
screen: ForgotPasswordView,
navigationOptions: {
- title: 'Forgot my password',
+ title: I18n.t('Forgot_my_password'),
headerTintColor: '#292E35'
}
}
@@ -83,14 +84,14 @@ const RegisterStack = createStackNavigator({
TermsService: {
screen: TermsServiceView,
navigationOptions: {
- title: 'Terms of service',
+ title: I18n.t('Terms_of_Service'),
headerTintColor: '#292E35'
}
},
PrivacyPolicy: {
screen: PrivacyPolicyView,
navigationOptions: {
- title: 'Privacy policy',
+ title: I18n.t('Privacy_Policy'),
headerTintColor: '#292E35'
}
}
diff --git a/app/i18n/index.js b/app/i18n/index.js
new file mode 100644
index 000000000..b130a36bd
--- /dev/null
+++ b/app/i18n/index.js
@@ -0,0 +1,10 @@
+import I18n from 'react-native-i18n';
+import en from './locales/en';
+
+I18n.fallbacks = true;
+
+I18n.translations = {
+ en
+};
+
+export default I18n;
diff --git a/app/i18n/locales/en.js b/app/i18n/locales/en.js
new file mode 100644
index 000000000..e2cf96ecb
--- /dev/null
+++ b/app/i18n/locales/en.js
@@ -0,0 +1,216 @@
+export default {
+ '1_online_member': '1 online member',
+ '1_person_reacted': '1 person reacted',
+ Actions: 'Actions',
+ Add_Reaction: 'Add Reaction',
+ Add_Server: 'Add Server',
+ Add_user: 'Add user',
+ Alert: 'Alert',
+ alert: 'alert',
+ alerts: 'alerts',
+ All_users_in_the_channel_can_write_new_messages: 'All users in the channel can write new messages',
+ All: 'All',
+ Allow_Reactions: 'Allow Reactions',
+ and_more: 'and more',
+ and: 'and',
+ announcement: 'announcement',
+ Announcement: 'Announcement',
+ ARCHIVE: 'ARCHIVE',
+ archive: 'archive',
+ are_typing: 'are typing',
+ Are_you_sure_question_mark: 'Are you sure?',
+ Are_you_sure_you_want_to_leave_the_room: 'Are you sure you want to leave the room {{room}}?',
+ Authenticating: 'Authenticating',
+ Away: 'Away',
+ Block_user: 'Block user',
+ Broadcast_channel_Description: 'Only authorized users can write new messages, but the other users will be able to reply',
+ Broadcast_Channel: 'Broadcast Channel',
+ Busy: 'Busy',
+ By_proceeding_you_are_agreeing: 'By proceeding you are agreeing to our',
+ Cancel_editing: 'Cancel editing',
+ Cancel_recording: 'Cancel recording',
+ Cancel: 'Cancel',
+ Channel_Name: 'Channel Name',
+ Close_emoji_selector: 'Close emoji selector',
+ Code: 'Code',
+ Colaborative: 'Colaborative',
+ Connect: 'Connect',
+ Connected_to: 'Connected to',
+ Connecting: 'Connecting',
+ Copied_to_clipboard: 'Copied to clipboard!',
+ Copy_Message: 'Copy Message',
+ Copy_Permalink: 'Copy Permalink',
+ Create_account: 'Create account',
+ Create_Channel: 'Create Channel',
+ Create: 'Create',
+ Delete_Room_Warning: 'Deleting a room will delete all messages posted within the room. This cannot be undone.',
+ delete: 'delete',
+ Delete: 'Delete',
+ DELETE: 'DELETE',
+ description: 'description',
+ Description: 'Description',
+ Disable_notifications: 'Disable notifications',
+ Do_you_really_want_to_key_this_room_question_mark: 'Do you really want to {{key}} this room?',
+ edit: 'edit',
+ Edit: 'Edit',
+ Email_or_password_field_is_empty: 'Email or password field is empty',
+ Email: 'Email',
+ Enable_notifications: 'Enable notifications',
+ Everyone_can_access_this_channel: 'Everyone can access this channel',
+ Files: 'Files',
+ Finish_recording: 'Finish recording',
+ Forgot_my_password: 'Forgot my password',
+ Forgot_password_If_this_email_is_registered: 'If this email is registered, we\'ll send instructions on how to reset your password. If you do not receive an email shortly, please come back and try again.',
+ Forgot_password: 'Forgot password',
+ Has_joined_the_channel: 'Has joined the channel',
+ Has_left_the_channel: 'Has left the channel',
+ I_have_an_account: 'I have an account',
+ Invisible: 'Invisible',
+ is_a_valid_RocketChat_instance: 'is a valid Rocket.Chat instance',
+ is_not_a_valid_RocketChat_instance: 'is not a valid Rocket.Chat instance',
+ is_typing: 'is typing',
+ Just_invited_people_can_access_this_channel: 'Just invited people can access this channel',
+ last_message: 'last message',
+ Leave_channel: 'Leave channel',
+ leave: 'leave',
+ Loading_messages_ellipsis: 'Loading messages...',
+ Login: 'Login',
+ Logout: 'Logout',
+ Members: 'Members',
+ Mentioned_Messages: 'Mentioned Messages',
+ mentioned: 'mentioned',
+ Mentions: 'Mentions',
+ Message_accessibility: 'Message from {{user}} at {{time}}: {{message}}',
+ Message_actions: 'Message actions',
+ Message_pinned: 'Message pinned',
+ Message_removed: 'Message removed',
+ Microphone_Permission_Message: 'Rocket Chat needs access to your microphone so you can send audio message.',
+ Microphone_Permission: 'Microphone Permission',
+ Mute: 'Mute',
+ muted: 'muted',
+ My_servers: 'My servers',
+ N_online_members: '{{n}} online members',
+ N_person_reacted: '{{n}} people reacted',
+ Name: 'Name',
+ New_in_RocketChat_question_mark: 'New in Rocket.Chat?',
+ New_Message: 'New Message',
+ New_Server: 'New Server',
+ No_files: 'No files',
+ No_mentioned_messages: 'No mentioned messages',
+ No_pinned_messages: 'No pinned messages',
+ No_snippeted_messages: 'No snippeted messages',
+ No_starred_messages: 'No starred messages',
+ No_announcement_provided: 'No announcement provided.',
+ No_description_provided: 'No description provided.',
+ No_topic_provided: 'No topic provided.',
+ No_Message: 'No Message',
+ No_Reactions: 'No Reactions',
+ Not_logged: 'Not logged',
+ Nothing_to_save: 'Nothing to save!',
+ Notify_active_in_this_room: 'Notify active users in this room',
+ Notify_all_in_this_room: 'Notify all in this room',
+ Offline: 'Offline',
+ Online: 'Online',
+ Only_authorized_users_can_write_new_messages: 'Only authorized users can write new messages',
+ Open_emoji_selector: 'Open emoji selector',
+ Or_continue_using_social_accounts: 'Or continue using social accounts',
+ Password: 'Password',
+ Permalink_copied_to_clipboard: 'Permalink copied to clipboard!',
+ Pin: 'Pin',
+ Pinned_Messages: 'Pinned Messages',
+ pinned: 'pinned',
+ Pinned: 'Pinned',
+ Privacy_Policy: ' Privacy Policy',
+ Private_Channel: 'Private Channel',
+ Private: 'Private',
+ Public_Channel: 'Public Channel',
+ Public: 'Public',
+ Quote: 'Quote',
+ Reactions_are_disabled: 'Reactions are disabled',
+ Reactions_are_enabled: 'Reactions are enabled',
+ Reactions: 'Reactions',
+ Read_Only_Channel: 'Read Only Channel',
+ Read_Only: 'Read Only',
+ Register: 'Register',
+ Repeat_Password: 'Repeat Password',
+ Reply: 'Reply',
+ Resend: 'Resend',
+ Reset_password: 'Reset password',
+ RESET: 'RESET',
+ Roles: 'Roles',
+ Room_actions: 'Room actions',
+ Room_changed_announcement: 'Room announcement changed to: {{announcement}} by {{userBy}}',
+ Room_changed_description: 'Room description changed to: {{description}} by {{userBy}}',
+ Room_changed_privacy: 'Room type changed to: {{type}} by {{userBy}}',
+ Room_changed_topic: 'Room topic changed to: {{topic}} by {{userBy}}',
+ Room_Files: 'Room Files',
+ Room_Info_Edit: 'Room Info Edit',
+ Room_Info: 'Room Info',
+ Room_Members: 'Room Members',
+ Room_name_changed: 'Room name changed to: {{name}} by {{userBy}}',
+ SAVE: 'SAVE',
+ Search_Messages: 'Search Messages',
+ Search: 'Search',
+ Select_Users: 'Select Users',
+ Send_audio_message: 'Send audio message',
+ Send_message: 'Send message',
+ Servers: 'Servers',
+ Settings_succesfully_changed: 'Settings succesfully changed!',
+ Share_Message: 'Share Message',
+ Share: 'Share',
+ Sign_in_your_server: 'Sign in your server',
+ Sign_Up: 'Sign Up',
+ Snippet_Messages: 'Snippet Messages',
+ snippeted: 'snippeted',
+ Snippets: 'Snippets',
+ Some_field_is_invalid_or_empty: 'Some field is invalid or empty',
+ Star_room: 'Star room',
+ Star: 'Star',
+ Starred_Messages: 'Starred Messages',
+ starred: 'starred',
+ Starred: 'Starred',
+ Start_of_conversation: 'Start of conversation',
+ Submit: 'Submit',
+ tap_to_change_status: 'tap to change status',
+ Tap_to_view_servers_list: 'Tap to view servers list',
+ Terms_of_Service: ' Terms of Service ',
+ There_was_an_error_while_saving_settings: 'There was an error while saving settings!',
+ This_room_is_blocked: 'This room is blocked',
+ This_room_is_read_only: 'This room is read only',
+ Timezone: 'Timezone',
+ topic: 'topic',
+ Topic: 'Topic',
+ Type_the_channel_name_here: 'Type the channel name here',
+ unarchive: 'unarchive',
+ UNARCHIVE: 'UNARCHIVE',
+ Unblock_user: 'Unblock user',
+ Unmute: 'Unmute',
+ unmuted: 'unmuted',
+ Unpin: 'Unpin',
+ unread_messages: 'unread messages',
+ Unstar: 'Unstar',
+ User_added_by: 'User {{userAdded}} added by {{userBy}}',
+ User_has_been_key: 'User has been {{key}}!',
+ User_is_no_longer_role_by_: '{{user}} is no longer {{role}} by {{userBy}}',
+ User_muted_by: 'User {{userMuted}} muted by {{userBy}}',
+ User_removed_by: 'User {{userRemoved}} removed by {{userBy}}',
+ User_unmuted_by: 'User {{userUnmuted}} unmuted by {{userBy}}',
+ User_was_set_role_by_: '{{user}} was set {{role}} by {{userBy}}',
+ Username_is_empty: 'Username is empty',
+ Username: 'Username',
+ Validating: 'Validating',
+ Video_call: 'Video call',
+ Voice_call: 'Voice call',
+ Welcome_title_pt_1: 'Prepare to take off with',
+ Welcome_title_pt_2: 'the ultimate chat platform',
+ Yes_action_it: 'Yes, {{action}} it!',
+ Yesterday: 'Yesterday',
+ You_are_in_preview_mode: 'You are in preview mode',
+ You_are_offline: 'You are offline',
+ You_can_search_using_RegExp_eg: 'You can search using RegExp. e.g. `/^text$/i`',
+ You_colon: 'You: ',
+ you_were_mentioned: 'you were mentioned',
+ You_will_not_be_able_to_recover_this_message: 'You will not be able to recover this message!',
+ you: 'you',
+ Your_server: 'Your server'
+};
diff --git a/app/lib/methods/helpers/mergeSubscriptionsRooms.js b/app/lib/methods/helpers/mergeSubscriptionsRooms.js
index e5d4340d4..371ddaf3d 100644
--- a/app/lib/methods/helpers/mergeSubscriptionsRooms.js
+++ b/app/lib/methods/helpers/mergeSubscriptionsRooms.js
@@ -2,7 +2,6 @@ import normalizeMessage from './normalizeMessage';
// TODO: delete and update
export const merge = (subscription, room) => {
- subscription.muted = [];
if (room) {
if (room.rid) {
subscription.rid = room.rid;
@@ -19,7 +18,9 @@ export const merge = (subscription, room) => {
subscription.broadcast = room.broadcast;
if (room.muted && room.muted.length) {
- subscription.muted = room.muted.filter(user => user).map(user => ({ value: user }));
+ subscription.muted = room.muted.map(user => ({ value: user }));
+ } else {
+ subscription.muted = [];
}
}
if (subscription.roles && subscription.roles.length) {
diff --git a/app/presentation/RoomItem.js b/app/presentation/RoomItem.js
index f2401d698..243d4e3be 100644
--- a/app/presentation/RoomItem.js
+++ b/app/presentation/RoomItem.js
@@ -4,13 +4,13 @@ import PropTypes from 'prop-types';
import { View, Text, StyleSheet, ViewPropTypes } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import { connect } from 'react-redux';
-// import SimpleMarkdown from 'simple-markdown';
import Avatar from '../containers/Avatar';
import Status from '../containers/status';
import Touch from '../utils/touch/index'; //eslint-disable-line
import Markdown from '../containers/message/Markdown';
import RoomTypeIcon from '../containers/RoomTypeIcon';
+import I18n from '../i18n';
const styles = StyleSheet.create({
container: {
@@ -98,36 +98,6 @@ const styles = StyleSheet.create({
marginTop: 3
}
});
-// const markdownStyle = { block: { marginBottom: 0, flexWrap: 'wrap', flexDirection: 'row' } };
-
-// const parseInline = (parse, content, state) => {
-// const isCurrentlyInline = state.inline || false;
-// state.inline = true;
-// const result = parse(content, state);
-// state.inline = isCurrentlyInline;
-// return result;
-// };
-// const parseCaptureInline = (capture, parse, state) => ({ content: parseInline(parse, capture[1], state) });
-// const customRules = {
-// strong: {
-// order: -4,
-// match: SimpleMarkdown.inlineRegex(/^\*\*([\s\S]+?)\*\*(?!\*)/),
-// parse: parseCaptureInline,
-// react: (node, output, state) => ({
-// type: 'strong',
-// key: state.key,
-// props: {
-// children: output(node.content, state)
-// }
-// })
-// },
-// text: {
-// order: -3,
-// match: SimpleMarkdown.inlineRegex(/^[\s\S]+?(?=[^0-9A-Za-z\s\u00c0-\uffff]|\n\n| {2,}\n|\w+:\S|$)/),
-// parse: capture => ({ content: capture[0] }),
-// react: node => node.content
-// }
-// };
const renderNumber = (unread, userMentions) => {
if (!unread || unread <= 0) {
@@ -207,13 +177,13 @@ export default class RoomItem extends React.Component {
return '';
}
if (!lastMessage) {
- return 'No Message';
+ return I18n.t('No_Message');
}
let prefix = '';
if (lastMessage.u.username === this.props.user.username) {
- prefix = 'You: ';
+ prefix = I18n.t('You_colon');
} else if (type !== 'd') {
prefix = `${ lastMessage.u.username }: `;
}
@@ -234,7 +204,7 @@ export default class RoomItem extends React.Component {
}
formatDate = date => moment(date).calendar(null, {
- lastDay: '[Yesterday]',
+ lastDay: `[${ I18n.t('Yesterday') }]`,
sameDay: 'h:mm A',
lastWeek: 'dddd',
sameElse: 'MMM D'
@@ -249,17 +219,17 @@ export default class RoomItem extends React.Component {
let accessibilityLabel = name;
if (unread === 1) {
- accessibilityLabel += `, ${ unread } alert`;
+ accessibilityLabel += `, ${ unread } ${ I18n.t('alert') }`;
} else if (unread > 1) {
- accessibilityLabel += `, ${ unread } alerts`;
+ accessibilityLabel += `, ${ unread } ${ I18n.t('alerts') }`;
}
if (userMentions > 0) {
- accessibilityLabel += ', you were mentioned';
+ accessibilityLabel += `, ${ I18n.t('you_were_mentioned') }`;
}
if (date) {
- accessibilityLabel += `, last message ${ date }`;
+ accessibilityLabel += `, ${ I18n.t('last_message') } ${ date }`;
}
return (
diff --git a/app/sagas/messages.js b/app/sagas/messages.js
index 0585e833b..0dff63c69 100644
--- a/app/sagas/messages.js
+++ b/app/sagas/messages.js
@@ -98,7 +98,7 @@ const handleReplyBroadcast = function* handleReplyBroadcast({ message }) {
}
yield delay(100);
const server = yield select(state => state.server.server);
- const msg = `[ ](${ server }/direct/${ username }?msg=${ message._id })`;
+ const msg = `[ ](${ server }/direct/${ username }?msg=${ message._id }) `;
yield put(setInput({ msg }));
} catch (e) {
log('handleReplyBroadcast', e);
diff --git a/app/views/CreateChannelView.js b/app/views/CreateChannelView.js
index ed221fe3e..bad0fcfad 100644
--- a/app/views/CreateChannelView.js
+++ b/app/views/CreateChannelView.js
@@ -11,6 +11,7 @@ import styles from './Styles';
import KeyboardView from '../presentation/KeyboardView';
import scrollPersistTaps from '../utils/scrollPersistTaps';
import Button from '../containers/Button';
+import I18n from '../i18n';
@connect(
state => ({
@@ -22,9 +23,6 @@ import Button from '../containers/Button';
})
)
export default class CreateChannelView extends LoggedView {
- static navigationOptions = () => ({
- title: 'Create a New Channel'
- });
static propTypes = {
create: PropTypes.func.isRequired,
createChannel: PropTypes.object.isRequired,
@@ -99,8 +97,8 @@ export default class CreateChannelView extends LoggedView {
return this.renderSwitch({
id: 'type',
value: type,
- label: type ? 'Private Channel' : 'Public Channel',
- description: type ? 'Just invited people can access this channel' : 'Everyone can access this channel',
+ label: type ? I18n.t('Private_Channel') : I18n.t('Public_Channel'),
+ description: type ? I18n.t('Just_invited_people_can_access_this_channel') : I18n.t('Everyone_can_access_this_channel'),
onValueChange: value => this.setState({ type: value })
});
}
@@ -110,8 +108,8 @@ export default class CreateChannelView extends LoggedView {
return this.renderSwitch({
id: 'readonly',
value: readOnly,
- label: 'Read Only Channel',
- description: readOnly ? 'Only authorized users can write new messages' : 'All users in the channel can write new messages',
+ label: I18n.t('Read_Only_Channel'),
+ description: readOnly ? I18n.t('Only_authorized_users_can_write_new_messages') : I18n.t('All_users_in_the_channel_can_write_new_messages'),
onValueChange: value => this.setState({ readOnly: value }),
disabled: broadcast
});
@@ -122,8 +120,8 @@ export default class CreateChannelView extends LoggedView {
return this.renderSwitch({
id: 'broadcast',
value: broadcast,
- label: 'Broadcast Channel',
- description: 'Only authorized users can write new messages, but the other users will be able to reply',
+ label: I18n.t('Broadcast_Channel'),
+ description: I18n.t('Broadcast_channel_Description'),
onValueChange: (value) => {
this.setState({
broadcast: value,
@@ -142,10 +140,10 @@ export default class CreateChannelView extends LoggedView {
this.setState({ channelName })}
- placeholder='Type the channel name here'
+ placeholder={I18n.t('Type_the_channel_name_here')}
returnKeyType='done'
autoFocus
testID='create-channel-name'
@@ -156,7 +154,7 @@ export default class CreateChannelView extends LoggedView {
{this.renderBroadcast()}
- RESET
+ {I18n.t('RESET')}
- { room.archived ? 'UNARCHIVE' : 'ARCHIVE' }
+ { room.archived ? I18n.t('UNARCHIVE') : I18n.t('ARCHIVE') }
@@ -389,7 +390,7 @@ export default class RoomInfoEditView extends LoggedView {
disabled={!this.hasDeletePermission()}
testID='room-info-edit-view-delete'
>
- DELETE
+ {I18n.t('DELETE')}
diff --git a/app/views/RoomInfoView/index.js b/app/views/RoomInfoView/index.js
index 369b4e3a1..68209a655 100644
--- a/app/views/RoomInfoView/index.js
+++ b/app/views/RoomInfoView/index.js
@@ -16,6 +16,7 @@ import Touch from '../../utils/touch';
import log from '../../utils/log';
import RoomTypeIcon from '../../containers/RoomTypeIcon';
+import I18n from '../../i18n';
const PERMISSION_EDIT_ROOM = 'edit-room';
@@ -56,7 +57,7 @@ export default class RoomInfoView extends LoggedView {
onPress={() => navigation.navigate({ key: 'RoomInfoEdit', routeName: 'RoomInfoEdit', params: { rid: navigation.state.params.rid } })}
underlayColor='#ffffff'
activeOpacity={0.5}
- accessibilityLabel='edit'
+ accessibilityLabel={I18n.t('edit')}
accessibilityTraits='button'
testID='room-info-view-edit-button'
>
@@ -132,14 +133,14 @@ export default class RoomInfoView extends LoggedView {
const [room] = this.rooms;
this.setState({ room });
}
- // TODO: translate
+
renderItem = (key, room) => (
- {camelize(key)}
+ {I18n.t(camelize(key))}
{ room[key] ? room[key] : `No ${ key } provided.` }
+ >{ room[key] ? room[key] : I18n.t(`No_${ key }_provided`) }
);
@@ -147,7 +148,7 @@ export default class RoomInfoView extends LoggedView {
renderRoles = () => (
this.state.roles.length > 0 &&
- Roles
+ {I18n.t('Roles')}
{this.state.roles.map(role => (
@@ -168,7 +169,7 @@ export default class RoomInfoView extends LoggedView {
// TODO: translate
return (
- Timezone
+ {I18n.t('Timezone')}
{moment().utcOffset(utcOffset).format(this.props.Message_TimeFormat)} (UTC { utcOffset })
);
@@ -189,11 +190,11 @@ export default class RoomInfoView extends LoggedView {
renderBroadcast = () => (
- Broadcast Channel
+ {I18n.t('Broadcast_Channel')}
Only authorized users can write new messages, but the other users will be able to reply
+ >{I18n.t('Broadcast_channel_Description')}
)
diff --git a/app/views/RoomMembersView/index.js b/app/views/RoomMembersView/index.js
index 8c6e9286e..68fc2d0cf 100644
--- a/app/views/RoomMembersView/index.js
+++ b/app/views/RoomMembersView/index.js
@@ -14,6 +14,7 @@ import { goRoom } from '../../containers/routes/NavigationService';
import database from '../../lib/realm';
import { showToast } from '../../utils/info';
import log from '../../utils/log';
+import I18n from '../../i18n';
@connect(state => ({
user: state.login.user,
@@ -26,7 +27,7 @@ export default class MentionedMessagesView extends LoggedView {
static navigationOptions = ({ navigation }) => {
const params = navigation.state.params || {};
- const label = params.allUsers ? 'All' : 'Online';
+ const label = params.allUsers ? I18n.t('All') : I18n.t('Online');
if (params.allUsers === undefined) {
return;
}
@@ -123,14 +124,14 @@ export default class MentionedMessagesView extends LoggedView {
if (!this.permissions['mute-user']) {
return;
}
- this.actionSheetOptions = ['Cancel'];
+ this.actionSheetOptions = [I18n.t('Cancel')];
const { muted } = this.state.room;
const userIsMuted = !!muted.find(m => m.value === user.username);
user.muted = userIsMuted;
if (userIsMuted) {
- this.actionSheetOptions.push('Unmute');
+ this.actionSheetOptions.push(I18n.t('Unmute'));
} else {
- this.actionSheetOptions.push('Mute');
+ this.actionSheetOptions.push(I18n.t('Mute'));
}
this.setState({ userLongPressed: user });
Vibration.vibrate(50);
@@ -141,7 +142,7 @@ export default class MentionedMessagesView extends LoggedView {
const { rid, userLongPressed } = this.state;
try {
await RocketChat.toggleMuteUserInRoom(rid, userLongPressed.username, !userLongPressed.muted);
- showToast(`User has been ${ userLongPressed.muted ? 'unmuted' : 'muted' }!`);
+ showToast(I18n.t('User_has_been_key', { key: userLongPressed.muted ? I18n.t('unmuted') : I18n.t('muted') }));
} catch (e) {
log('handleMute', e);
}
@@ -164,7 +165,7 @@ export default class MentionedMessagesView extends LoggedView {
style={styles.searchBox}
onChangeText={text => this.onSearchChangeText(text)}
returnKeyType='search'
- placeholder='Search'
+ placeholder={I18n.t('Search')}
clearButtonMode='while-editing'
blurOnSubmit
autoCorrect={false}
@@ -209,7 +210,7 @@ export default class MentionedMessagesView extends LoggedView {
this.ActionSheet = o}
- title='Actions'
+ title={I18n.t('Actions')}
options={this.actionSheetOptions}
cancelButtonIndex={this.CANCEL_INDEX}
onPress={this.handleActionPress}
diff --git a/app/views/RoomView/Header/index.js b/app/views/RoomView/Header/index.js
index 1301a8571..275150aad 100644
--- a/app/views/RoomView/Header/index.js
+++ b/app/views/RoomView/Header/index.js
@@ -11,28 +11,28 @@ import Avatar from '../../../containers/Avatar';
import { STATUS_COLORS } from '../../../constants/colors';
import styles from './styles';
import { closeRoom } from '../../../actions/room';
-
import log from '../../../utils/log';
import RoomTypeIcon from '../../../containers/RoomTypeIcon';
+import I18n from '../../../i18n';
const title = (offline, connecting, authenticating, logged) => {
if (offline) {
- return 'You are offline...';
+ return `${ I18n.t('You_are_offline') }...`;
}
if (connecting) {
- return 'Connecting...';
+ return `${ I18n.t('Connecting') }...`;
}
if (authenticating) {
- return 'Authenticating...';
+ return `${ I18n.t('Authenticating') }...`;
}
if (logged) {
return null;
}
- return 'Not logged...';
+ return `${ I18n.t('Not_logged') }...`;
};
@connect(state => ({
@@ -87,7 +87,7 @@ export default class RoomHeaderView extends React.PureComponent {
getUserStatusLabel() {
const status = this.getUserStatus();
- return status.charAt(0).toUpperCase() + status.slice(1);
+ return I18n.t(status.charAt(0).toUpperCase() + status.slice(1));
}
updateState = () => {
@@ -104,7 +104,7 @@ export default class RoomHeaderView extends React.PureComponent {
requestAnimationFrame(() => this.props.close());
}}
tintColor='#292E35'
- title='Back'
+ title={I18n.t('Back')}
titleStyle={{ display: 'none' }}
/>);
@@ -124,7 +124,7 @@ export default class RoomHeaderView extends React.PureComponent {
let t = '';
if (!title(offline, connecting, authenticating, logged) && loading) {
- t = 'Loading messages...';
+ t = I18n.t('Loading_messages_ellipsis');
} else if (this.isDirect()) {
t = this.getUserStatusLabel();
} else {
@@ -177,7 +177,7 @@ export default class RoomHeaderView extends React.PureComponent {
log('toggleFavorite', e);
}
}}
- accessibilityLabel='Star room'
+ accessibilityLabel={I18n.t('Star_room')}
accessibilityTraits='button'
testID='room-view-header-star'
>
@@ -191,7 +191,7 @@ export default class RoomHeaderView extends React.PureComponent {
this.props.navigation.navigate({ key: 'RoomActions', routeName: 'RoomActions', params: { rid: this.state.room.rid } })}
- accessibilityLabel='Room actions'
+ accessibilityLabel={I18n.t('Room_actions')}
accessibilityTraits='button'
testID='room-view-header-actions'
>
diff --git a/app/views/RoomView/UnreadSeparator.js b/app/views/RoomView/UnreadSeparator.js
index 7892b1664..00b4b9958 100644
--- a/app/views/RoomView/UnreadSeparator.js
+++ b/app/views/RoomView/UnreadSeparator.js
@@ -1,5 +1,6 @@
import React from 'react';
import { View, StyleSheet, Text, LayoutAnimation } from 'react-native';
+import I18n from '../../i18n';
const styles = StyleSheet.create({
firstUnread: {
@@ -30,7 +31,7 @@ export default class UnreadSeparator extends React.PureComponent {
return (
- unread messages
+ {I18n.t('unread_messages')}
);
}
diff --git a/app/views/RoomView/banner.js b/app/views/RoomView/banner.js
deleted file mode 100644
index bc5424ff0..000000000
--- a/app/views/RoomView/banner.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import { Text, View } from 'react-native';
-import { connect } from 'react-redux';
-import styles from './styles';
-
-@connect(state => ({
- loading: state.messages.isFetching
-}), null)
-export default class Banner extends React.PureComponent {
- static propTypes = {
- loading: PropTypes.bool
- };
-
- render() {
- return (this.props.loading ? (
-
- Loading new messages...
-
- ) : null);
- }
-}
diff --git a/app/views/RoomView/index.js b/app/views/RoomView/index.js
index 5a7d3c741..928da4fb1 100644
--- a/app/views/RoomView/index.js
+++ b/app/views/RoomView/index.js
@@ -2,12 +2,12 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Text, View, Button } from 'react-native';
import { connect } from 'react-redux';
-import { bindActionCreators } from 'redux';
+// import { bindActionCreators } from 'redux';
import equal from 'deep-equal';
import LoggedView from '../View';
import { List } from './ListView';
-import * as actions from '../../actions';
+// import * as actions from '../../actions';
import { openRoom, setLastOpen } from '../../actions/room';
import { editCancel, toggleReactionPicker, actionsShow } from '../../actions/messages';
import database from '../../lib/realm';
@@ -21,17 +21,18 @@ import RoomsHeader from './Header';
import ReactionPicker from './ReactionPicker';
import styles from './styles';
import log from '../../utils/log';
+import I18n from '../../i18n';
@connect(
state => ({
- Site_Url: state.settings.Site_Url || state.server ? state.server.server : '',
- Message_TimeFormat: state.settings.Message_TimeFormat,
+ // Site_Url: state.settings.Site_Url || state.server ? state.server.server : '',
+ // Message_TimeFormat: state.settings.Message_TimeFormat,
loading: state.messages.isFetching,
user: state.login.user,
actionMessage: state.messages.actionMessage
}),
dispatch => ({
- actions: bindActionCreators(actions, dispatch),
+ // actions: bindActionCreators(actions, dispatch),
openRoom: room => dispatch(openRoom(room)),
editCancel: () => dispatch(editCancel()),
setLastOpen: date => dispatch(setLastOpen(date)),
@@ -48,8 +49,8 @@ export default class RoomView extends LoggedView {
editCancel: PropTypes.func,
rid: PropTypes.string,
name: PropTypes.string,
- Site_Url: PropTypes.string,
- Message_TimeFormat: PropTypes.string,
+ // Site_Url: PropTypes.string,
+ // Message_TimeFormat: PropTypes.string,
loading: PropTypes.bool,
actionMessage: PropTypes.object,
toggleReactionPicker: PropTypes.func.isRequired,
@@ -191,7 +192,7 @@ export default class RoomView extends LoggedView {
if (!this.state.joined) {
return (
- You are in preview mode.
+ {I18n.t('You_are_in_preview_mode')}
);
@@ -199,14 +200,14 @@ export default class RoomView extends LoggedView {
if (this.state.room.archived || this.isReadOnly()) {
return (
- This room is read only
+ {I18n.t('This_room_is_read_only')}
);
}
if (this.isBlocked()) {
return (
- This room is blocked
+ {I18n.t('This_room_is_blocked')}
);
}
@@ -215,9 +216,9 @@ export default class RoomView extends LoggedView {
renderHeader = () => {
if (this.state.end) {
- return Start of conversation;
+ return {I18n.t('Start_of_conversation')};
}
- return Loading more messages...;
+ return {I18n.t('Loading_messages_ellipsis')};
}
render() {
return (
diff --git a/app/views/RoomsListView/Header/index.js b/app/views/RoomsListView/Header/index.js
index 194540754..a225b7d70 100644
--- a/app/views/RoomsListView/Header/index.js
+++ b/app/views/RoomsListView/Header/index.js
@@ -14,25 +14,26 @@ import { STATUS_COLORS } from '../../../constants/colors';
import { setSearch } from '../../../actions/rooms';
import styles from './styles';
import log from '../../../utils/log';
+import I18n from '../../../i18n';
const title = (offline, connecting, authenticating, logged) => {
if (offline) {
- return 'offline...';
+ return `${ I18n.t('Offline') }...`;
}
if (connecting) {
- return 'Connecting...';
+ return `${ I18n.t('Connecting') }...`;
}
if (authenticating) {
- return 'Authenticating...';
+ return `${ I18n.t('Authenticating') }...`;
}
if (logged) {
return null;
}
- return 'Not logged...';
+ return `${ I18n.t('Not_logged') }...`;
};
@connect(state => ({
@@ -96,7 +97,7 @@ export default class RoomsListHeaderView extends React.PureComponent {
getUserStatusLabel() {
const status = this.getUserStatus();
- return status.charAt(0).toUpperCase() + status.slice(1);
+ return I18n.t(status.charAt(0).toUpperCase() + status.slice(1));
}
showModal() {
@@ -124,7 +125,7 @@ export default class RoomsListHeaderView extends React.PureComponent {
@@ -156,7 +157,7 @@ export default class RoomsListHeaderView extends React.PureComponent {
const t = title(offline, connecting, authenticating, logged);
- const accessibilityLabel = `${ user.username }, ${ this.getUserStatusLabel() }, tap to change status`;
+ const accessibilityLabel = `${ user.username }, ${ this.getUserStatusLabel() }, ${ I18n.t('tap_to_change_status') }`;
return (
this.onPressSearchButton()}
- accessibilityLabel='Search'
+ accessibilityLabel={I18n.t('Search')}
accessibilityTraits='button'
>
this.createChannel()}
- accessibilityLabel='Create channel'
+ accessibilityLabel={I18n.t('Create_Channel')}
accessibilityTraits='button'
testID='rooms-list-view-create-channel'
>
@@ -223,6 +224,7 @@ export default class RoomsListHeaderView extends React.PureComponent {
renderModalButton = (status, text) => {
const statusStyle = [styles.status, { marginRight: 10, backgroundColor: STATUS_COLORS[status] }];
const textStyle = { flex: 1, fontWeight: this.props.user.status === status ? 'bold' : 'normal' };
+ const label = text || status;
return (
- {text || status.charAt(0).toUpperCase() + status.slice(1)}
+ {I18n.t(label.charAt(0).toUpperCase() + label.slice(1))}
);
@@ -252,7 +254,7 @@ export default class RoomsListHeaderView extends React.PureComponent {
style={styles.inputSearch}
onChangeText={text => this.onSearchChangeText(text)}
returnKeyType='search'
- placeholder='Search'
+ placeholder={I18n.t('Search')}
clearButtonMode='while-editing'
blurOnSubmit
autoCorrect={false}
@@ -281,7 +283,7 @@ export default class RoomsListHeaderView extends React.PureComponent {
{this.renderModalButton('online')}
{this.renderModalButton('busy')}
{this.renderModalButton('away')}
- {this.renderModalButton('offline', 'Invisible')}
+ {this.renderModalButton('offline', 'invisible')}
diff --git a/app/views/RoomsListView/index.js b/app/views/RoomsListView/index.js
index d1c8726fc..929e0cfb9 100644
--- a/app/views/RoomsListView/index.js
+++ b/app/views/RoomsListView/index.js
@@ -14,6 +14,7 @@ import styles from './styles';
import debounce from '../../utils/debounce';
import LoggedView from '../View';
import log from '../../utils/log';
+import I18n from '../../i18n';
@connect(state => ({
user: state.login.user,
@@ -166,7 +167,7 @@ export default class RoomsListView extends LoggedView {
style={styles.searchBox}
onChangeText={text => this.onSearchChangeText(text)}
returnKeyType='search'
- placeholder='Search'
+ placeholder={I18n.t('Search')}
clearButtonMode='while-editing'
blurOnSubmit
autoCorrect={false}
@@ -213,7 +214,7 @@ export default class RoomsListView extends LoggedView {
renderCreateButtons = () => (
- { this.createChannel(); }} >
+ { this.createChannel(); }} >
diff --git a/app/views/SearchMessagesView/index.js b/app/views/SearchMessagesView/index.js
index f7ca21767..4aa45da26 100644
--- a/app/views/SearchMessagesView/index.js
+++ b/app/views/SearchMessagesView/index.js
@@ -14,6 +14,7 @@ import buildMessage from '../../lib/methods/helpers/buildMessage';
import Message from '../../containers/message';
import scrollPersistTaps from '../../utils/scrollPersistTaps';
import log from '../../utils/log';
+import I18n from '../../i18n';
@connect(state => ({
user: state.login.user,
@@ -114,12 +115,12 @@ export default class SearchMessagesView extends LoggedView {
{ this.name = e; }}
- label='Search'
+ label={I18n.t('Search')}
onChangeText={this.onChangeSearch}
- placeholder='Search Messages'
+ placeholder={I18n.t('Search_Messages')}
testID='search-message-view-input'
/>
-
+
params.nextAction()}
- accessibilityLabel='Submit'
+ accessibilityLabel={I18n.t('Submit')}
accessibilityTraits='button'
testID='selected-users-view-submit'
>
@@ -227,7 +228,7 @@ export default class SelectedUsersView extends LoggedView {
style={styles.searchBox}
onChangeText={text => this.onSearchChangeText(text)}
returnKeyType='search'
- placeholder='Search'
+ placeholder={I18n.t('Search')}
clearButtonMode='while-editing'
blurOnSubmit
testID='select-users-view-search'
diff --git a/app/views/SnippetedMessagesView/index.js b/app/views/SnippetedMessagesView/index.js
index 9535e28c2..f1b240023 100644
--- a/app/views/SnippetedMessagesView/index.js
+++ b/app/views/SnippetedMessagesView/index.js
@@ -8,6 +8,7 @@ import { openSnippetedMessages, closeSnippetedMessages } from '../../actions/sni
import styles from './styles';
import Message from '../../containers/message';
import RCActivityIndicator from '../../containers/ActivityIndicator';
+import I18n from '../../i18n';
@connect(
state => ({
@@ -74,7 +75,7 @@ export default class SnippetedMessagesView extends LoggedView {
renderEmpty = () => (
- No snippeted messages
+ {I18n.t('No_snippeted_messages')}
)
diff --git a/app/views/StarredMessagesView/index.js b/app/views/StarredMessagesView/index.js
index f9df1e04d..6feed3c3b 100644
--- a/app/views/StarredMessagesView/index.js
+++ b/app/views/StarredMessagesView/index.js
@@ -10,10 +10,11 @@ import styles from './styles';
import Message from '../../containers/message';
import { toggleStarRequest } from '../../actions/messages';
import RCActivityIndicator from '../../containers/ActivityIndicator';
+import I18n from '../../i18n';
const STAR_INDEX = 0;
const CANCEL_INDEX = 1;
-const options = ['Unstar', 'Cancel'];
+const options = [I18n.t('Unstar'), I18n.t('Cancel')];
@connect(
state => ({
@@ -98,7 +99,7 @@ export default class StarredMessagesView extends LoggedView {
renderEmpty = () => (
- No starred messages
+ {I18n.t('No_starred_messages')}
)
@@ -138,7 +139,7 @@ export default class StarredMessagesView extends LoggedView {
this.actionSheet = o}
- title='Actions'
+ title={I18n.t('Actions')}
options={options}
cancelButtonIndex={CANCEL_INDEX}
onPress={this.handleActionPress}
diff --git a/app/views/TermsServiceView.js b/app/views/TermsServiceView.js
index b56abca08..f27d30a41 100644
--- a/app/views/TermsServiceView.js
+++ b/app/views/TermsServiceView.js
@@ -3,15 +3,11 @@ import PropTypes from 'prop-types';
import { WebView } from 'react-native';
import { connect } from 'react-redux';
-class TermsServiceView extends React.Component {
+class TermsServiceView extends React.PureComponent {
static propTypes = {
termsService: PropTypes.string
}
- static navigationOptions = () => ({
- title: 'Terms of service'
- });
-
render() {
return (
diff --git a/e2e/07-room.spec.js b/e2e/07-room.spec.js
index e3cb3874d..70490aef9 100644
--- a/e2e/07-room.spec.js
+++ b/e2e/07-room.spec.js
@@ -178,16 +178,16 @@ describe('Room screen', () => {
describe('Message', async() => {
it('should show message actions', async() => {
await element(by.text(`${ data.random }message`)).longPress();
- await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
- await expect(element(by.text('Messages actions'))).toBeVisible();
+ await waitFor(element(by.text('Message actions'))).toBeVisible().withTimeout(5000);
+ await expect(element(by.text('Message actions'))).toBeVisible();
await element(by.text('Cancel')).tap();
await waitFor(element(by.text('Cancel'))).toBeNotVisible().withTimeout(2000);
});
it('should copy permalink', async() => {
await element(by.text(`${ data.random }message`)).longPress();
- await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
- await expect(element(by.text('Messages actions'))).toBeVisible();
+ await waitFor(element(by.text('Message actions'))).toBeVisible().withTimeout(5000);
+ await expect(element(by.text('Message actions'))).toBeVisible();
await element(by.text('Copy Permalink')).tap();
await expect(element(by.text('Permalink copied to clipboard!'))).toBeVisible();
await waitFor(element(by.text('Permalink copied to clipboard!'))).toBeNotVisible().withTimeout(5000);
@@ -197,8 +197,8 @@ describe('Room screen', () => {
it('should copy message', async() => {
await element(by.text(`${ data.random }message`)).longPress();
- await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
- await expect(element(by.text('Messages actions'))).toBeVisible();
+ await waitFor(element(by.text('Message actions'))).toBeVisible().withTimeout(5000);
+ await expect(element(by.text('Message actions'))).toBeVisible();
await element(by.text('Copy Message')).tap();
await expect(element(by.text('Copied to clipboard!'))).toBeVisible();
await waitFor(element(by.text('Copied to clipboard!'))).toBeNotVisible().withTimeout(5000);
@@ -207,10 +207,10 @@ describe('Room screen', () => {
it('should star message', async() => {
await element(by.text(`${ data.random }message`)).longPress();
- await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
- await expect(element(by.text('Messages actions'))).toBeVisible();
+ await waitFor(element(by.text('Message actions'))).toBeVisible().withTimeout(5000);
+ await expect(element(by.text('Message actions'))).toBeVisible();
await element(by.text('Star')).tap();
- await waitFor(element(by.text('Messages actions'))).toBeNotVisible().withTimeout(5000);
+ await waitFor(element(by.text('Message actions'))).toBeNotVisible().withTimeout(5000);
await element(by.text(`${ data.random }message`)).longPress();
await waitFor(element(by.text('Unstar'))).toBeVisible().withTimeout(2000);
await expect(element(by.text('Unstar'))).toBeVisible();
@@ -220,8 +220,8 @@ describe('Room screen', () => {
it('should react to message', async() => {
await element(by.text(`${ data.random }message`)).longPress();
- await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
- await expect(element(by.text('Messages actions'))).toBeVisible();
+ await waitFor(element(by.text('Message actions'))).toBeVisible().withTimeout(5000);
+ await expect(element(by.text('Message actions'))).toBeVisible();
await element(by.text('Add Reaction')).tap();
await waitFor(element(by.id('reaction-picker'))).toBeVisible().withTimeout(2000);
await expect(element(by.id('reaction-picker'))).toBeVisible();
@@ -254,8 +254,8 @@ describe('Room screen', () => {
it('should reply message', async() => {
await mockMessage('reply');
await element(by.text(`${ data.random }reply`)).longPress();
- await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
- await expect(element(by.text('Messages actions'))).toBeVisible();
+ await waitFor(element(by.text('Message actions'))).toBeVisible().withTimeout(5000);
+ await expect(element(by.text('Message actions'))).toBeVisible();
await element(by.text('Reply')).tap();
await element(by.id('messagebox-input')).typeText('replied');
await element(by.id('messagebox-send-message')).tap();
@@ -265,8 +265,8 @@ describe('Room screen', () => {
it('should edit message', async() => {
await mockMessage('edit');
await element(by.text(`${ data.random }edit`)).longPress();
- await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
- await expect(element(by.text('Messages actions'))).toBeVisible();
+ await waitFor(element(by.text('Message actions'))).toBeVisible().withTimeout(5000);
+ await expect(element(by.text('Message actions'))).toBeVisible();
await element(by.text('Edit')).tap();
await element(by.id('messagebox-input')).typeText('ed');
await element(by.id('messagebox-send-message')).tap();
@@ -277,8 +277,8 @@ describe('Room screen', () => {
it('should quote message', async() => {
await mockMessage('quote');
await element(by.text(`${ data.random }quote`)).longPress();
- await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
- await expect(element(by.text('Messages actions'))).toBeVisible();
+ await waitFor(element(by.text('Message actions'))).toBeVisible().withTimeout(5000);
+ await expect(element(by.text('Message actions'))).toBeVisible();
await element(by.text('Quote')).tap();
await element(by.id('messagebox-input')).typeText(`${ data.random }quoted`);
await element(by.id('messagebox-send-message')).tap();
@@ -287,10 +287,10 @@ describe('Room screen', () => {
it('should pin message', async() => {
await element(by.text(`${ data.random }edited`)).longPress();
- await waitFor(element(by.text('Messages actions'))).toBeVisible().withTimeout(5000);
- await expect(element(by.text('Messages actions'))).toBeVisible();
+ await waitFor(element(by.text('Message actions'))).toBeVisible().withTimeout(5000);
+ await expect(element(by.text('Message actions'))).toBeVisible();
await element(by.text('Pin')).tap();
- await waitFor(element(by.text('Messages actions'))).toBeNotVisible().withTimeout(5000);
+ await waitFor(element(by.text('Message actions'))).toBeNotVisible().withTimeout(5000);
await waitFor(element(by.text(`${ data.random }edited`)).atIndex(1)).toBeVisible().withTimeout(60000);
await element(by.text(`${ data.random }edited`)).atIndex(0).longPress();
await waitFor(element(by.text('Unpin'))).toBeVisible().withTimeout(2000);
diff --git a/ios/RocketChatRN.xcodeproj/project.pbxproj b/ios/RocketChatRN.xcodeproj/project.pbxproj
index 800e7e1a1..9ce790288 100644
--- a/ios/RocketChatRN.xcodeproj/project.pbxproj
+++ b/ios/RocketChatRN.xcodeproj/project.pbxproj
@@ -5,6 +5,7 @@
};
objectVersion = 46;
objects = {
+
/* Begin PBXBuildFile section */
00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; };
00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; };
@@ -12,6 +13,7 @@
00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; };
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; };
00E356F31AD99517003FC87E /* RocketChatRNTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* RocketChatRNTests.m */; };
+ 09CB5909C1E64707832358CE /* libRNI18n-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C01CD6D4653143EEB5100C3A /* libRNI18n-tvOS.a */; };
0C6E2DE448364EA896869ADF /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = B37C79D9BD0742CE936B6982 /* libc++.tbd */; };
0DC38A29B0E54AF4AF96CB95 /* MaterialCommunityIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 2EADB1731B5E47D093292B59 /* MaterialCommunityIcons.ttf */; };
0F026E58B8A6427D9A204D89 /* libSplashScreen.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B2607FA180F14E6584301101 /* libSplashScreen.a */; };
@@ -65,12 +67,13 @@
B8C682AD1FD8511E003A12C8 /* Ionicons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 1B0746E708284151B8AD1198 /* Ionicons.ttf */; };
B8C682AE1FD8511F003A12C8 /* Ionicons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 1B0746E708284151B8AD1198 /* Ionicons.ttf */; };
B8E79AF41F3CD167005B464F /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB61A68108700A75B9A /* Info.plist */; };
+ BAB7DC22804246F3923A1833 /* libFastImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FD2E2837F110483CA29EE0D4 /* libFastImage.a */; };
BED2B77AA660460E8BC9F8E0 /* libRNFetchBlob.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6533FB90166345D29F1B91C0 /* libRNFetchBlob.a */; };
C758F0BD5C3244E2BA073E61 /* libRNImagePicker.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B696712EE2345A59F007A88 /* libRNImagePicker.a */; };
CBD0E0A35B174C4DBFED3B31 /* Zocial.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E528DE3A405E43B4A37ABA68 /* Zocial.ttf */; };
D6408D9E4A864FF6BA986857 /* SimpleLineIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 8A2DD67ADD954AD9873F45FC /* SimpleLineIcons.ttf */; };
EF736EF520A64AE8820E684A /* libRealmReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DF26CC845883492D8AC8869B /* libRealmReact.a */; };
- BAB7DC22804246F3923A1833 /* libFastImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FD2E2837F110483CA29EE0D4 /* libFastImage.a */; };
+ F5BF54DC78E1411B8343933B /* libRNI18n.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 921481B47B50490CA761932E /* libRNI18n.a */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -326,6 +329,27 @@
remoteGlobalIDString = 39DF4FE71E00394E00F5B4B2;
remoteInfo = RCTCustomInputController;
};
+ 7A770EC120BECDC7001AD51A /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 1845C223DA364898A8400573 /* FastImage.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = A287971D1DE0C0A60081BDFA;
+ remoteInfo = FastImage;
+ };
+ 7A770EC520BECDC7001AD51A /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 22D3971EAF2E4660B4FAB3DD /* RNI18n.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 134814201AA4EA6300B7C361;
+ remoteInfo = RNI18n;
+ };
+ 7A770EC720BECDC7001AD51A /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 22D3971EAF2E4660B4FAB3DD /* RNI18n.xcodeproj */;
+ proxyType = 2;
+ remoteGlobalIDString = 6476C4051EEAA69700B10F51;
+ remoteInfo = "RNI18n-tvOS";
+ };
7A7F5C981FCC982500024129 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = AD0379F2BCE84C968538CDAF /* RCTVideo.xcodeproj */;
@@ -490,10 +514,12 @@
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = RocketChatRN/Info.plist; sourceTree = ""; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = RocketChatRN/main.m; sourceTree = ""; };
146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = ""; };
+ 1845C223DA364898A8400573 /* FastImage.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = FastImage.xcodeproj; path = "../node_modules/react-native-fast-image/ios/FastImage.xcodeproj"; sourceTree = ""; };
1B0746E708284151B8AD1198 /* Ionicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = file; name = Ionicons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf"; sourceTree = ""; };
1D3BB00B9ABF44EA9BD71318 /* libSafariViewManager.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libSafariViewManager.a; sourceTree = ""; };
20CE3E407E0D4D9E8C9885F2 /* libRCTVideo.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRCTVideo.a; sourceTree = ""; };
22A8B76C8EBA443BB97CE82D /* RNVectorIcons.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNVectorIcons.xcodeproj; path = "../node_modules/react-native-vector-icons/RNVectorIcons.xcodeproj"; sourceTree = ""; };
+ 22D3971EAF2E4660B4FAB3DD /* RNI18n.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNI18n.xcodeproj; path = "../node_modules/react-native-i18n/ios/RNI18n.xcodeproj"; sourceTree = ""; };
2D02E47B1E0B4A5D006451C7 /* RocketChatRN-tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "RocketChatRN-tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
2D02E4901E0B4A5D006451C7 /* RocketChatRN-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "RocketChatRN-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
2EADB1731B5E47D093292B59 /* MaterialCommunityIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = MaterialCommunityIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf"; sourceTree = ""; };
@@ -519,6 +545,7 @@
7AFB8035205AE63000D004E7 /* RCTToast.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTToast.xcodeproj; path = "../node_modules/@remobile/react-native-toast/ios/RCTToast.xcodeproj"; sourceTree = ""; };
832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = ""; };
8A2DD67ADD954AD9873F45FC /* SimpleLineIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = SimpleLineIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf"; sourceTree = ""; };
+ 921481B47B50490CA761932E /* libRNI18n.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNI18n.a; sourceTree = ""; };
9A1E1766CCB84C91A62BD5A6 /* Foundation.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Foundation.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Foundation.ttf"; sourceTree = ""; };
A18EFC3B0CFE40E0918A8F0C /* EvilIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = EvilIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf"; sourceTree = ""; };
AD0379F2BCE84C968538CDAF /* RCTVideo.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RCTVideo.xcodeproj; path = "../node_modules/react-native-video/ios/RCTVideo.xcodeproj"; sourceTree = ""; };
@@ -528,6 +555,7 @@
B8971BAC202A091D0000D245 /* KeyboardTrackingView.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = KeyboardTrackingView.xcodeproj; path = "../node_modules/react-native-keyboard-tracking-view/lib/KeyboardTrackingView.xcodeproj"; sourceTree = ""; };
B8C682611FD84CEF003A12C8 /* icomoon.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = icomoon.ttf; path = ../resources/fonts/icomoon.ttf; sourceTree = ""; };
BAAE4B947F5D44959F0A9D5A /* libRNZeroconf.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNZeroconf.a; sourceTree = ""; };
+ C01CD6D4653143EEB5100C3A /* libRNI18n-tvOS.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = "libRNI18n-tvOS.a"; sourceTree = ""; };
C21010507E5B4B37BA0E4C9D /* RNAudio.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNAudio.xcodeproj; path = "../node_modules/react-native-audio/ios/RNAudio.xcodeproj"; sourceTree = ""; };
C23AEF1D9EBE4A38A1A6B97B /* RNSVG.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNSVG.xcodeproj; path = "../node_modules/react-native-svg/ios/RNSVG.xcodeproj"; sourceTree = ""; };
DA50CE47374C4C35BE6D9D58 /* libRNSVG.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNSVG.a; sourceTree = ""; };
@@ -535,8 +563,7 @@
DF26CC845883492D8AC8869B /* libRealmReact.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRealmReact.a; sourceTree = ""; };
E528DE3A405E43B4A37ABA68 /* Zocial.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Zocial.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Zocial.ttf"; sourceTree = ""; };
F88C6541BD764BEEABB87272 /* Octicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Octicons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Octicons.ttf"; sourceTree = ""; };
- 1845C223DA364898A8400573 /* FastImage.xcodeproj */ = {isa = PBXFileReference; name = "FastImage.xcodeproj"; path = "../node_modules/react-native-fast-image/ios/FastImage.xcodeproj"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; };
- FD2E2837F110483CA29EE0D4 /* libFastImage.a */ = {isa = PBXFileReference; name = "libFastImage.a"; path = "libFastImage.a"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; };
+ FD2E2837F110483CA29EE0D4 /* libFastImage.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libFastImage.a; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -583,6 +610,7 @@
2C800DF680F8451599E80AF1 /* libSafariViewManager.a in Frameworks */,
74815BBCB91147C08C8F7B3D /* libRNAudio.a in Frameworks */,
BAB7DC22804246F3923A1833 /* libFastImage.a in Frameworks */,
+ F5BF54DC78E1411B8343933B /* libRNI18n.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -598,6 +626,7 @@
2D02E4C61E0B4AEC006451C7 /* libRCTSettings-tvOS.a in Frameworks */,
2D02E4C71E0B4AEC006451C7 /* libRCTText-tvOS.a in Frameworks */,
2D02E4C81E0B4AEC006451C7 /* libRCTWebSocket-tvOS.a in Frameworks */,
+ 09CB5909C1E64707832358CE /* libRNI18n-tvOS.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -788,6 +817,23 @@
name = Products;
sourceTree = "";
};
+ 7A770EBC20BECDC7001AD51A /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 7A770EC620BECDC7001AD51A /* libRNI18n.a */,
+ 7A770EC820BECDC7001AD51A /* libRNI18n-tvOS.a */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 7A770EBE20BECDC7001AD51A /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 7A770EC220BECDC7001AD51A /* libFastImage.a */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
7A7F5C831FCC982500024129 /* Products */ = {
isa = PBXGroup;
children = (
@@ -843,6 +889,7 @@
4019A5E1911B4C61944FBCEC /* SafariViewManager.xcodeproj */,
C21010507E5B4B37BA0E4C9D /* RNAudio.xcodeproj */,
1845C223DA364898A8400573 /* FastImage.xcodeproj */,
+ 22D3971EAF2E4660B4FAB3DD /* RNI18n.xcodeproj */,
);
name = Libraries;
sourceTree = "";
@@ -948,6 +995,9 @@
B2607FA180F14E6584301101 /* libSplashScreen.a */,
1D3BB00B9ABF44EA9BD71318 /* libSafariViewManager.a */,
1142E3442BA94B19BCF52814 /* libRNAudio.a */,
+ FD2E2837F110483CA29EE0D4 /* libFastImage.a */,
+ 921481B47B50490CA761932E /* libRNI18n.a */,
+ C01CD6D4653143EEB5100C3A /* libRNI18n-tvOS.a */,
);
name = "Recovered References";
sourceTree = "";
@@ -1109,6 +1159,10 @@
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
projectDirPath = "";
projectReferences = (
+ {
+ ProductGroup = 7A770EBE20BECDC7001AD51A /* Products */;
+ ProjectRef = 1845C223DA364898A8400573 /* FastImage.xcodeproj */;
+ },
{
ProductGroup = B8971BAD202A091D0000D245 /* Products */;
ProjectRef = B8971BAC202A091D0000D245 /* KeyboardTrackingView.xcodeproj */;
@@ -1185,6 +1239,10 @@
ProductGroup = B8E79A881F3CCC6C005B464F /* Products */;
ProjectRef = 4CD38E4891ED4601B7481448 /* RNFetchBlob.xcodeproj */;
},
+ {
+ ProductGroup = 7A770EBC20BECDC7001AD51A /* Products */;
+ ProjectRef = 22D3971EAF2E4660B4FAB3DD /* RNI18n.xcodeproj */;
+ },
{
ProductGroup = 60B8375C1F3F6F4B00677E56 /* Products */;
ProjectRef = 4B38C7E37A8748E0BC665078 /* RNImagePicker.xcodeproj */;
@@ -1463,6 +1521,27 @@
remoteRef = 7A430E1D20238C02008F55BC /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
+ 7A770EC220BECDC7001AD51A /* libFastImage.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libFastImage.a;
+ remoteRef = 7A770EC120BECDC7001AD51A /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 7A770EC620BECDC7001AD51A /* libRNI18n.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = libRNI18n.a;
+ remoteRef = 7A770EC520BECDC7001AD51A /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ 7A770EC820BECDC7001AD51A /* libRNI18n-tvOS.a */ = {
+ isa = PBXReferenceProxy;
+ fileType = archive.ar;
+ path = "libRNI18n-tvOS.a";
+ remoteRef = 7A770EC720BECDC7001AD51A /* PBXContainerItemProxy */;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
7A7F5C991FCC982500024129 /* libRCTVideo.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
@@ -1773,6 +1852,7 @@
"$(SRCROOT)/../node_modules/react-native-safari-view",
"$(SRCROOT)/../node_modules/react-native-audio/ios",
"$(SRCROOT)/../node_modules/react-native-fast-image/ios/FastImage/**",
+ "$(SRCROOT)/../node_modules/react-native-i18n/ios",
);
INFOPLIST_FILE = RocketChatRNTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
@@ -1787,6 +1867,8 @@
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
);
OTHER_LDFLAGS = (
"-ObjC",
@@ -1818,6 +1900,7 @@
"$(SRCROOT)/../node_modules/react-native-safari-view",
"$(SRCROOT)/../node_modules/react-native-audio/ios",
"$(SRCROOT)/../node_modules/react-native-fast-image/ios/FastImage/**",
+ "$(SRCROOT)/../node_modules/react-native-i18n/ios",
);
INFOPLIST_FILE = RocketChatRNTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
@@ -1832,6 +1915,8 @@
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
);
OTHER_LDFLAGS = (
"-ObjC",
@@ -1873,6 +1958,7 @@
"$(SRCROOT)/../node_modules/react-native-audio/ios",
"$(SRCROOT)/../../../react-native/React/**",
"$(SRCROOT)/../node_modules/react-native-fast-image/ios/FastImage/**",
+ "$(SRCROOT)/../node_modules/react-native-i18n/ios",
);
INFOPLIST_FILE = RocketChatRN/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
@@ -1919,6 +2005,7 @@
"$(SRCROOT)/../node_modules/react-native-audio/ios",
"$(SRCROOT)/../../../react-native/React/**",
"$(SRCROOT)/../node_modules/react-native-fast-image/ios/FastImage/**",
+ "$(SRCROOT)/../node_modules/react-native-i18n/ios",
);
INFOPLIST_FILE = RocketChatRN/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
@@ -1963,6 +2050,7 @@
"$(SRCROOT)/../node_modules/react-native-safari-view",
"$(SRCROOT)/../node_modules/react-native-audio/ios",
"$(SRCROOT)/../node_modules/react-native-fast-image/ios/FastImage/**",
+ "$(SRCROOT)/../node_modules/react-native-i18n/ios",
);
INFOPLIST_FILE = "RocketChatRN-tvOS/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
@@ -1976,6 +2064,8 @@
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
);
OTHER_LDFLAGS = (
"-ObjC",
@@ -2017,6 +2107,7 @@
"$(SRCROOT)/../node_modules/react-native-safari-view",
"$(SRCROOT)/../node_modules/react-native-audio/ios",
"$(SRCROOT)/../node_modules/react-native-fast-image/ios/FastImage/**",
+ "$(SRCROOT)/../node_modules/react-native-i18n/ios",
);
INFOPLIST_FILE = "RocketChatRN-tvOS/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
@@ -2030,6 +2121,8 @@
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
);
OTHER_LDFLAGS = (
"-ObjC",
@@ -2067,6 +2160,8 @@
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
);
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.RocketChatRN-tvOSTests";
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -2100,6 +2195,8 @@
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
"\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
+ "\"$(SRCROOT)/$(TARGET_NAME)\"",
);
PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.RocketChatRN-tvOSTests";
PRODUCT_NAME = "$(TARGET_NAME)";
diff --git a/package-lock.json b/package-lock.json
index 62ea43eeb..b8dbfd33f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8852,6 +8852,11 @@
"resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz",
"integrity": "sha1-MRYKNpMK2vH8BMYHT360FGXU7Es="
},
+ "i18n-js": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/i18n-js/-/i18n-js-3.0.3.tgz",
+ "integrity": "sha512-u144MQhV/8mz4Y5wP86SQAWMwS8gpe/JavIa9hugSI4WreezGgbhJPdk2Q60KcdIltKLiNefGtHNh1N8SSmQqQ=="
+ },
"iconv-lite": {
"version": "0.4.19",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
@@ -14806,6 +14811,14 @@
"prop-types": "15.6.1"
}
},
+ "react-native-i18n": {
+ "version": "2.0.12",
+ "resolved": "https://registry.npmjs.org/react-native-i18n/-/react-native-i18n-2.0.12.tgz",
+ "integrity": "sha512-2eTUk7BVZP5knthCmVt6y7rePFwrxXl4ym2I20e91oTYJnKM22sAjQMnLhRCYZWC4ucRBbe2pUp63uxNdTkkQw==",
+ "requires": {
+ "i18n-js": "3.0.3"
+ }
+ },
"react-native-image-picker": {
"version": "0.26.10",
"resolved": "https://registry.npmjs.org/react-native-image-picker/-/react-native-image-picker-0.26.10.tgz",
diff --git a/package.json b/package.json
index 60b026184..8e6b4dda7 100644
--- a/package.json
+++ b/package.json
@@ -47,6 +47,7 @@
"react-native-fabric": "^0.5.1",
"react-native-fast-image": "^4.0.14",
"react-native-fetch-blob": "^0.10.8",
+ "react-native-i18n": "^2.0.12",
"react-native-image-picker": "^0.26.10",
"react-native-keyboard-aware-scroll-view": "^0.5.0",
"react-native-keyboard-input": "git+https://github.com/RocketChat/react-native-keyboard-input.git",