Developing an admin that has no need for translations. Is there a way to turn them off completely. As it is now, for things like doing notifications, they display but I also get a console warning about missing key for translation.
In addition to Frederik's answer, here's the right way to disable the 'missing translations' warnings on react-admin:
import polyglotI18nProvider from 'ra-i18n-polyglot'; // install the package
import englishMessages from 'ra-language-english'; // install the package
const App = () => {
const i18nProvider = polyglotI18nProvider(() => englishMessages, 'en', { allowMissing: true });
return (
<Admin i18nProvider={i18nProvider}
...
/>
)
}
Solved it by adding a custom i18nProvider that allows missing keys:
const i18nProvider = polyglotI18nProvider(locale => i18nMessages[locale], 'en', { allowMissing: true });
<Admin
i18nProvider={i18nProvider}
...
/>
More details: https://marmelab.com/react-admin/Translation.html
and: https://www.npmjs.com/package/node-polyglot#options-overview
Related
I'm trying to integrate storyblok's preview/live editing features in my Shopify Hydrogen app. There's isn't any documentation on how to do this in Hydrogen, so I've been using a combination of the react-specific documentation and nextjs-specific documentation to try to figure it out.
I have everything configured correctly in Storyblok (I built a simple nextjs app and can get the preview/live editing features working correctly there.) But I can't figure out how to get the StoryblokComponent working in my Hydrogen app.
Here's what I'm doing:
I've put the storyblokInit function in App.server.jsx and that part seems to be working (I think).
import { storyblokInit, apiPlugin } from '#storyblok/react';
import { Page } from './components/storyblok/Page.client';
import { Teaser } from './components/storyblok/Teaser.client';
const storyblokComponents = {
page: Page,
teaser: Teaser
}
storyblokInit({
accessToken: 'xxxxxxx',
use: [apiPlugin],
storyblokComponents
});
I'm fetching my Storyblok data using hydrogen's fetchSync. This is working as expected.
export function getStoryblokData(slug) {
if (isServer()) {
const storyblokData = fetchSync(
'https://api.storyblok.com/v2/cdn/stories/' + slug + '?token=' + storyblokToken,
{
preload: true,
cache: CacheLong(),
}
).json();
log.debug('storyblok data from slug: /' + slug, storyblokData);
return storyblokData;
}
}
I've built the Page and Teaser components pretty much just copy/pasting from the tutorials.
import { storyblokEditable, StoryblokComponent } from "#storyblok/react";
function Page({ blok }) {
return (
<main {...storyblokEditable(blok)}>
{blok.body.map((nestedBlok) => (
<StoryblokComponent blok={nestedBlok} key={nestedBlok._uid} />
))}
</main>
);
}
export default Page;
import { storyblokEditable } from "#storyblok/react";
const Teaser = ({ blok }) => {
return <h2 style={{textAlign: 'center'}}
{...storyblokEditable(blok)} >{blok.headline}</h2>;
};
export default Teaser;
Then in index.server.jsx I'm trying to use StoryblokComponent from storyblok/react
import {
StoryblokComponent,
} from "#storyblok/react";
let storyblokData = getStoryblokData('home');
return (
<>
<StoryblokComponent blok={storyblokData.story.content} />
</>
);
}
This, as far as I can tell, is where things go wrong. My app breaks and I get this error message:
Error processing route: http://localhost:3000/
TypeError: Cannot read properties of undefined (reading 'page')
at q (/Users/jbaudreau/Desktop/DEMO/hydrogen-storyblok-demo/node_modules/#storyblok/react/dist/storyblok-react.js:7:1033)
at ce (/Users/jbaudreau/Desktop/DEMO/hydrogen-storyblok-demo/node_modules/#storyblok/react/dist/storyblok-react.js:7:429)
at attemptResolveElement (/node_modules/#shopify/hydrogen/vendor/react-server-dom-vite/esm/react-server-dom-vite-writer.browser.server.js?v=32cf2471:1060:12)
at resolveModelToJSON (/node_modules/#shopify/hydrogen/vendor/react-server-dom-vite/esm/react-server-dom-vite-writer.browser.server.js?v=32cf2471:1377:21)
at Array.toJSON (/node_modules/#shopify/hydrogen/vendor/react-server-dom-vite/esm/react-server-dom-vite-writer.browser.server.js?v=32cf2471:1029:14)
at stringify (<anonymous>)
at processModelChunk (/node_modules/#shopify/hydrogen/vendor/react-server-dom-vite/esm/react-server-dom-vite-writer.browser.server.js?v=32cf2471:164:14)
at retryTask (/node_modules/#shopify/hydrogen/vendor/react-server-dom-vite/esm/react-server-dom-vite-writer.browser.server.js?v=32cf2471:1625:26)
at performWork (/node_modules/#shopify/hydrogen/vendor/react-server-dom-vite/esm/react-server-dom-vite-writer.browser.server.js?v=32cf2471:1658:7)
at eval (/node_modules/#shopify/hydrogen/vendor/react-server-dom-vite/esm/react-server-dom-vite-writer.browser.server.js?v=32cf2471:1139:14)
at scheduleWork (/node_modules/#shopify/hydrogen/vendor/react-server-dom-vite/esm/react-server-dom-vite-writer.browser.server.js?v=32cf2471:58:3)
at pingTask (/node_modules/#shopify/hydrogen/vendor/react-server-dom-vite/esm/react-server-dom-vite-writer.browser.server.js?v=32cf2471:1138:5)
at ping (/node_modules/#shopify/hydrogen/vendor/react-server-dom-vite/esm/react-server-dom-vite-writer.browser.server.js?v=32cf2471:1152:14)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
If anyone can help me figure this out, I'd really appreciate it!
I have been following the tinder 2.0 react native tutorial https://youtu.be/qJaFIGjyRms At 1:04:00 he sets the sign in method to: "await Google.logInAsync()" but I have noticed the google app auth library used in the video is now deprecated, I am redirected to use expo auth session instead but I notice there is a slight difference, where they used "await Google.logInAsync()" I must put "promptAsync" instead, when I do this I get the error promptAsync is undefined, I try with google.loginasync and get the same error that it is still undefined, what should I do? screenshot
code:
import React, { createContext, useContext } from 'react'
//import * as Google from 'expo-auth-session/providers/google';
import * as Google from 'expo-google-app-auth';
const AuthContext = createContext({});
const config = {
androidClientId:
'236293699216-9a0nknjdq7ie79h40iubg0tddokgogfv.apps.googleusercontent.com',
iosClientId:
'236293699216-6jdpm0rd6kn5d0qlbh1vgva5afgbqgib.apps.googleusercontent.com',
scopes: ["profile", "email"],
permissions: ["public_profile","email", "gender", "location"],
}
export const AuthProvider = ({ children}) => {
const signInWithGoogle = async() => {
await Google.logInAsync(config).then(async (logInResult) => {
if (logInResult.type === "success") {
// login
}
});
};
return (
<AuthContext.Provider
value={{
user: null,
signInWithGoogle
}}
>
{children}
</AuthContext.Provider>
)
}
export default function useAuth() {
return useContext(AuthContext);
}
I sought help on the forum that belongs to the maker of the video and other people had come across the same issue, one person recommended to go into package.json find the installed dependencies and change “expo-google-app-auth” from “^10.0.0” to “~9.0.0” and then npm I in the terminal, I have done this and I'm now getting the error “no such file or directory /Users/shangefagan/twinder-3/node_modules/expo-google-app-auth/node-modules/react-native/package.json” I have changed it back to “^10.0.0” but still getting the same error, screenshot
do I just npm uninstall expo-google-app-auth and try to use expo-auth-session as I was originally trying? if so What is the correct way to use promptAsync from the expo-auth-session library
I check the docs for both libraries, expo google app auth: https://docs.expo.dev/versions/v43.0.0/sdk/google/ and expo auth session: https://docs.expo.dev/versions/latest/sdk/auth-session/ but I am unsure exactly how to use the new login method "promptAsync"
To use promptAsync you have to use the package expo-auth-session. Like you said expo-google-app-auth is deprecated.
Currently my react native app allow language switching by user (have a language selection screen in the app for user to switch) with react-native-localization. What i did is use redux-persist to store the selected language. But that requires an app restart to take effect.
However, we have a business requirement to switch the language on the fly. Anyone have successfully implement it before?
import LocalizedStrings from 'react-native-localization';
export default new LocalizedStrings({
en: {
},
de: {
},
});
In my main navigator:
componentDidMount() {
const language = store.getState().language;
if (language.code) {
LocalizedStrings.setLanguage(language.code);
} else {
LocalizedStrings.setLanguage('en');
}
}
Anyone have successfully implemented in such a way that an app restart is not required?
When language got update, you just need to update key of the root component to force all child component re-render.
In my case, I am using react-navigation, whenever language changed. I update screenProps
export default () => {
const language = useSelector((state: AppState) => state.preferences.language);
return (
<AppContainer
screenProps={{ language }}
...
/>
);
};
In RN my bilingual app (English - Arabic), I have used I18nManager (views) and I18n (for translations)
When I am changing app language to Arabic, the whole app gets reloaded again from the splash-screen using this code:
I18nManager.forceRTL(true)
Ideally, it should not restart the app from start and it should continue with the current screen with Arabic data.
Currently, it is not happening, only translation elements are getting converted using I18n.t('keyword') but for views Arabic alignment, it's not proper.
Still looking for a better solution, let me know if anyone achieved it.
Thanks
Sopo !!
you should put this code in the top component in your project
import RNRestart from "react-native-restart";
I18nManager.forceRTL(true);
if (!I18nManager.isRTL) RNRestart.Restart();
If you guys wants to store stack state after reloading(because there is no other option without reloading) and want stack state back you can follow this link also you can check my code.
Link: React navigation state persist
Any Component
AsyncStorage.setItem('navigation_state', JSON.stringify(navigation.dangerouslyGetState()));
My App.js
const App = () => {
const [initialState, setInitialState] = useState();
const [isReady, setIsReady] = useState(false);
useEffect(() => {
restoreState();
}, []);
const restoreState = async () => {
try {
const savedStateString = await AsyncStorage.getItem('navigation_state');
const state = savedStateString ? JSON.parse(savedStateString) : undefined;
if (state !== undefined) {
AsyncStorage.removeItem('navigation_state');
setInitialState(state);
}
} finally {
setIsReady(true);
}
};
if (!isReady) {
return null;
}
return (
<Provider store={store}>
<NavigationContainer
initialState={initialState}
ref={rootNavigationRef}>
<Root>
<AppNavigator />
</Root>
</NavigationContainer>
</Provider>
);
};
I working on a project which has two languages, Arabic and English.i use redux for handling app language. I put all styles on redux and handle app style with redux. and when user change language all styles on my app change to that language . also all text handled with redux too. with this way, my app does not reload and app language changed immediately.
If your app is an android hybrid app, you can try this:
import com.facebook.react.modules.i18nmanager.I18nUtil;
I18nUtil i18nUtil = I18nUtil.getInstance();
i18nUtil.forceRTL(context, forceRtl);
i18nUtil.allowRTL(context, true);
value 'forceRtl' is a boolean.
for iOS,I think you can find the same method.
In Expo use
import {Updates} from "expo"
Updates.reload()
I'm trying to write some tests for a React app I've been working on, and I figured I would use Jest since it's mentioned in the React docs.
I'm using Webpack and so far I've installed jest-cli, babel-jest, and I included the following configuration in package.json:
"jest": {
"scriptPreprocessor": "./node_modules/babel-jest",
"unmockedModulePathPatterns": [
"./node_modules/react",
"./node_modules/react-dom"
],
}
So, I'm writing the tests for some file foo.js. This file includes some other module bar.js (i.e. const bar = require('./bar');). Unfortunately, when I run jest I get the following error:
SyntaxError: Block-scoped declarations (let, const, function, class) not yet
supported outside strict mode in file 'js/foo.js'.
So, after some research, I find out I have to include 'use strict'; at the top of foo-test.js. However, for some reason, I still get the same error unless I also include 'use strict'; at the top of foo.js.
So my question is: am I doing something wrong? If not, is there anyway for me to write my tests using Jest without having to write 'use strict'; at the top of all my source files?
It seems to test out basic ES2015 classes with jest, use strict is required, however to test React Components, 'use strict' isn't required. Here's an example
//CheckboxWithLabel.js
import React, {Component} from 'react';
class CheckboxWithLabel extends Component {
constructor(){
super(...arguments);
this.state = {
isChecked: false
};
this.onChange = this.onChange.bind(this);
}
onChange() {
this.setState({
isChecked: !this.state.isChecked
});
}
render() {
return (
<label>
<input type="checkbox"
checked={this.state.isChecked}
onChange={this.onChange} />
{this.state.isChecked ? this.props.labelOn : this.props.labelOff }
</label>
);
}
}
export default CheckboxWithLabel;
//CheckboxWithLabel_tests.js
jest.disableAutomock(); //use this instead of jest.autoMockOff()
import React from 'react';
import ReactDOM from 'react-dom';
import TestUtils from 'react-addons-test-utils';
import CheckboxWithLabel from '../source/components/CheckboxWithlabel';
// const CheckboxWithLabel = require('../source/components/CheckboxWithLabel');
describe('CheckboxWithlabel', () => {
const shallowRenderer = TestUtils.createRenderer();
//render a checkbox
const checkbox = TestUtils.renderIntoDocument(
<CheckboxWithLabel labelOn="On" labelOff="Off" />
);
// shallowRenderer.render(<CheckboxWithLabel labelOn="On" labelOff="Off" />)
// const checkbox = shallowRenderer.getRenderOutput();
// it('defaults to unchecked and off label', () => {
// const inputField = checkbox.props.children[0];
// const textNode = checkbox.props.children[1];
// expect(inputField.props.checked).toBe(false);
// expect(textNode).toEqual('Off');
// })
var checkboxNode = ReactDOM.findDOMNode(checkbox);
// let checkboxElement = TestUtils.findRenderedDOMComponentWithTag(checkbox, 'input');
it('defaults to Off label', () => {
expect(checkboxNode.textContent).toEqual('Off');
// expect(checkboxElement.checked).toBe(false);
});
})
Edited: This is not required anymore
Notice the only caveat being that you have to explicitly add a auto_mock_off.js file that simply adds this line (it took me hours to figure this one out)
jest.autoMockOff();
More information can be found on this thread on github Github React Issue #932
That's it! the component testing works perfectly. I've also tried the same example with shallow rendering and it worked perfectly too! Hope this helps!