Reading from JSON - json

I'm trying to read my i18n-strings from a JSON file following this guide.
I have en-US.json:
{
"world": "the world!"
}
And for setting up my Vue app I use:
import { createI18n } from 'vue-i18n'
import enUS from '../src/i18n/en-US.json'
// Type-define 'en-US' as the master schema for the resource
type MessageSchema = typeof enUS
const i18n = createI18n<[MessageSchema], 'en-US'>({
locale: 'en-US',
messages: {
'en-US': enUS
}
})
This works. But as soon as I add one non-ASCII char (e.g. "world": "the w#rld!"), I get the following error message:
[plugin:vite-plugin-vue-i18n] Cannot read properties of undefined (reading 'message')
/home/bernhard/wd/quasar2-project/src/i18n/en-US.json
Strangely, this works when I do the following straight in my .ts file:
const enUS = {
"world": "the w#rld!"
}
so maybe something wrong with the way the JSON is processed?

The answer has two layers.
As #jonrsharpe pointed out, there is a set of special characters: { } # $ | - i.e. for inserting variables. A # should i.e. be replaced by {'#'}.
A bug in how vite processes external json as described on this bug on Github. By default, quasar is using "#intlify/vite-plugin-vue-i18n": "^3.3.1". Changing that to "#intlify/vite-plugin-vue-i18n": "^7.0.0" solved the issue.

Related

How can I import a JSON file on Next.js on build?

I just want to do a simple thing: import a JSON file and read it within a function to return some specific data of it, but it's been really hard to do.
When on dev env, it works perfectly, but when I try to do the build, the file is not fount. It's like it's not being imported. Since I'm new with Next.JS architecture, I'm not able to find a solution by myself (read a lot of pages with help, but no success).
structure
- root
- config
- labels
data.json
index.ts
index.ts
import data from './data.json';
export type HomeLabels = typeof data.in.home;
export function getHomeLabels(language: string): HomeLabels {
return data[language as keyof typeof data].home;
}
data.json
{
"in":{
"home":{
"contact_button": "Contact",
"view_all_button": "View all"
}
},
"pt-br":{
"home":{
"contact_button": "Contato",
"view_all_button": "Ver tudo"
}
}
}
error on build
TypeError: Cannot read properties of undefined (reading 'home')
at getHomeLabels (/home/runner/work/boutme/boutme/.next/server/chunks/261.js:42:43)
All the solutions that I found out was related to using API or getStaticsProps and using on component. But I really don't want it. I think that it's possible to do what I want (import json and read just on a function), but it's been hard.

NextJs Webpack asset/source returns JSON as a string

Looking for some help to understand what is going on here.
The Problem
We are using a translation service that requires creating JSON resource files of copy, and within these resource files, we need to add some specific keys that the service understands so it knows what should and should not be translated.
To do this as simple as possible I want to import JSON files into my code without them being tree shaken and minified. I just need the plain JSON file included in my bundle as a JSON object.
The Solution - or so I thought
The developers at the translation service have instructed me to create a webpack rule with a type of assets/source to prevent tree shaking and modification.
This almost works but the strange thing is that the JSON gets added to the bundle as a string like so
module.exports = "{\n \"sl_translate\": \"sl_all\",\n \"title\": \"Page Title\",\n \"subtitle\": \"Page Subtitle\"\n}\n";
This of course means that when I try and reference the JSON values in my JSX it fails.
Test Repo
https://github.com/lukehillonline/nextjs-json-demo
NextJs 12
Webpack 5
SSR
Steps To Reproduce
Download the test repo and install packages
Run yarn build and wait for it to complete
Open /.next/server/pages/index.js to see the SSR page
On line 62 you'll find the JSON object as a string
Open .next/static/chunks/pages/index-{HASH}.js to see the Client Side page
If you format the code you'll find the JSON object as a string on line 39
Help!
If anyone can help me understand what is going wrong or how I can improve the webpack rule to return a JSON object rather than a string that would be a massive help.
Cheers!
The Code
next.config.js
module.exports = {
trailingSlash: true,
productionBrowserSourceMaps: true,
webpack: function (config) {
config.module.rules.push({
test: /\.content.json$/,
type: "asset/source",
});
return config;
},
};
Title.content.json
{
"sl_translate": "sl_all",
"title": "Page Title",
"subtitle": "Page Subtitle"
}
Title.jsx
import content from "./Title.content.json";
export function Title() {
return <h1>{content.title}</h1>;
}
pages/index.js
import { Title } from "../components/Title/Title";
function Home({ dummytext }) {
return (
<div>
<Title />
<p>{dummytext}</p>
</div>
);
}
export const getServerSideProps = async () => {
const dummytext = "So we can activate SSR";
return {
props: {
dummytext,
},
};
};
export default Home;

Error: 'Map' is not exported from 'react-leaflet' (imported as 'LeafletMap')

