Use statically generates messages in React Intl - reactjs

I have an object that contains content for a page, I import it and try to use it like you'd use any object variable:
import {Variable} from 'data'
const message = defineMessages({
message: {
id: 'component.title',
defaultMessage: Variable.title
}
})
However, I get React Intl] Messages must be statically evaluate-able for extraction.. I googled a lot and found no solution to this. I'm using babel-plugin-react-intl to generate the locale files, and a contributor said that Babel can only parse simple statically messages
It's hard to believe there's no way to be able to import content from another file and have it translated. There must be a way, I couldn't come up with a solution and help would be appreciated.

I struggled with the same problem by myself. As far as I know, there's no way to translate a content of a variable in react-intl.
If you're interested in alternative solutions, I wrote jsLingui i18n library and recently just added support for noop translations, which is exactly what you're looking for.

Related

Is there a way to "dynamically" load json files into my component based on a condition?

Let's say I have a couple translation files like so:
import English from "./lang/compiled-en.json";
import Spanish from "./lang/compiled-es.json";
and so on for all the languages we plan to support. These are imported directly into the component they are used, and our app as a whole is split into chunks with webpack that may contain many components and thus, many strings.
It would be ideal to only be importing the languages.json file I need depending on the user's locale, and not import all of them while having to check the locale and using only one.
I tried a super naive stab at it here, but it certainly does it work:
Helper function existing in another directory:
export async function loadLocaleData(locale: string, path: string ) {
switch (locale) {
case "en-US":
return await import(path + "/lang/en-compiled.json");
case "pt-BR":
return await import(path + "/lang/pt-br-compiled.json");
default:
return await import(path + "/lang/en-compiled/en.json");
}
}
I was thinking that importing this helper function into my components that need translations would look in their own directory for the translation file. But even when I have that path hardcoded to specify exactly where the translation file is, I still get errors.
The above may be implemented into a component like so:
const localeContext = useContext(LocaleContext);
const messages = loadLocaleData(
localeContext.locale,
"packages/components/Preferences/Billing"
);
And then I'd ideally pass just that message into my IntlProvider that wraps this individual component.
This definitely isn't working. Is there a way to make it work? I know what I want to do, I'm just not sure how possible it is.
You can use dynamic imports like you are trying, but you need to use absolute paths. Otherwise your bundler (Webpack) won't actually know where to find them.
Alternatively, store your language files in your public/ directory and use the public path to it. Webpack won't touch those files (besides index.html) and might be your best option here.

Using gatsby-source-graphcms with gatsby-plugin-react-i18next: GraphCMS_Locale variable type issue

I've run into an challenge/posible incompatibility between gatsby-source-graphcms and gatsby-plugin-react-i18next, for which there appears to be virtually no information online and I'm wondering if anyone else has encountered this before please.
I'm working on adding localisation to a site which uses gatsby-source-graphcms and the Gatsby File System Route API to build pages dynamically. Everything was going fine, until I tried to use the $language GraphQL query variable made available by gatsby-plugin-react-i18next with the locale filter field in GraphCMS, which yielded this error message:
Variable "$language" of type "String!" used in position expecting type "GraphCMS_Locale"
The one and only reference I've been able to find to a similar issue was on GraphCMS' public Slack, where someone referred to abandoning gatsby-source-graphcms I favour of gatsby-source-graphql due to this. However I'm hesitant to do this, as that would basically means re-writing the entire site for me! 😢
I've been trying to find some way to feed the page query a second variable, which duplicates the value $language variable from gatsby-plugin-react-i18next but is declared as the correct data type for GraphCMS, or perhaps to somehow cast the string to GraphCMS_locale but have had no luck so far.
Has anyone found a way to make gatsby-source-graphcms play nicely with gatsby-plugin-react-i18next please?
The WIP code for this can be seen here: https://github.com/binghamchris/paddelbuch/blob/feature-i18n/src/pages/index.js
Apologies if the code is a bit bad somewhere. I'm not a web dev (this is a community project I'm volunteering on, where there's no professional web devs) and am really just hacking away on copy-and-paste code 😉
Thanks in advance for any help anyone can offer
I found a super hacky workaround, inspired by #notrab's kind help, in case it helps anyone else:
I added the following to gatsby-node.js:
exports.createSchemaCustomization = ({
actions: { createTypes, printTypeDefinitions }
}) => {
createTypes(`
type Locale implements Node {
language: GraphCMS_Locale
}
`);
};
This changes the GraphQL data type on the language field in the i18next translation data to GraphCMS_Locale, which then means both data types needed by both gatsby-plugin-react-i18next and gatsby-source-graphcms match... and so far it seems to be working in dev mode!

