I use the Google Cloud translation API for my react-native app to translate the text. In translateText function, the header has the key that generates by Google Cloud SDK shell manually, so when I rebuild the app, this key is inactive and the text can not be translated. I use this API: https://cloud.google.com/translate/docs/basic/translating-text.
Here is my code:
import { useNavigation } from '@react-navigation/native';
import React, { useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
Image,
Platform,
SafeAreaView,
StyleProp,
StyleSheet,
Text,
ToastAndroid,
TouchableOpacity,
View,
ViewStyle,
} from 'react-native';
import { Clipboard } from 'react-native';
import { ScrollView } from 'react-native-gesture-handler';
import Textarea from 'react-native-textarea';
import usePreferenceContext from '~/hooks/usePreferenceContext';
import getImage from '~/libs/getImage';
import IconCopy from '~/resources/Icons/IconCopy';
import IconDropdown from '~/resources/Icons/IconDropdown';
import IconShare from '~/resources/Icons/IconShare';
import IconStar from '~/resources/Icons/IconStar';
import IconSwap from '~/resources/Icons/IconSwap';
import IconVoice from '~/resources/Icons/IconVoice';
import { useAppTheme } from '~/resources/theme';
import { RootNavigatorNavProps } from '~/navigation/RootNavigator';
import HistoryTrans from '../components/History/historyTrans';
import axios from 'axios';
const HomePage = (): JSX.Element => {
const actionButton = usePreferenceContext();
const dataLanguageInput = actionButton.result.languageSelect;
const dataLanguageOutPut = actionButton.result.languageSelectOutput;
const { t } = useTranslation();
const theme = useAppTheme();
const [textInput, setTextInput] = useState('');
const [textOutPut, setTextOutPut] = useState('');
const navigation = useNavigation<RootNavigatorNavProps>();
const data = {
title:
'This is the first workshop dedicated to new employees since June of this year This is the first workshop dedicated to new employees since June of this year',
description:
'This is the first workshop dedicated to new employees since June of this year This is the first workshop dedicated to new employees since June of this year',
active: false,
time: '24/12/2023',
};
const handleCopyInput = () => {
Clipboard.setString(textInput);
ToastAndroid.show('Text copied to clipboard!', ToastAndroid.SHORT);
};
const onChangeInput = (e: any) => {
setTextInput(e);
};
const onChangeOutPut = (e: any) => {
setTextOutPut(e);
};
const handleCopy = () => {
Clipboard.setString(textOutPut);
ToastAndroid.show('Text copied to clipboard!', ToastAndroid.SHORT);
};
const handleTrans = async () => {
if (textInput) {
const translatedText = await translateText(textInput, dataLanguageOutPut.countyCode);
setTextOutPut(translatedText);
} else {
console.log('typing to translate');
}
};
const styleContainer = useMemo<StyleProp<ViewStyle>>(
() => [
{
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#EDEDED',
},
],
[theme],
);
const translateText = async (text, targetLanguage) => {
console.log(text, 'text');
console.log(targetLanguage, 'targetLanguage');
try {
const response = await axios.post(
'https://translation.googleapis.com/language/translate/v2',
{
q: text,
target: targetLanguage,
},
{
headers: { 'Authorization': `Bearer ya29.a0AfB_byBW4x4jeQ_fFiRXKH2pZlxz-l0YdFswol81M8S1CNPkPtMapNEJNwYjGCCKNpxhEWJsmi7c4sSPkAU-lgzQakFtGeb71SnCGnQ7IIk8Zl7JWcLV2WahWxm_PsMiq44FPUardFE_AJJQC0KxEYR0_1mks85sPg4Um4aRXdcaCgYKAaQSARMSFQHGX2MiDRmtAuMhNdctGYPrsAKYpQ0178`, "x-goog-user-project": "translation-app-410307"}
}
);
return response.data.data.translations[0].translatedText;
} catch (error) {
console.error('Error during translation:', error);
return '';
}
};
return (
<SafeAreaView style={styleContainer}>
<View
style={{
flex: 1,
width: '100%',
paddingHorizontal: 24,
paddingTop: Platform.select({
ios: 0,
android: 40,
}),
}}>
<View
style={{
alignItems: 'center',
flexDirection: 'row',
justifyContent: 'center',
paddingBottom: 24,
}}>
<Text
style={{
color: '#000000',
fontSize: 24,
textAlign: 'center',
fontWeight: '700',
}}>
{t('Translator')}
</Text>
<View />
</View>
<>
<ScrollView
showsVerticalScrollIndicator={false}
style={{ marginBottom: 5 }}>
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
}}>
<View
style={{
backgroundColor: '#fff',
width: '40%',
borderRadius: 12,
height: 48,
justifyContent: 'center',
}}>
<TouchableOpacity
onPress={() =>
navigation.navigate('Language', { data: 'false' })
}
style={{ width: '100%' }}>
<View
style={{
padding: 12,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
}}>
<View style={{ flexDirection: 'row' }}>
<View style={{ paddingRight: 8 }}>
<Image
source={dataLanguageInput.image}
style={{ width: 24, height: 16 }}
/>
</View>
<Text>{dataLanguageInput.name}</Text>
</View>
<View>
<IconDropdown />
</View>
</View>
</TouchableOpacity>
</View>
<View
style={{
backgroundColor: '#2665EF',
width: 48,
height: 48,
borderRadius: 99,
alignItems: 'center',
justifyContent: 'center',
}}>
<IconSwap />
</View>
<View
style={{
backgroundColor: '#fff',
width: '40%',
borderRadius: 12,
height: 48,
justifyContent: 'center',
}}>
<TouchableOpacity
onPress={() =>
navigation.navigate('Language', { data: 'true' })
}
style={{ width: '100%' }}>
<View
style={{
padding: 12,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
}}>
<View style={{ flexDirection: 'row' }}>
<View style={{ paddingRight: 8 }}>
<Image
source={dataLanguageOutPut.image}
style={{ width: 24, height: 16 }}
/>
</View>
<Text>{dataLanguageOutPut.name}</Text>
</View>
<View>
<IconDropdown />
</View>
</View>
</TouchableOpacity>
</View>
</View>
<View>
<View style={{ paddingTop: 24 }}>
<View
style={{
backgroundColor: '#FFFFFF',
paddingHorizontal: 16,
borderRadius: 12,
paddingVertical: 12,
}}>
<Textarea
containerStyle={styles.textareaContainer}
onChangeText={(e: any) => onChangeInput(e)}
placeholder={'Typing to be able to translate 。。。'}
placeholderTextColor={'#c7c7c7'}
underlineColorAndroid={'transparent'}
/>
<View
style={{
backgroundColor: '#A0A0A0',
width: '100%',
height: 1,
}}
/>
<View
style={{
paddingTop: 14,
flexDirection: 'row',
justifyContent: 'flex-end',
}}>
<IconVoice />
<TouchableOpacity onPress={handleCopyInput}>
<View style={{ paddingLeft: 24 }}>
<IconCopy />
</View>
</TouchableOpacity>
</View>
</View>
</View>
<TouchableOpacity onPress={handleTrans}>
<View
style={{ justifyContent: 'center', alignItems: 'center' }}>
<View
style={{
backgroundColor: textInput ? '#2665EF' : '#A0A0A0',
width: 154,
height: 48,
borderRadius: 12,
justifyContent: 'center',
alignItems: 'center',
marginVertical: 12,
}}>
<Text
style={{
color: '#fff',
fontSize: 14,
fontWeight: '900',
}}>
Translate
</Text>
</View>
</View>
</TouchableOpacity>
<View>
<View
style={{
backgroundColor: '#FFFFFF',
paddingHorizontal: 16,
borderRadius: 12,
paddingVertical: 12,
}}>
<Textarea
containerStyle={styles.textareaContainer}
onChangeText={(e: any) => onChangeOutPut(e)}
underlineColorAndroid={'transparent'}
editable={false}
value = {textOutPut}
/>
<View
style={{
backgroundColor: '#A0A0A0',
width: '100%',
height: 1,
}}
/>
<View
style={{
paddingTop: 14,
flexDirection: 'row',
justifyContent: 'flex-end',
}}>
<IconStar />
<View style={{ paddingHorizontal: 24 }}>
<IconShare />
</View>
<IconVoice />
<TouchableOpacity onPress={handleCopy}>
<View style={{ paddingLeft: 24 }}>
<IconCopy />
</View>
</TouchableOpacity>
</View>
</View>
</View>
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
paddingVertical: 12,
}}>
<Text style={{ fontSize: 14, fontWeight: '400' }}>
{t('Recent')}
</Text>
<TouchableOpacity
onPress={() => navigation.navigate('History')}>
<Text
style={{
fontSize: 14,
fontWeight: '400',
color: '#2665EF',
}}>
{t('View more')}
</Text>
</TouchableOpacity>
</View>
</View>
<HistoryTrans
title={data.title}
description={data.description}
active={data.active}
time={data.time}
/>
</ScrollView>
</>
</View>
</SafeAreaView>
);
};
export default HomePage;
const styles = StyleSheet.create({
textareaContainer: {
height: 120,
padding: 5,
},
});