Here is my code:
import { Map as LeafletMap, TileLayer } from 'react-leaflet';
function Map() {
return (
<div className="map">
<LeafletMap>
<TileLayer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution='© OpenStreetMap contributors'/>
</LeafletMap>
</div>
But I got an error saying Attempted import error: 'Map' is not exported from 'react-leaflet' (imported as 'LeafletMap'). I've tried changing the 'import { Map' to 'import { MapContainer' but still won't work. Instead I got another error saying:
./node_modules/#react-leaflet/core/esm/path.js 10:41
Module parse failed: Unexpected token (10:41)
File was processed with these loaders:
* ./node_modules/babel-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.
| useEffect(function updatePathOptions() {
| if (props.pathOptions !== optionsRef.current) {
> const options = props.pathOptions ?? {};
| element.instance.setStyle(options);
| optionsRef.current = options;
I also tried changing the react-leaflet version from ^3.2.1 to ^2.7.0 and leaflet from ^1.7.1 to ^1.6.0. But still no luck. Any solutions?
You'll have to explicitly transpile react-leaflet because the maintainer is not understanding they should change their transpilation target to a lower version in order to more fully support the nullish coalescing operator: https://github.com/PaulLeCam/react-leaflet/issues/877#issuecomment-841871904
You can try adding this to your babel config
{
"plugins": ["#babel/plugin-proposal-nullish-coalescing-operator"]
}
And then make sure you transpile node_modules/react-leaflet during your build. If you are already using #babel/preset-env then you only need to make sure you're transpiling react-leaflet during the build. If you're using webpack you can do something like
module: {
rules: [
{
test: /\.jsx?$/,
exclude: filename => {
return /node_modules/.test(filename) && !/react-leaflet/.test(filename)
},
use: ['babel-loader']
}
]
}

How to import a map defined in an external json file?

I have the following json file containing a configuration:
{
"config1": { //this would be a map
"a": [ "string1", "string2"],
"b": [ "string1", "string2"]
}
}
Prior to migrating to typescript the following worked:
import * as myConfig from './config.json';
...
myConfig.config1[this.state.section]; //section would be either "a" or "b"
Now the code gives me:
Element implicitely has an "any" type because blablabla has no index signature
Note that I made sure that the following are set in my tsconfig file:
"esModuleInterop": true,
"resolveJsonModule": true,
But it still doesn't work.
What am I missing?
Edit:
It seems has something to do with runtime validation, the following seems fine:
myConfig.config1["a"]; //alright!
but this is not:
const name:string = "a";
myConfig.config1[name]; //NOT!
regardless I need to pass a variable..how can I do that? :(
You don't need a asterisk any more. Starting Typescript 2.9 (I can be wrons about specific version) you can do just import myConfig from './config.json';
If you still have this issue I guess there is no typedef for your config file so typescript transpiler can't get what is the structure of your imported object.
create #types directory inside src folder of your project
create myConfig.d.ts inside of #types
define the structure of your config file in myConfig.d.ts like:
declare module "myConfig.json" {
const config: object;
export default config;
}
In order to make "bracket notation" working your config type should define an index signature like:
interface IConfig {
[ key: string ]: object;
}
You can read more about it https://www.typescriptlang.org/docs/handbook/interfaces.html#indexable-types

Index.js file continuously gives "JSON text did not start with array" despite being formatted as an array

I have a parse-server hosted by heroku, which has an index.js file utilized for its configuration. I want to use Mailgun to up functionality for the user to request a password reset, and I have set up the config file, following this answer, as follows:
var api = new ParseServer({
appName: 'App Name',
publicServerURL: 'https://<name>.herokuapp.com/parse',
databaseURI: databaseUri || 'mongodb://localhost:27017/dev',
cloud: process.env.CLOUD_CODE_MAIN || __dirname + '/cloud/main.js',
appId: process.env.APP_ID || 'myAppId',
masterKey: process.env.MASTER_KEY || '', //Add your master key here. Keep it $
serverURL: process.env.SERVER_URL || 'http://localhost:1337/parse', // Don't$
liveQuery: {
classNames: ["Posts", "Comments"] // List of classes to support for query s$
},
push: JSON.parse(process.env.SERVER_PUSH || "{}"),
verifyUserEmails: true, //causing errors
emailAdapter: { //causing errors
module: 'parse-server-simple-mailgun-adapter',
options: {
fromAddress: 'parse#example.com',
domain: '<domain>',
apiKey: '<key>',
}
}
});
This code does not work, though, because of the verifyUserEmails and emailAdapter. Removing both of them removes the "JSON text did not start with array" error. Adding either one of them back in results in the error being thrown. I have no idea why, though, since I do not see any obvious reason as to how they aren't being set up in an array correctly?
Do I need to set up the cooresponding config vars in heroku in addition to having them in the config file? I considered this, but appName and publicServerURL are not set up in this way and don't give this error.
emailAdapter.options.apiKey doesn't need a comma at the end since its the last element of it's JSON.
I wouldn't be surprised that you're also leaving in the comma at the end of verifyUserEmails when you include it improperly as well.
options: {
fromAddress: 'parse#example.com',
domain: '<domain>',
apiKey: '<key>',
}
This is not valid JSON, because there is a comma at the end of the apiKey line. The last item in a JSON object does not have a comma.
For anyone that is repeatedly running into this issue, I have figured out exactly what was going wrong. Despite the error informing me that my JSON was incorrectly formatted, it turns out it was actually that the module was misnamed. According to this post, the updated module has been renamed to '#parse/simple-mailgun-adapter'. Inserting this into the index.js, after ensuring I had ran the npm install --save #parse/simple-mailgun-adapter in my local repo, fixed the issue.