createRef<View>() giving error react-native

I'm trying to implement drag and drop using this tutorial. In this tutorial i have to create a refs like this list = createRef<RecyclerListView<any, any>>() (line no 55), which is giving me syntex error: unexpected token. What i understand is that, they are using .tsx extension (don't know what for) but i'm using .js extension, which maybe the reason why this code not working in my end, and not finding any solution of that. Can anyone help me out on that? Thank you
.tsx extension is for Typescript files. Javascript is not a typed language. To put it simply, Typescript was built to make Javascript look like a typed language. Whatever you put in <> after createRef, specifies the type of the ref that is being created and you can only use types in Typescript files (.ts and .tsx). If you want to move to Typescript, you'll have to do some setup and change your file extensions to .tsx. Otherwise, if you'd like to stay on .js, just ignore the types in the tutorial and instead write list = createRef().

Liferay 7.1 npm-react-module localization

I'm trying to include localization into my npm-react-module, but I have failed receiving the value for the corresponding key from the Langugage.properties file. It simply returns the key. I did some research but I couldn't find any source that would help me solve my problem.
In the code which I will show you bellow, I have included a Language.properties file into my module. In my portlet, I have included the needed configuration for the language properties. I have also tried to add a separate file for a specific locale, but that didn't help me either.
This is an example of my portlet configuration:
"javax.portlet.resource-bundle=content.Language"
This is an example content from my Language.properties file:
example-key=example-value
This is how I'm trying to access the value in my React Component:
<h1> {Liferay.Language.get('example-key')} </h1>
But it only returns "example-key" instead of "example-value".
In my view.jsp file I am able to retrieve the corresponding values using
<liferay-ui:message key='example-key'/>
I have tried this method: https://portal.liferay.dev/docs/7-1/tutorials/-/knowledge_base/t/localizing-your-portlet but it didn't work either. Did anyone get this to work properly in their npm-react-module? I really don't want to spend time implementing my own localization service. Thanks!
Liferay.Language.get('key') gets text replaced by the build mechanism. Therefore there is no actual object/class to do this. I have been trying to get this to work myself and have resolved that I will have to do internationalization on my own.
localizing is done only in build time meaning if you have a language
key that generated dynamicly , you can't localizate it or for example
if you get a key from api fetch and need to localizate it, you can't
beacuse Liferay localization method for react (
Liferay.Language.get("yourLanguageKey") ) its undefined in runtime and
you can't use it.
from: https://npm.io/package/liferay-react-runtime-localization

Hardcoded strings/static contents in React/Redux app

I am optimizing a react/redux app and I wondered if there is the best practice to store and render hardcoded strings in such an app? Some of my components are using the same text and if there is a text change I will have to search all for all text occurrences. Would be better to have central location. I mean some static contents that y you do not want to put into state.
I would store all texts in a json object but I assume there must be a better way.
could anyone share his/her experience? any helpful tools or packages?
thank a lot for your answers!
Nothing special here really regarding react or redux, you could just create a constants file...
export const VAR_NAME = "this is some text";
export const ANOTHER_VAR = "something else";
then when you want to use, simply:
import { ANOTHER_VAR } from 'path/to/constants/file';
thank you for comments. In case, someone looks for nice solution this is - https://github.com/yahoo/react-intl
Requires some setup though but does what I wanted through making first steps towards internalization of the app.

Resources