I want to translate the complete app into any other language without using JSON files like ar.json, en.json like it is possible in Websites by using google translate.
I want to know it is possible in React Native somehow. If possible then how can we translate the whole app language in any other language without Prepare language JSON files like we can do in Websites.
I'm new to react native development and want to know this. I searched a lot for this but could not found helpful.
Thanks
There is no such way for auto translating the app without exclusively make language files (JSON). React i18Next is a really good library for it.
I suggest you not to use a library but a simple context provider would do.
import React from 'react';
const lang = {
// in this way, you could dynamically add lang
// later on which worrying about if-elses in your component
en: {
hello: 'hello'
},
fr: {
hello: 'bonjour',
},
}
const langDict = (key) => lang[key]
const LanguageContext = React.createContext(null);
function LanguageProvider({ initialState = 'en', children }) {
const [lang, setLang] = React.useState(initialState);
return (
<LanguageContext.Provider value={[langDict(lang), setLang]}>
{children}
</LanguageContext.Provider>
)
}
function useLanguage() {
return React.useContext(LanguageContext);
}
export default function AppWrapper() {
return (
<LanguageProvider>
<App />
</LanguageProvider>
)
}
function App() {
const [lang, setLang] = useLanguage();
return (
<View>
<Text>{lang.hello}</Text>
<Button onPress={() => setLang('fr')}>French</Button>
<Button onPress={() => setLang('en')}>English</Button>
</VIew>
)
}
Great question. The answers depend on what type of translation you’re talking about. Is this free flowing, conversational text that’s variable? If so, the translations will be variable and may not say what you want it to say. Or, if this is just a series of app labels, help info, or context info? If so, you’ll likely be better off doing just switching either separate files or json switches as others have stated. More clarification is needed.
Related
I'm relatively new to puppeteer and I'm trying to understand the patterns that can be used to build more complex apis with it. I am building a cli where I am running a WebGL app in puppeteer which i call various functions in, and with my current implementation i have to copy and paste a lot of setup code.
Usually, in every cli command i have to setup pupeteer, setup the app and get access to its api object, and then run an arbitrary command on that api, and get the data back in node.
It looks something like this.
const {page, browser} = await createBrowser() // Here i setup the browser and add some script tags.
let data;
page.exposeFunction('extractData', (data) => {
data = data;
})
await page.evaluate(async (input) => {
// Setup work
const requestEvent = new CustomEvent('requestAppApi', {
api: undefined;
})
window.dispatchEvent(requestEvent);
const api = requestEvent.detail.api;
// Then i call some arbitrary function, that will
always return some data that gets extracted by the exposed function.
const data = api.arbitraryFunction(input);
window.extractData(data)
}, input)
What i would like is to wrap all of the setup code in a function, so that i could call it and just specify what to do with the api object once i have it.
My initial idea was to have a function that will take a callback that has this api object as a parameter.
const { page, browser } = wait createBrowser();
page.exposeFunction(async (input) =>
setupApiObject(((api) =>
api.callSomeFunction(input)
), input)
However, this does not work. I understand that puppeteer requires any communication between the node context and the browser to be serialised as json, and obviously a function cant be. Whats tripping me up is that I'm not actually wanting to call these methods in the node context, just have a way to reuse them. The actual data transfer is already handled by page.exposeFunction.
How would a more experienced puppeteer dev accomplish this?
I'll answer my own question here, since i managed to figure out a way to do it. Basically, you can use page.evaluate to create a function on the window object that can later be reused.
So i did something like
await page.evaluate(() => {
window.useApiObject = function(callback: (api) => void){
// Perform setup code
callback()
}
})
Meaning that later on i could use that method in the browser context and avoid redoing the setup code.
page.evaluate(() => {
window.useApiObject((api) => {
api.someMethod()
})
})
after some google searched,
I am doing this in plugins/callApi.js
import axios from 'axios';
import Vue from 'vue';
Vue.use(callApi);
export default async (apiUrl, postData, headers = {}) => {
let msg = await axios.post(https://my-api-location.com' + apiUrl,postData);
return msg.data;
};
then set in nuxt.config.js
plugins: [
'~plugins/callApi.js']
when I want to use it
const msgData = await callApi('/api/news/getNewsList', postData);
if (msgData.response === 'success') { .......
but when I start yarn dev, it hightlight "Vue.use(callApi);" part and says "callApi is not defined"
how cant I fix it? thanks a lot :)
I actually re-read your answer because I was a little confused.
So, in your callApi.js, you define what you want there, but you are calling Vue.use(callApi) in the file where you are actually defining what callApi will be.
At the moment the compiler goes to Vue.use(callApi), this variable "callApi" is not defined yet (because it will only be available after it finishes compiling this very file).
So just do the
import axios from 'axios';
import Vue from 'vue';
export default async (apiUrl, postData, headers = {}) => {
let msg = await axios.post(https://my-api-location.com' + apiUrl,postData);
return msg.data;
};
then, by setting the plugin path on the plugins property in the nuxt.config file (exactly the way you did), the very callApi file will be automatically called (try to put a console log in your callApi file, and you'll see it logging when you start your application).
An example of what you want:
https://codesandbox.io/s/nuxt-app-demovue-ssr-forked-s94rz?file=/pages/index.vue
Now in your plugin, you have to decide exactly what you want to do. you might want to expose the function or make it globally available, that's up to you!
For this last option, you might want to take a look here:
Vue/Nuxt: How to define a global method accessible to all components?
Good luck!
I am quite new to React Native and JS and have recently purchased a React Native template which has a Dummy DB.
Ideally Id like it to pull data from an external JSON (api) which is being generated from a PHP website we already have running.
Here is the Dummy data file:
import {
DoctorModel,
TreatmentModel,
CampaignModel,
EventModel
} from "../models";
export const doctorsList: DoctorModel[] = [ { ##JSON HERE## } ];
export const treatmentsList: TreatmentModel[] = [ { ##JSON HERE## } ];
export const campaignList: CampaignModel[] = [ { ##JSON HERE## } ];
export const eventList: EventModel[] = [ { ##JSON HERE## } ];
I want it to export as the same values as above so it will work seamlessly with the current app configuration.
I have tried the following...
export const doctorsList: DoctorModel[] = () =>
fetch(' ##LINK TO API## ')
.then((response) => response.json());
But got this error:
Type '() => Promise<any>' is missing the following properties from type 'DoctorModel[]': pop, push, concat, join, and 27 more.
I have looked all over here and other platforms for a solution but cant find anything.
Again the ideal outcome would for it to work exactly how it would if I manually typed the JSON in as seen in the first code snippet.
Any help is much appreciated, still trying to wrap my head around React! :)
This doesn’t look like a react problem, but a typescript one. Typescript does a type inference from your return value to check and see if it matches what you’ve stated.
In short: you’ve just declared your types wrong.
The function doesn’t return a DoctorModel[] it’s returning Promise<DoctorModel[]>
export const doctorsList: Promise<DoctorModel[]> = () =>
fetch(' ##LINK TO API## ')
.then((response) => response.json() as DoctorsModel[]);
So changing that line ought to make your typescript compiler chooch again!
I am new to node.js and react but I love gatsby.js. I have followed all the tutorials that I can find and it's such a great tool.
However one of the main reasons why I want to use it is I have a file json with 1000 different records in and I would like to generate a new page for each record.
I believe I have come to the conclusion that I need to learn more about the gatsby-node.js file and am aware of the following resource but are there any tutorials or other examples on this topic that maybe a little easier to follow:
https://www.gatsbyjs.org/docs/creating-and-modifying-pages/#creating-pages-in-gatsby-nodejs
The example you were referring to should already give you a good idea. The basic concept is to import the JSON file, loop over it and run createPage for each of the items in your JSON source. So given an example source file like:
pages.json
[{
"page": "name-1"
}, {
"page": "name-2"
}]
You can then use the Node API to create pages for each:
gatsby-node.js
const path = require('path');
const data = require('./pages.json');
exports.createPages = ({ boundActionCreators }) => {
const { createPage } = boundActionCreators;
// Your component that should be rendered for every item in JSON.
const template = path.resolve(`src/template.js`);
// Create pages for each JSON entry.
data.forEach(({ page }) => {
const path = page;
createPage({
path,
component: template,
// Send additional data to page from JSON (or query inside template)
context: {
path
}
});
});
};
I'm working on my first complicated React app and I am making a request to a movie API. My site allows the user to do a search in a searchbar for whatever movie, show, actor, etc... that they are searching for. I'm pulling the user's search query and inserting it into an api request like this:
export const getDetails = (id) => {
return new Promise(function(resolve, reject) {
axios.get(`https://api.themoviedb.org/3/movie/` + id +`?api_key=&language=en-US`)
.then(function(response) {
resolve(response)
})
.catch(function(error) {
reject(error)
})
})
}
I'm able to get the data like this and console.log it:
import React, { Component } from 'react';
import Header from '../header';
import {Link} from 'react-router-dom';
import axios from 'axios';
import Footer from '../Footer.js';
import Searchbar from '../header/searchbar.js';
import List from '../results/list';
import {getDetails} from '../api/getDetails';
class Detail extends Component {
constructor(props) {
super(props);
this.state = {
id: this.props.match.params.id,
result: null,
error: false,
}
}
componentWillMount() {
getDetails(this.state.id).then(function(response){
this.setState({result: response});
console.log(response.data.original_title);
console.log(response.data.homepage);
console.log(response.data.popularity);
console.log(response.data.release_data);
console.log(response.data.overview);
}.bind(this)).catch(function(err) {
this.setState({
result:"There was a problem loading the results. Please try again.",
error: true
})
}.bind(this))
}
render() {
return(
<div>
<Header/>
<div className="details-container">
<h2>Details: </h2>
</div>
</div>
)
}
}
export default Detail
Console.logging it in the componentWillMount function successfully logs the data but I am not able to access the data in the render function via something like {response.data.orginal_title). How would I render the data being logged in componentWillMount?
TLDR; You can access your state variables from within your render function via this.state. Something like: console.log(this.state.result.data.origin_title) outside of the jsx and {this.state.response.data.orginal_title} inside the jsx.
P.S. You are using the correct this.
The following are picky recommendations and explanations, feel free to disregard.
It's recommended to make requests for data in componentDidMount. That can be read here in the docs for componentDidMount.
You're using arrow functions already in your get details function, if you convert the rest of your functions to arrow functions you no longer have to explicitly bind this to each one; it's automatically set be the this of it's parent. See the "No Separate This" section in the MDN docs
If you don't need any of the header information I would save response.data into your state so you don't have to type as much when you want to access the data. this.state.result.original_title vs this.state.result.data.original_title. That's just me and I'm lazy.
axios does return a promise like Eric said so you don't actually need to wrap it in the extra promise. You can just straight up return it and since arrow functions automatically return one line expressions you can spiff that up into a one liner:
export const getDetails = id => axios.get(`https://api.themoviedb.org/3/movie/${id}?api_key=&language=en-US`)
Finally you should be able to access the data you've stored in your state from your render function as mentioned in #3 above. Outside of the JSX you can console.log it like normal console.log(this.state.result), inside your JSX, however, you will need to make sure you escape with {} like: <div>{this.result.original_title}</div>
Small working example here: https://codesandbox.io/s/zqz6vpmrw3
You can simply use
{this.state.result}
inside the render.