How to translate in React Native app- Globalization, Internationalization, and Text to Speech
Tags: reactnative, translation, localization, internationalization
Published: 2020-03-29 15:27:22

<main role="main"><article class=" u-minHeight100vhOffset65 u-overflowHidden postArticle postArticle--full is-supplementalPostContentLoaded is-withAccentColors" lang="en"><div class="postArticle-content js-postField js-notesSource editable" id="editor_6" g_editable="true" role="textbox" contenteditable="true" data-default-value="Title
Tell your story…" spellcheck="false"><section name="71e9" class="section section--body section--first section--last"><div class="section-divider"><hr class="section-divider"></div><div class="section-content"><div class="section-inner sectionLayout--insetColumn"><p name="63d1" class="graf graf--p graf-after--figure">This post is all about implementing the multi-language translation and text to speech in your cool new react-native application. In this post, you will learn</p><ul class="postList"><li name="df63" class="graf graf--li graf-after--p">How to implement <code class="markup--code markup--li-code">react-native-tts </code>in our app.</li><li name="039a" class="graf graf--li graf-after--li">How to use <code class="markup--code markup--li-code">i18n-js</code> in your app.</li><li name="9b69" class="graf graf--li graf-after--li">How to implement <code class="markup--code markup--li-code">react-native-localization </code>in our app.</li></ul><p name="9ab1" class="graf graf--p graf-after--li">Before start, first you will need a React-Native app to start with, hence you can follow <a href="https://facebook.github.io/react-native/docs/getting-started"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank"><strong class="markup--strong markup--p-strong">how to create a react-native app for beginners</strong> </a>and start after that from here.</p><blockquote name="5aba" class="graf graf--blockquote graf-after--p"><strong class="markup--strong markup--blockquote-strong">Complete source code of this tutorial is available here&#8202;—&#8202;</strong><a href="https://github.com/mdshadman/RNInternationalizatio-TextToSpeech"  class="markup--anchor markup--blockquote-anchor" rel="noopener"    target="_blank"><strong class="markup--strong markup--blockquote-strong">RNInternationalizatio-TextToSpeech</strong></a><strong class="markup--strong markup--blockquote-strong">.</strong></blockquote><h3 name="63a9" class="graf graf--h3 graf-after--blockquote">What is React-Native</h3><p name="e21e" class="graf graf--p graf-after--h3 is-selected">React Native is a JavaScript framework for writing real, natively rendering mobile applications for iOS and Android. It’s based on React, Facebook’s JavaScript library for building user interfaces, but instead of targeting the browser, it targets mobile platforms. In other words: web developers can now write mobile applications that look and feel truly “native,” all from the comfort of a JavaScript library that we already know and love. Plus, because most of the code you write can be shared between platforms, React Native makes it easy to simultaneously develop for both Android and iOS.</p><p name="5626" class="graf graf--p graf-after--p">Similar to React for the Web, React Native applications are written using a mixture of JavaScript and XML-Esque markup, known as JSX. Then, under the hood, the React Native “bridge” invokes the native rendering APIs in Objective-C (for iOS) or Java (for Android). Thus, your application will render using real mobile UI components, <em class="markup--em markup--p-em">not</em> web views, and will look and feel like any other mobile application. React Native also exposes JavaScript interfaces for platform APIs, so your React Native apps can access platform features like the phone camera, or the user’s location.</p><p name="de54" class="graf graf--p graf-after--p">React Native currently supports both iOS and Android and has the potential to expand to future platforms as well. In this tutorial, we’ll cover translation and text to speech implementation. The vast majority of the code we write will be cross-platform. And yes: you can use React Native to build production-ready mobile applications! Some anecdota: <a href="http://bit.ly/1YipO7A"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">Facebook</a>, <a href="http://bit.ly/1PPEiZH"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">Palantir</a>, and <a href="http://bit.ly/1PPEjNg"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">TaskRabbit</a> are already using it in production for user-facing applications.<br>&nbsp;The fact that React Native actually renders using its host platform’s standard rendering APIs enables it to stand out from most existing methods of cross-platform application development, like Cordova or Ionic.</p><p name="cd94" class="graf graf--p graf-after--p">Existing methods of writing mobile applications using combinations of JavaScript, HTML, and CSS typically render using web views. While this approach can work, it also comes with drawbacks, especially around performance. Additionally, they do not usually have access to the host platform’s set of native UI elements. When these frameworks do try to mimic native UI elements, the results usually “feel” just a little off; reverse-engineering all the fine details of things like animations takes an enormous amount of effort, and they can quickly become out of date.</p><h3 name="84aa" class="graf graf--h3 graf-after--p">What and why Internationalization and Text to&nbsp;speech?</h3><p name="1df5" class="graf graf--p graf-after--h3"><strong class="markup--strong markup--p-strong">Internationalization in React Native</strong>. <strong class="markup--strong markup--p-strong">Internationalization</strong> (<strong class="markup--strong markup--p-strong">i18n</strong> for short) is the process of adapting an application to work with different languages and regions.</p><h4 name="a557" class="graf graf--h4 graf-after--p">i18n</h4><p name="13b7" class="graf graf--p graf-after--h4">In computing, there’s a common term used when discussing localization &amp; internationalization called <strong class="markup--strong markup--p-strong">i18n </strong>which is basically the first and last letters in the word <strong class="markup--strong markup--p-strong">i</strong>nternationalizatio<strong class="markup--strong markup--p-strong">n </strong>and the 18 characters between them (thanks <a href="https://en.wikipedia.org/wiki/Internationalization_and_localization"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">Wikipedia</a> for that).</p><p name="a3da" class="graf graf--p graf-after--p">Multi-language translation OR internationalization-localization is a growing need for every app that wants to target international customers. Till date, the majority of apps have been developed in English, no surprise! In this blog post, we will learn how to implement translation, OR technically&#8202;—&#8202;Internationalization + Localization in Ionic 4 apps.</p><p name="6150" class="graf graf--p graf-after--p">First, we need to understand the steps involved in the process. Translations, thanks to Google, look very easy, but they are a bit involved in the case of apps and websites, in our case Ionic 4 apps. There are 3 major steps in the translation process in an app —</p><ol class="postList"><li name="b895" class="graf graf--li graf-after--p"><strong class="markup--strong markup--li-strong">Translation Language</strong>&#8202;—&#8202;Detect the language you want to translate into. This can either be done automatically by detecting phone or browser’s language OR, can be done with user actions (say, by using a dropdown).<br>For our use case, we will detect the device’s language using <a href="https://www.npmjs.com/package/react-native-localization"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank"><strong class="markup--strong markup--li-strong">react-native-localization.</strong></a></li><li name="b140" class="graf graf--li graf-after--li"><strong class="markup--strong markup--li-strong">Prepare Language Text</strong>&#8202;—&#8202;You need to have a pre-translated dictionary (or JSON file) that stores the translations of all your app’s text in the Translation language. There are several ways to do this, as we’ll see in the following steps. This is mostly a manual process for smaller apps, but you can use online tools like <a href="https://www.logisticinfotech.com/translate-language-files-online-json/"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">this</a> for quick translations, or like <a href="https://poeditor.com/"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">POEditor</a> for more standardized workflow.</li><li name="7429" class="graf graf--li graf-after--li"><strong class="markup--strong markup--li-strong">Translate</strong>&#8202;—&#8202;After the above two steps, you actually translate your app’s text to the Translation language text. We will use the <a href="https://github.com/fnando/i18n-js"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">i18n-js</a> library for translating our texts.</li></ol><p name="56ff" class="graf graf--p graf-after--li">Till now we got to know about our implementations and the basic idea of our need. Hence we will achieve the above target by following it step by step.</p><h3 name="53d1" class="graf graf--h3 graf-after--p">STEP 1: Prepare language JSON&nbsp;files</h3><p name="8911" class="graf graf--p graf-after--h3">We will create these JSON files in <code class="markup--code markup--p-code">android/app/src/main/assets/translations</code> folder. The <code class="markup--code markup--p-code">assets</code> folder remains in the root even after a production builds, so the path does not break. I have created multiple JSON files <code class="markup--code markup--p-code">en.json</code> (English), <code class="markup--code markup--p-code">fr.json</code> (French),<code class="markup--code markup--p-code">es.json</code> (Spanish),<code class="markup--code markup--p-code">ar.json</code> (Arabic),<code class="markup--code markup--p-code">it.json</code> (Italian),<code class="markup--code markup--p-code">hi.json</code> (Hindi),<code class="markup--code markup--p-code">ru.json</code> (Russian) and many more.</p><p name="f909" class="graf graf--p graf-after--p">Folder structure for i18n files are like below</p><p name="7b20" class="graf graf--p graf-after--p"><strong class="markup--strong markup--p-strong">en.json</strong></p><pre name="2a67" class="graf graf--pre graf-after--p">{<br>"hello": "Hello shadman! Welcome to localizationa nd internationalization tutorial. Hope you enjoyed the tutorial and implemented it in your app."<br>}</pre><p name="f004" class="graf graf--p graf-after--pre">The <code class="markup--code markup--p-code">`{{value}}`</code> and <code class="markup--code markup--p-code">`{{name_value}}`</code> are kind of variable/constants we can pass from our component. This can be used to keep a word constant across translations OR to give translations not supported by the library.</p><h3 name="19a6" class="graf graf--h3 graf-after--p">STEP 2: Implement libraries</h3><p name="20f5" class="graf graf--p graf-after--h3">We’ll start by adding an internationalization module to our React Native project called <code class="markup--code markup--p-code"><a href="https://github.com/AlexanderZaytsev/react-native-i18n"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank"><strong class="markup--strong markup--p-strong">react-native-i18n</strong></a></code>:</p><pre name="c1c6" class="graf graf--pre graf-after--p">npm i react-native-i18n --save</pre><p name="1c20" class="graf graf--p graf-after--pre">Now install the npm package <strong class="markup--strong markup--p-strong">react-native-localization</strong></p><pre name="b367" class="graf graf--pre graf-after--p">npm i react-native-localization</pre><p name="7271" class="graf graf--p graf-after--pre">Now install the npm package <strong class="markup--strong markup--p-strong">react-native-tts </strong>for text to speech</p><pre name="8faf" class="graf graf--pre graf-after--p">npm i react-native-tts</pre><p name="864f" class="graf graf--p graf-after--pre">We will implement both internationalization and text to speech together in our app but step by step.</p><p name="271a" class="graf graf--p graf-after--p">Here, we are working on <strong class="markup--strong markup--p-strong">react-native version 0.60.5</strong>. Hence we don’t need to link any package externally as in the latest versions above 0.60 react-native provides <strong class="markup--strong markup--p-strong">auto-linking functionality</strong>.</p><h4 name="b984" class="graf graf--h4 graf-after--p">Add Interactive UI to Translate and text to&nbsp;speech</h4><p name="d865" class="graf graf--p graf-after--h4">Now you are ready to use the localization and text to speech function provided by the React-Native <code class="markup--code markup--p-code">react-native-tts and react-native-localization </code>package and get the result. Before this let us make a beautiful view to access these functions by clicking a button and getting the data in response.</p><figure tabindex="0" contenteditable="false" name="e0e5" class="graf graf--figure graf--iframe is-defaultValue graf-after--p"><div class="aspectRatioPlaceholder is-locked"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 35.699999999999996%;"></div><div class="iframeContainer">{% gist https://gist.github.com/mdshadman/ea91b94fafa110a6344d284362f222cf.js %}</div></div></figure><p name="eab5" class="graf graf--p graf-after--figure">The Result for the above code is:</p><figure tabindex="0" contenteditable="false" name="7ab3" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 295px; max-height: 640px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 216.9%;"></div><img class="graf-image" data-image-id="1*UwY3qIvRS7pljGWsTD9-Tw.png" data-width="295" data-height="640" src="https://cdn-images-1.medium.com/max/800/1*UwY3qIvRS7pljGWsTD9-Tw.png"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Select your&nbsp;language</figcaption></figure><figure tabindex="0" contenteditable="false" name="fa93" class="graf graf--figure graf-after--figure"><div class="aspectRatioPlaceholder is-locked" style="max-width: 295px; max-height: 640px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 216.9%;"></div><img class="graf-image" data-image-id="1*w17NE_9vCajG9_via5lUaA.png" data-width="295" data-height="640" src="https://cdn-images-1.medium.com/max/800/1*w17NE_9vCajG9_via5lUaA.png"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Check translation</figcaption></figure><p name="d243" class="graf graf--p graf-after--figure">As we have completed our UI for beautiful interaction, you can simply use the below function to complete translation and text to speech process.</p><p name="0023" class="graf graf--p graf-after--p">Complete Logic of the application: —</p><figure tabindex="0" contenteditable="false" name="b4d7" class="graf graf--figure graf--iframe graf-after--p"><div class="aspectRatioPlaceholder is-locked"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 35.699999999999996%;"></div><div class="iframeContainer">{% gist https://gist.github.com/mdshadman/ee8a41af80e2abe48bb8cd9e03e8dc38.js %}</div></div><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for embed (optional)">Logics for Translation and Text-to-Speech</figcaption></figure><p name="58e4" class="graf graf--p graf-after--figure">In the above gist, I have used a function “I18n.t()<strong class="markup--strong markup--p-strong">” </strong>to translate our texts in different languages.<br>This plugin obtains information and performs operations specific to the user’s locale, language, and timezone. Note the difference between locale and language: locale controls how numbers, dates, and times are displayed for a region, while language determines what language text appears as, independently of locale settings. Often developers use locale to set both settings, but there is no reason a user couldn’t set her language to “English” but locale to “French”, so that text is displayed in English but dates, times, etc., are displayed as they are in France. Unfortunately, most mobile platforms currently do not make a distinction between these settings.</p><p name="2585" class="graf graf--p graf-after--p">In the above example, I have called some events in the constructor to load default values like start, cancel, finish, speech rate to control these actions.</p><pre name="f306" class="graf graf--pre graf-after--p">Tts.addEventListener("tts-start", event =&gt;<br>this.setState({ ttsStatus: "started" })<br>);<br>Tts.addEventListener("tts-finish", event =&gt;<br>this.setState({ ttsStatus: "finished" })<br>);<br>Tts.addEventListener("tts-cancel", event =&gt;<br>this.setState({ ttsStatus: "cancelled" })<br>);<br>Tts.setDefaultRate(this.state.speechRate);<br>Tts.setDefaultPitch(this.state.speechPitch);<br>Tts.getInitStatus().then(this.initTts);</pre><p name="d09d" class="graf graf--p graf-after--pre">After this, we have called initTts function.</p><pre name="dc4c" class="graf graf--pre graf-after--p">initTts = async () =&gt; {<br>const voices = await Tts.voices();<br>const availableVoices = voices<br>.filter(v =&gt; !v.networkConnectionRequired &amp;&amp; !v.notInstalled)<br>.map(v =&gt; {<br>return { id: v.id, name: v.name, language: v.language };<br>});<br>let selectedVoice = null;<br>if (voices &amp;&amp; voices.length &gt; 0) {<br>selectedVoice = voices[4].id;<br>try {<br>await Tts.setDefaultLanguage(voices[0].language);<br>} catch (err) {<br>// My Samsung S9 has always this error: "Language is not supported"<br>console.log(`setDefaultLanguage error `, err);<br>}<br>await Tts.setDefaultVoice(voices[0].id);<br>this.setState({<br>voices: availableVoices,<br>selectedVoice,<br>ttsStatus: "initialized"<br>});<br>} else {<br>this.setState({ ttsStatus: "initialized" });<br>}<br>};</pre><p name="b731" class="graf graf--p graf-after--pre">We have used this function to filter available languages and voices.<br>After executing these functions we can achieve our requirement. The code view and output of the above function in my app are as: —</p><figure tabindex="0" contenteditable="false" name="839e" class="graf graf--figure is-defaultValue graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 295px; max-height: 640px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 216.9%;"></div><img class="graf-image" data-image-id="1*xL4gDZNJdjqDxoBNG429PA.png" data-width="295" data-height="640" src="https://cdn-images-1.medium.com/max/800/1*xL4gDZNJdjqDxoBNG429PA.png"><div class="crosshair u-ignoreBlock"></div></div></figure><figure tabindex="0" contenteditable="false" name="92f9" class="graf graf--figure graf-after--figure"><div class="aspectRatioPlaceholder is-locked" style="max-width: 295px; max-height: 640px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 216.9%;"></div><img class="graf-image" data-image-id="1*a-ibZv9paZhko7fufeKAJQ.png" data-width="295" data-height="640" src="https://cdn-images-1.medium.com/max/800/1*a-ibZv9paZhko7fufeKAJQ.png"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Text To speech&nbsp;View</figcaption></figure><p name="1c73" class="graf graf--p graf-after--figure">In the above image, you can type any thing in the text input field and click on the Start reading Text button to listen to the text invoice.<br>A list of available voices is on the list which you can select for speech either for male or female.<br><strong class="markup--strong markup--p-strong">To Install (additional) language data</strong></p><p name="2e26" class="graf graf--p graf-after--p">Shows the Android Activity to install additional language/voice data.</p><pre name="0ed8" class="graf graf--pre graf-after--p">Tts.requestInstallData();</pre><p name="7433" class="graf graf--p graf-after--pre">There are some methods that you can use to get features according to your requirement —</p><h3 name="8913" class="graf graf--h3 graf-after--p">Speaking</h3><p name="eb61" class="graf graf--p graf-after--h3">Add utterance to the TTS queue and start speaking. Returns promise with utteranceId.</p><pre name="913e" class="graf graf--pre graf-after--p">Tts.speak('Hello, world!');</pre><p name="0727" class="graf graf--p graf-after--pre">Additionally, speak() allows to pass platform-specific options ‘voiceId’ on IOS and ‘params’ on Android to underlying platform API:</p><pre name="70ca" class="graf graf--pre graf-after--p">Tts.speak('Hello, world!', { iosVoiceId<strong class="markup--strong markup--pre-strong">:</strong> 'com.apple.ttsbundle.Moira-compact' });<br>Tts.speak('Hello, world!', { androidParams<strong class="markup--strong markup--pre-strong">:</strong> { KEY_PARAM_PAN<strong class="markup--strong markup--pre-strong">:</strong> <strong class="markup--strong markup--pre-strong">-</strong>1, KEY_PARAM_VOLUME<strong class="markup--strong markup--pre-strong">:</strong> 0.5, KEY_PARAM_STREAM<strong class="markup--strong markup--pre-strong">:</strong> 'STREAM_MUSIC' } });</pre><p name="3b1f" class="graf graf--p graf-after--pre">For more detail on <code class="markup--code markup--p-code">androidParams</code> properties, please take a look at <a href="https://developer.android.com/reference/android/speech/tts/TextToSpeech.Engine.html"  class="markup--anchor markup--p-anchor" rel="nofollow noopener"    target="_blank">official android documentation</a>. Please note that there are still unsupported key with this wrapper library such as <code class="markup--code markup--p-code">KEY_PARAM_SESSION_ID</code>. The following are brief summarization of currently implemented keys:</p><ul class="postList"><li name="2275" class="graf graf--li graf-after--p"><code class="markup--code markup--li-code">KEY_PARAM_PAN</code> ranges from <code class="markup--code markup--li-code">-1</code> to <code class="markup--code markup--li-code">+1</code>.</li><li name="063a" class="graf graf--li graf-after--li"><code class="markup--code markup--li-code">KEY_PARAM_VOLUME</code> ranges from <code class="markup--code markup--li-code">0</code> to <code class="markup--code markup--li-code">1</code>, where 0 means silence. Note that <code class="markup--code markup--li-code">1</code> is a default value for Android.</li><li name="dd81" class="graf graf--li graf-after--li">For <code class="markup--code markup--li-code">KEY_PARAM_STREAM</code> the property, you can currently use one of <code class="markup--code markup--li-code">STREAM_ALARM</code>, <code class="markup--code markup--li-code">STREAM_DTMF</code>, <code class="markup--code markup--li-code">STREAM_MUSIC</code>, <code class="markup--code markup--li-code">STREAM_NOTIFICATION</code>, <code class="markup--code markup--li-code">STREAM_RING</code>, <code class="markup--code markup--li-code">STREAM_SYSTEM</code>, <code class="markup--code markup--li-code">STREAM_VOICE_CALL</code>,</li></ul><p name="68aa" class="graf graf--p graf-after--li">Stop speaking and flush the TTS queue.</p><pre name="f547" class="graf graf--pre graf-after--p">Tts.stop();</pre><h3 name="4166" class="graf graf--h3 graf-after--pre">Waiting for initialization</h3><p name="4332" class="graf graf--p graf-after--h3">On some platforms, it could take some time to initialize the TTS engine, and Tts.speak() will fail to speak until the engine is ready.</p><p name="c332" class="graf graf--p graf-after--p">To wait for successful initialization you could use getInitStatus() call.</p><pre name="16f6" class="graf graf--pre graf-after--p">Tts.getInitStatus().then(() =&gt; {<br>Tts.speak('Hello, world!');<br>});</pre><h3 name="d0a6" class="graf graf--h3 graf-after--pre">Ducking</h3><p name="292a" class="graf graf--p graf-after--h3">Enable lowering other applications output level while speaking (also referred to as “ducking”).</p><pre name="41f1" class="graf graf--pre graf-after--p">Tts.setDucking(true);</pre><h3 name="bd8b" class="graf graf--h3 graf-after--pre">List Voices</h3><p name="f2ae" class="graf graf--p graf-after--h3">Returns list of available voices</p><p name="ea02" class="graf graf--p graf-after--p"><em class="markup--em markup--p-em">(not supported on Android API Level &lt; 21, returns empty list)</em></p><pre name="2518" class="graf graf--pre graf-after--p">Tts.voices().then(voices =&gt; console.log(voices));<br>// Prints:<br>// [ { id: 'com.apple.ttsbundle.Moira-compact', name: 'Moira', language: 'en-IE', quality: 300 },<br>// ...<br>// { id: 'com.apple.ttsbundle.Samantha-compact', name: 'Samantha', language: 'en-US' } ]</pre><p name="55a0" class="graf graf--p graf-after--pre">Voice fieldDescriptionidUnique voice identifier (e.g. <code class="markup--code markup--p-code">com.apple.ttsbundle.Moira-compact</code>)nameName of the voice <em class="markup--em markup--p-em">(iOS only)</em>languageBCP-47 language code (e.g. 'en-US')qualityVoice quality (300 = normal, 500 = enhanced/very high)latencyExpected synthesizer latency (100 = very low, 500 = very high) <em class="markup--em markup--p-em">(Android only)</em>networkConnectionRequiredTrue when the voice requires an active network connection <em class="markup--em markup--p-em">(Android only)</em>notInstalledTrue when the voice may need to download additional data to be fully functional <em class="markup--em markup--p-em">(Android only)</em></p><h3 name="14f6" class="graf graf--h3 graf-after--p">Set default&nbsp;Language</h3><pre name="a8ab" class="graf graf--pre graf-after--h3">Tts.setDefaultLanguage('en-IE');</pre><h3 name="2cca" class="graf graf--h3 graf-after--pre">Set default&nbsp;Voice</h3><p name="0684" class="graf graf--p graf-after--h3">Sets default voice, pass one of the voiceId as reported by a call to Tts.voices()</p><p name="4db6" class="graf graf--p graf-after--p"><em class="markup--em markup--p-em">(not available on Android API Level &lt; 21)</em></p><pre name="d79f" class="graf graf--pre graf-after--p">Tts.setDefaultVoice('com.apple.ttsbundle.Moira-compact');</pre><h3 name="2aec" class="graf graf--h3 graf-after--pre">Set default Speech&nbsp;Rate</h3><p name="0b83" class="graf graf--p graf-after--h3">Sets default speech rate. The rate parameter is a float where 0.01 is a slowest rate and 0.99 is the fastest rate.</p><pre name="e169" class="graf graf--pre graf-after--p">Tts.setDefaultRate(0.6);</pre><p name="dfd7" class="graf graf--p graf-after--pre">There is a significant difference to how the rate value is interpreted by iOS and Android native TTS APIs. To provide unified cross-platform behavior, translation is applied to the rate value. However, if you want to turn off the translation, you can provide optional <code class="markup--code markup--p-code">skipTransform</code> parameter to <code class="markup--code markup--p-code">Tts.setDefaultRate()</code> to pass rate value unmodified.</p><p name="d1e2" class="graf graf--p graf-after--p">Do not translate the rate parameter:</p><pre name="221b" class="graf graf--pre graf-after--p">Tts.setDefaultRate(0.6, true);</pre><h3 name="06da" class="graf graf--h3 graf-after--pre">Set default&nbsp;Pitch</h3><p name="ade3" class="graf graf--p graf-after--h3">Sets default pitch. The pitch parameter is a float where 1.0 is a normal pitch. On iOS min, pitch is 0.5 and max pitch is 2.0</p><pre name="a203" class="graf graf--pre graf-after--p">Tts.setDefaultPitch(1.5);</pre><p name="98df" class="graf graf--p graf-after--pre">Here in the tutorial, successfully implemented the plugin and got the perfect result. <a href="https://github.com/mdshadman/RNInternationalizatio-TextToSpeech"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank"><strong class="markup--strong markup--p-strong">You can follow all the steps and achieve this very easily or you can clone my repo on Github for both the implementations here and enjoy 😎 😎 😎 🕺 🕺 🕺..…</strong></a></p><h3 name="32fb" class="graf graf--h3 graf-after--p">Conclusion</h3><p name="3058" class="graf graf--p graf-after--h3">In this post, we learned how to translate text in multi-language and text to speech and use it in React-Native applications. Since the packages are amazingly light and have great documentation, it is the developers’ first choice when it comes to creating translation app and text to speech.</p><blockquote name="4284" class="graf graf--blockquote graf-after--p"><strong class="markup--strong markup--blockquote-strong">Complete source code of this tutorial is available here&#8202;—&#8202;</strong><a href="https://github.com/mdshadman/RNInternationalizatio-TextToSpeech"  class="markup--anchor markup--blockquote-anchor" rel="noopener"    target="_blank"><strong class="markup--strong markup--blockquote-strong">RNInternationalizatio-TextToSpeech</strong></a><strong class="markup--strong markup--blockquote-strong">.</strong></blockquote><h3 name="76fd" class="graf graf--h3 graf-after--blockquote">Next Steps</h3><p name="178a" class="graf graf--p graf-after--h3">Now that you have learned the implementation of translation and text to speech in React-Native, you can also try</p><ul class="postList"><li name="771c" class="graf graf--li graf-after--p">Firebase&#8202;—&#8202;<a href="https://enappd.com/blog/intergrate-firebase-in-react-native-app/73"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Integrate Firebase</a> | <a href="https://enappd.com/blog/firebase-analytics-in-react-native-app/101"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Analytics</a> | <a href="https://enappd.com/blog/react-native-firebase-crud-image-upload-and-phone-authentication/86"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Push notifications</a> | <a href="https://enappd.com/blog/react-native-firebase-crud-image-upload-and-phone-authentication/86"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Firebase CRUD</a></li><li name="ce44" class="graf graf--li graf-after--li">How To in React Native&#8202;—&#8202;<a href="https://enappd.com/blog/geolocation-geocoding-react-native-apps/84"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Geolocation</a> | <a href="https://enappd.com/blog/react-native-life-cycle-hooks/79"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Life cycle hooks</a> | <a href="https://enappd.com/blog/pick-images-from-camera-gallery-in-react-native-app/78"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Image Picker</a> | <a href="https://enappd.com/blog/redux-in-react-native-app/92"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Redux implementation</a> | <a href="https://enappd.com/blog/how-to-make-api-calls-in-react-native-apps/125"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Make API calls</a> | <a href="https://enappd.com/blog/navigations-in-react-native-app/124"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Navigation</a> | <a href="https://enappd.com/blog/react-native-qr-code-scanning-using-react-native-camera/117"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Barcode &amp; QR code scan</a> | <a href="https://enappd.com/blog/send-read-and-delete-sms-in-react-native/107"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Send &amp; Read SMS</a> | <a href="https://enappd.com/blog/google-vision-with-react-native/96"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Google Vision</a></li><li name="e480" class="graf graf--li graf-after--li">Payments&#8202;—&#8202;<a href="https://enappd.com/blog/implement-apple-pay-in-react-native-apps/93"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Apple Pay</a> | <a href="https://enappd.com/blog/stripe-integration-in-react-native-apps-using-firebase/108"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Stripe payments</a></li><li name="4d3b" class="graf graf--li graf-after--li">Authentication&#8202;—&#8202;<a href="https://enappd.com/blog/google-login-in-react-native-android-apps-with-firebase/90"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener noopener"    target="_blank">Google Login</a>| <a href="https://enappd.com/blog/facebook-login-in-react-native-apps/89"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener noopener"    target="_blank">Facebook login</a> | <a href="https://enappd.com/blog/react-native-firebase-crud-image-upload-and-phone-authentication/86"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener noopener"    target="_blank">Phone Auth</a> | <a href="https://enappd.com/blog/twitter-login-in-react-native-apps-using-firebase/95"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Twitter login</a>| <a href="https://enappd.com/blog/anonymous-login-in-react-native-apps-with-firebase/129"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Anonymous Auth</a></li><li name="2ccd" class="graf graf--li graf-after--li"><a href="https://enappd.com/blog/how-to-make-stories-ui-like-instagram-and-whatsapp-in-react-native/123"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Create Instagram / Whatsapp Story Feature in React Native</a></li><li name="01c3" class="graf graf--li graf-after--li"><a href="https://enappd.com/blog/react-native-life-cycle-hooks/79"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">React Native life cycle hooks</a> | <a href="https://enappd.com/blog/redux-in-react-native-app/92"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Implement Redux</a> | <a href="https://enappd.com/blog/async-actions-with-redux-thunk-middleware-in-react-native-apps-1/100"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Async actions with Redux</a></li><li name="ae6c" class="graf graf--li graf-after--li"><a href="https://enappd.com/blog/guide-on-react-native-full-app/53"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener"    target="_blank">Create Awesome Apps in React Native</a> using Full App</li></ul><p name="2930" class="graf graf--p graf-after--li">If you need a base to start your next React Native app, you can make your next awesome app using <a href="https://store.enappd.com/product/react-native-full-app/"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">React Native Full App</a></p><figure tabindex="0" contenteditable="false" name="e4d4" class="graf graf--figure is-defaultValue graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 700px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 100%;"></div><img class="graf-image" data-image-id="1*sWyEeAfCMk7ULOkLUCdSug.jpeg" data-width="800" data-height="800" src="https://cdn-images-1.medium.com/max/800/1*sWyEeAfCMk7ULOkLUCdSug.jpeg"><div class="crosshair u-ignoreBlock"></div></div></figure><p name="97b1" class="graf graf--p graf--empty graf-after--figure graf--trailing"><br></p></div></div></section></div></article></main>