I'm doing a react-typescript app where I need to be able to translate the site. I'm using the i18next library. In the main page the user can change the language using a button which runs this method.
changeLang(lang:string):any{
i18next.changeLanguage(lang).then(() => {
this.props.close();
i18next.options.lng = lang;
});
}
This works great for changing the language of the main page. However when I go to the next page it goes back to the original language. I can't seem to get the whole site running on a different language.
My index.tsx file
import React from 'react';
import ReactDOM from 'react-dom';
import './styles/index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import Amplify from 'aws-amplify';
import awsmobile from "./aws-exports";
import * as enTranslations from "./locales/en"; /* This import refers to all of the texts in english */
import * as ptTranslations from "./locales/pt" /* This import refers to all of the texts in portuguese */
import {initReactI18next, I18nextProvider} from 'react-i18next'; /* Import needed for the use of the dictionary/translation */
import LanguageDetector from "i18next-browser-languagedetector"; /* Import needed for the use of the dictionary/translation */
import i18next from "i18next"; /* Import needed for the use of the dictionary/translation */
/* Configure Amplify on the client so that we can use it to interact with our backend services */
Amplify.configure(awsmobile);
/* Extract the translations */
const resources = {
en: {messages: enTranslations},
pt: {messages: ptTranslations}
};
/* Setting up the dictionary/translator */
const i18n = i18next.use(LanguageDetector).use(initReactI18next);
i18n.init({
react: {
wait: true,
},
resources: resources,
lng: 'pt', /* Main Language */
fallbackLng: 'en',
keySeparator: '.',
interpolation: {
escapeValue: false,
},
ns: ['messages'],
defaultNS: 'messages',
fallbackNS: [],
});
ReactDOM.render(
<I18nextProvider i18n={i18n}>
<App />
</I18nextProvider>,
document.getElementById('root')
);
reportWebVitals();
All the pages on my website have the following structure:
import { Component } from "react"
import { AuthProps } from "../../#types/auth" // Imports Auth props used to authenticate user
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome" /* Import needed to be able to use the custom FontAwesome font */
import { faChevronLeft } from "#fortawesome/free-solid-svg-icons" /* Import needed to get the desired font elements */
import i18next from "i18next"; /* Import needed for the use of the dictionary/translation */
import { withTranslation } from 'react-i18next'; /* Import needed for the use of the dictionary/translation */
import '../styles/views/change-password-confirm.css';
/**
* Simple page that tells our user that his password has been changed
*/
class ChangePasswordConfirmation extends Component<AuthProps> {
render() {
return (
<div className="change-password-confirm-background">
<div className="change-password-confirm-main">
<div className="change-password-confirm-container">
{/* Button used to go back to the login page */}
<FontAwesomeIcon icon={faChevronLeft}></FontAwesomeIcon>
<h1>{i18next.t('ChangePasswordConfirm.catchphrase')}</h1>
<p>{i18next.t('ChangePasswordConfirm.secondaryText')}</p>
</div>
</div>
</div>
)
}
}
export default withTranslation()(ChangePasswordConfirmation)
As you can see I use i18next.t('my-key') to get the translations and I export every component/page with "withTranslation()". So I don't know why the whole website doesn't change language. Can anyone help me?
So I think the problem here is that you're importing i18next from the library on every page. What you're supposed to do is that you export the i18n you created in your index file and import it in every other file instead of importing a new i18next for every component you have there. Also try putting the language value of the whole website in some kinda global context incase you wanna change the language in other pages. I hope this was helpful!
I was running into the same issue with i18n.changeLanguage() method. So,I end up fixing this by getting the current language that the user is using in their browser,
const getUserLanguage = () => window.navigator.userLanguage || window.navigator.language;
window.navigator.language works for most of the modern browsers but to be on the safe side adding window.navigator.userLanguage
Now get the userlanguage by calling the getUserLangauge() method. And based on that change the language.
Something like this,
i18n.use(initReactI18next).init({
resources,
lng: `${userLanguage}`,
fallbackLng: 'en',
keySeparator: false,
interpolation: {
escapeValue: false,
},
});
But the downside is that we need to refresh the page when we switch the language. Note that, in production, it is just going to check the user's browser setting and render the specific language based on that. Users are not able to switch the language(the only way to switch is to change their language setting in their browser and refresh the page)
Just putting out there as someone can have the same issue, double check your imports of locales/lang/translations.json. I had a bad copy paste that make two of my language point to the same translation file, hence it was not translating anything
Related
We are currently working on a project where,
project structure demo:
whenever i use pdf.js and pdf.css in seperate project then it works perfectly.But when i put that pdf js and css inside this project ,then the css of the projects overriding the pdf.css
is there any way to use separate css files each component?
i have tried doing modules.css ,but i have to change the existing all css for that,
please provide some suggestion
Here is a reference to React's docs. Basically you need to name your file {file_name}.module.css, where the file extension needs to end with module.css
Then you can use like this, as shown on React example:
Class based component
import React, { Component } from 'react';
import styles from './Button.module.css'; // Import css modules stylesheet as styles
import './another-stylesheet.css'; // Import regular stylesheet
class Button extends Component {
render() {
// reference as a js object
return <button className={styles.error}>Error Button</button>;
}
}
Functional base component
import React, { Component } from 'react';
import styles from './Button.module.css'; // Import css modules stylesheet as styles
import './another-stylesheet.css'; // Import regular stylesheet
const Button = () => {
return <button className={styles.error}>Error Button</button>
}
I would like to export my point map done using kepler gl to an interactive html file. This interactive html file should have a legend (colour key) visible by default. What I mean is i shouldn't click on the show legend button to see the meaning of colours on the map - the show legend should be visible and fixed by default after exporting. Is this possible? Can anyone please guide me on how to achive this?
I am not sure about html exporting thing, and I am also not sure if you mean how to do it with the demo, basically using a front-end (GUI), or by the API components.
Since I made the legend open by default using react, I'll talk about it.
/* store.js */
// some of your import
import { createStore, applyMiddleware } from "redux";
import keplerGlReducer, { uiStateUpdaters } from 'kepler.gl/reducers';
import { taskMiddleware } from "react-palm/tasks";
// rest of them
const customizedKeplerGlReducer = keplerGlReducer
.initialState({
uiState: {
mapControls: {
...uiStateUpdaters.DEFAULT_MAP_CONTROLS,
mapLegend: {
show: true,
active: false
},
/* another map controls */
//toggle3d: {
// show: true
//},
}
}
});
export default createStore(customizedKeplerGlReducer, {}, applyMiddleware(taskMiddleware));
This way your legend will be open (clicked) by default, unless this is not what you asked for.
Full example by kepler.gl
I'm looking to create a video streaming app using react-native and roll out its web version via react-native-web so I can share the codebase. Unfortunetaly I can't wrap my head around how to properly create e.g. a <video /> element when in the browser context.
This is what I currently have:
import { RTCView, /* ... some other components */ } from 'react-native-webrtc';
import { Platform } from 'react-native';
const VideoViewNative = () => {
// Some logic
return <RTCView {/* props for RTCView */};
}
const VideoViewWeb = () => {
return <video {/* props for web video */} />;
}
export default Platform.OS === 'web' ? VideoViewWeb : VideoViewNative;
While this works as expected it does not "feel" right. I think I am bypassing react-native-web here and gettings some drawbacks from that later on.
What would be the proper way to achieve what I want to achieve and why is the approach above wrong?
you can try splitting the code out into separate files. React Native will detect when a file has a .ios. or .android. or .web. extension and load the relevant platform file when required from other components.
Example:
VideoView.native.js for android and ios, also can be separate
platform-specific VideoView.ios.js and VideoView.android.js
VideoView.js for others or you can also make it VideoView.web.js
And You can then require the component as follows:
import VideoView from './VideoView';
React Native will automatically pick up the right file based on the running platform.
I am using ReactNavigation library in my react-native project and since 6 hours I am trying to navigate from one screen to others screen and have tried every possible way but I think I am not able to get the logic properly.
This is my project structure.
Here
The way I am doing it.
const AppStack = StackNavigator({ Main: Feeds });
const AuthStack = StackNavigator({ Launch: LaunchScreen, });
export default SwitchNavigator({
Auth: AuthStack,
App: AppStack
});
In my LaunchScreen.js
const SimpleTabs = TabNavigator(
{
Login: {
screen: Login,
path: ""
},
SignUp: {
screen: SignUp,
path: "doctor"
}
},
);
<SimpleTabs screenProps={{rootNavigation : this.props.navigation }}/>
But the problem is in my LaunchScreen Component there is a TabNavigator which contains my other two components Login.js and SignUp.js but the button in my Login.js doesn't navigate it to Feed.js.
When you click on the button this is performed.
signInAsync = async () => {
await AsyncStorage.setItem('userToken', 'abc');
this.props.navigation.navigate('Main');
console.log("AAAAAsSSS");
};
My LaunchScreen.js contains a TabNavigation which lets you slide between two components ie. Login.js and SignUp.js.
Now when you click on the Login button which is in Login.js component it will authenticate the user and will switch the entire LauchScreen.js component with the Feed.js component.
I am a noob to react-native.
You can use react-native-router-flux (npm install --save react-native-router-flux)
just make one Navigator.js file and define each page you wanted to navigate.
import React from 'react';
import { Router, Scene } from 'react-native-router-flux';
import LaunchScreen from '../components/LaunchScreen.js';
import Feed from '../components/Feed.js';
const Navigator = () => {
return (
<Router>
<Scene key="root">
<Scene key="lauchscreen" component={LaunchScreen} hideNavBar initial />
<Scene key="feedscreen" type="reset" hideNavBar component={Feed} />
</Scene>
</Router>
);
};
export default Navigator;
now in your App.js file add this:
import Navigator from './src/Navigator.js';
export default class App extends Component<Props> {
render() {
return (
<Navigator />
);
}
}
now in your login.js when you click on login button write this:
import { Actions } from 'react-native-router-flux';
onLoginClick() {
Actions.feedscreen();
}
Thats it.. happy coding.
If you want to navigate to Feeds.js then navigate as
this.props.navigation.navigate('App');
not as
this.props.navigation.navigate('Main');
because your
export default SwitchNavigator({
Auth: AuthStack,
App: AppStack // here is your stack of Main
});
refer example
I came across the same issue few months ago. Thank god you have spent just 6 hours, i almost spent around 4 days in finding a solution for it.
Coming to the issue, Please note that in react-navigation you can either navigate to siblings or children classes.
So here, You have a swtichNavigator which contain 2 stack navigators (say stack 1 and stack 2), stack1 has feeds and stack2 has a tab navigator with login and signup.
Now you want to navigate from login.js to feeds.js(say file name is feeds.js). As mentioned already you can not navigate back to parent or grandparent. Then how to solve this issue?
In react native you have the privilege to pass params (screenprops) from parent to children. Using this, you need to store this.props.navigation of launchScreen into a variable and pass it to tab/login (check the tree structure). Now in the login.js use this variable to navigate.
You are simply passing the navigating privilege from parent to children.
Editing here:
<InnerTab screenProps={{rootNavigation : this.props.navigation }} />
Here, InnerTab is the tab navigator.
export const InnerTab = TabNavigator({
login: {
screen: login,
},
},
signup: {
screen: signup,
},
},
},
in login class, use const { navigate } = this.props.screenProps.rootNavigation;
Now you can use variable navigate.
I know its little tricky to understand but i have tried and it works.
Write your Navigator.js file as below,
import React from 'react'
import { NavigationContainer, useNavigation } from '#react-navigation/native'
import { createStackNavigator } from '#react-navigation/stack'
const SwitchNavigatorStack = () => {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName='{nameofscreen}' screenOptions={screenOptions}>
<Stack.Screen name='{nameofscreen}' component={{nameofscreen}}/>
<Stack.Screen name='{nameofscreen}' component={{nameofscreen}}/>
<Stack.Screen name='{nameofscreen}' component={{nameofscreen}}/>
<Stack.Screen name='{nameofscreen}' component={{nameofscreen}}/>
</Stack.Navigator>
</NavigationContainer>
)
}
export default SwitchNavigatorStack
Once, you are done with that change your App.js file to,
import SignedInStack from './navigation'
import React from 'react'
export default function App() {
return <SwitchNavigatorStack/>
}
After this, you are done with setting your project for navigating. In all the components where you want to add navigation feature make sure you use the navigation.navigate() (or) navigation.push() method. Also make sure you hook navigation constant by import useNavigation library. For example,
const Login = () => {
const navigation = useNavigation()
< Button title = 'Login' onPress={() => navigation.navigate('{nameofscreen}')} />
}
with this code snippet you can implement navigation between screens using #react-navigation/native and #react-navigation/stack
I have an issue on Microsoft Edge where I have a page with a read only state for a form and a pencil edit button that just toggles a boolean in the component and that boolean is used on two divs to toggle which one is displayed using ngIf.
This works fine in chrome but not in IE. There are no errors in the console and even if I log the boolean as it is changed it logs the change.
I have seen several other posts with similar issues and it all seems to have to do with the click event going out of the angular zone for some reason.
With that being said I found out that I can do:
toggleEdit(event?): void {
if (event) {
event.preventDefault();
}
this.ngZone.run(() => {
this.isEditable = !this.isEditable;
});
}
That works on Edge and the divs toggle back and forth, BUT what I want to know is what is actually causing the click to go outside of the angular zone so that I can fix the actual issue.
Here is more of the actual code:
Personal Info Component
#Component({
selector: 'personal-info',
template: require('./personal_info.component.html'),
styles: [require('./personal_info.component.scss')]
})
export class PersonalInfoComponent implements OnInit {
isEditable: boolean = false;
ngOnInit: void {
...
}
toggleEdit(event?): void {
if (event) {
event.preventDefault();
}
this.isEditable = !this.isEditable;
}
}
Personal Info HTML
<div class='read-only container' *ngIf='!isEditable'>
<h2>Personal Information <a href (click)='toggleEdit($event)'><img class='pencil' src='/images/legal-purple.png'/></a></h2>
...
</div>
<div class='editable container' *ngIf='isEditable'>
...
</div>
Profile Component HTML
<h1>Your Profile</h1>
<personal-info></personal-info>
I am using angular at version 4.1.3 and zone at 0.8.10.
These are the current shims we are using:
import 'core-js/es6/symbol';
import 'core-js/es6/object';
import 'core-js/es6/function';
import 'core-js/es6/parse-int';
import 'core-js/es6/parse-float';
import 'core-js/es6/promise';
import 'core-js/es6/number';
import 'core-js/es6/math';
import 'core-js/es6/string';
import 'core-js/es6/date';
import 'core-js/es6/array';
import 'core-js/es6/regexp';
import 'core-js/es6/map';
import 'core-js/es6/set';
import 'core-js/es6/weak-map';
import 'core-js/es6/weak-set';
import 'core-js/es6/typed';
import 'core-js/es6/reflect';
import 'core-js/es7/reflect';
import 'zone.js/dist/zone';
import 'ts-helpers';