Missing key in i18next translation - javascript

I am using http://i18next.com/ for multi-language support in my Javascript app.
However, I am running into an issue where, presumably, the Javascript that renders HTML is loaded before the file i18next uses to find translations, and instead of the translation text, I get an error.
For example, for a key-translation pair of "popups.notifications":"Account Notifications" I'll get:
i18next::translator: missingKey undefined translation popups.notifications popups.notifications
The i18next JS is included in the page header before any other Javascript, but it makes no difference.
How do I make sure the translation file is loaded before any HTML rendering takes place?

I had the same problem with using i18n-fetch-backend with the following config:
.init({
...
backend: {
loadPath: "somePatch",
parse: (data) => {console.log(data)}
}
})
Removing the parse attribute solved it for me.

Related

How to render SVGs coming from api response using next/image or <img> in Next.js?

I've got a bunch of svgs coming from an api response, which I get inside useEffect. Response looks like this
{svg1: 'https://remoteserver.com/assests/svg1.svg', ...and so on}
( These svgs aren't static coming from /public folder. So I don't import them at top.)
I want to render them in nextjs using next/image or normal <img> tag, passing the url into src. I know that next.js by default don't support svgs.
<Image alt='SVG from api'
src={response.svg1}
width={'45px'}
height={'45px'}
objectFit='contain' />
According to docs, this is possible with dangerouslyAllowSVG, but there is security risk here, so I don't want to go this route.
I know packages like SVGR and babel-inline-svg are there to solve the issue, but they are for using svgs as react components.
I've also tried next-images and made use of withImages inside next.config.js.
const withImages = require('next-images')
module.exports = withImages({
reactStrictMode: true,
env: {
BASE_URL: process.env.BASE_URL
},
images: {
domains: ['remoteserver.com', 'remoteserver2.com']
},
webpack(config, options) {
return config
}
})
But the build is failing when I try next build.
./static/images/Logo.png
TypeError: unsupported file type: undefined (file: undefined)
What am I missing/doing wrong here ? Are there any alternate solutions ?
So apparantly I went with dangerouslyAllowSVG and added the CSP headers.
Still svg wasn't loading with <Image /> from next/image. It worked when I used normal <img> tag though.
Not sure if this is the best fix though :)

How to add custom scripts bundle in NextJS

I have some legacy custom javascripts that I need to bundle and put them in _document.js as a link. The filename should include a hash.
What would be the best way to accomplish this?
I tried webpack configs regarding entry/output but they break NextJs build.
The problem is that we use things like window, document, etc that do crash in server side.
Ideally what is needed is to inject this into a tag, as compiled / babelified javascript code.
What I tried is
Webpack HTML Plugin plus other plugins like InlineChunk or
InlineSource plugins. They didn't work because they generate code in
an index.html that is not used by NextJS.
Using Raw Loader to get the file content. Doesn't work because it is
not babelified.
Adding a custom entry to the Webpack config, like scripts:
'path/to/my-entry.js'. Didn't work because it adds a hash name to the
file and I have no way of knowing it.
Adding a custom entry into the NextJs polyfills. I thought it made
sense, but the polyfill tag has a nomodule which prevents its code to
run on new browsers.
Another options is to add the javascript code as a string, and then using __dangerouslySetInnerHtml but the problem is that I lose linter and babel abilities there.
I tried adding it as a page, but crashes for local development and even on build
webpack.config.js
module.exports = (nextConfig = {}) =>
Object.assign({}, nextConfig, {
webpack(config, options) {
const nextJsEntries = config.entry;
config.entry = async () => {
const entries = await nextJsEntries();
entries['pages/rscripts'] = 'test/test.js';
return entries;
};
...
Then in _document.js
<script src={`${publicRuntimeConfig.ASSET_PREFIX}/_next/${this.props.buildManifest.pages['/rscripts'][2]}`} />
You can just import js file like import 'path/to/js_file' in your _app.js/app.tsx file
import "../styles/globals.css"
import "../js/test"
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
export default MyApp
This one works fine for me
I wanted to add another answer here as I came across this and I believe some things have changed in Next JS. Next now has this script component that you can use to load external scripts or dangerously set a script.
The Next.js Script component, next/script, is an extension of the HTML
element. It enables developers to set the loading priority of
third-party scripts anywhere in their application, outside next/head,
saving developer time while improving loading performance.
The cool thing is you can put them into whatever pages you want, maybe you have a script you want on a homepage, but not other pages, and Next will extract them and place them on the page based on the strategy you select. There are a few gotchas, can't load in the head, beforeInteractive is a little finicky, so I would read the link above and the actual API reference before making any choices.
import { useEffect } from 'react';
import Script from 'next/script';
function thirdPartyScript() {
useEffect(() => {
// just for fun. This actually fires
// before the onLoad callback
}, []);
return (
<Script
id="test-script"
strategy="afterInteractive"
src="/public/pages/scripts/test.js"
onLoad={() => {
console.log('Onload fires as you would expect');
}}
/>
);
}

Next.js dynamic page params for static export

I have page which depends on route params (ex.: slug) like so http://example.com/blog/:slug. This route path is defined properly in my next.config.js file:
module.exports = withPlugins(plugins, {
exportPathMap: (defaultPathMap) => {
return {
'/': { page: '/home/home' },
'/blog/:slug': { page: '/careers/careers' }
}
}
});
This works fine when running the project in dev mode but once i export the project as static the route is not accessible and i get the regular 404 error from next.
Is there a way to fix this without using query parameters?
http://example.com/?slug=123
This solution https://github.com/zeit/next.js/blob/canary/examples/with-static-export/next.config.js is also not acceptable since the posts come from backend CMS
This is not possible because Next.js static export generates, well, static html pages. If you think about it, for this to work Next.js would somehow have to export every possible combination of letters valid in a url segment, which is not a good idea at all.
The closest you could get is using query parameters and the as attribute, for example when linking to a page:
<Link href='/blog/page?slug=SLUG_HERE' as='/blog/slug'>
// Link content here
</Link>
This only breaks when the user tries to link to or reload the page because there is no server-side support for the masking. You could theoretically use Nginx or Apache to proxy (is proxy the right word?) requests from /blog/SLUG_HERE to /blog/page?slug=SLUG_HERE. This is left up to you to figure out.
To handle dynamic paths in your next js project (provided you are going through the export route!).
Ensure trailingSlash is set to false or not defined at all in your next.config.js file
This way, every request will land in the index component, and from here, you can just handle your path redirect.
if (window.location.pathname !== "/") {
Router.push(window.location.pathname + window.location.search);
}
Ensure your project is mounted before doing this (e.g do this with useEffect hook)

Get asset path in Laravel from within React component?

I'm wondering what the best way is to get the asset path for things like images from inside a React component. I'm using Laravel, and the built-in asset() function that you can use in Blade files is exactly what I need, but I need it on the front-end in JS. Seems like Webpack territory, but I'm not sure what setting I need to modify.
The problem arises when my path is more than just the hostname, for example "localhost:3000/myproject/public" instead of just "localhost:3000".
Doing something like....
import myImage from '../../images/my-image.png'
...
<img src={myImage} />
results in a src path of "/images/my-image.png", which is not found, because the image actually resides at "/myproject/public/images/my-image.png"
In the past I've used the not-so-elegant solution of doing:
// react.blade.php
<body data-root-url={{ asset('') }}>
...
</body>
// helpers.js
export const rootUrl = document.querySelector('body').getAttribute('data-root-url')
While this hasn't gotten me into any trouble yet, I'm trying to find a better way, and I also started using Typescript recently and it (understandably) gets cranky about this because it technically could be null.
I've also tried the following in webpack.mix.js:
mix.webpackConfig({
output: {
publicPath: 'http://localhost:3000/myproject/public/',
},
})
but that doesn't seem to have any effect on image paths. Oddly enough though, this did work when running into a similar issue with code-splitting and looking for the JS chunks.
Any thoughts? Thanks!
I fix it by adding a new controller in the routes/web.php file.
Route::get('assets/{path}', function ($path) {
return response()->file(public_path("assets/$path"));
});
Then I added the images inside the folder public/assets/img/test.jpg and called it in my React component normally.
<Card sectioned>
<EmptyState image="/assets/img/test.jpg">
</EmptyState>
</Card>

Cannot load my JSON file: Http failure during parsing for JSON

I am attempting to load valid json but I am getting the error:
stackblitz
Http failure during parsing for ... .json
recipe.component.ts
url = '../../files/recipes.json';
recipes;
constructor(private fileService: FileLoaderService) {}
ngOnInit() {
this.fileService.getData(this.url).subscribe(res => console.log(res));
}
file-loader.service.ts
constructor(private http: HttpClient) { }
getData(url: string): Observable<any> {
return this.http.get(url);
}
What you have is not a valid JSON file. epascarello's answer tells you how to convert it to valid JSON, but another option is to just import the data directly.
Change the .json file extension to .ts
In your component, add import {recipes} from '../../files/recipes'
You've got your data! No need to mess around with http requests.
Having the export
export const recipes = [
{...}
]
makes it not a valid json document. Do not use export, remove it
JSON file should just be the json.
[
{...}
]
Couple this wrong and missing here:
This is not a valid JSON file (in the stackblitz). This is a constant which you can just import using a normal typescript import. If you want to load it using http, you should remove the export const recipes from the file
You should move the files folder to the assets folder of the project, this way the file can be loaded from the http server.
I spent a while ripping my hair out today (new to writing in StackBlitz). and even tried what was marked as answer on this thread, with no luck. Anyhow, the key seemed to be adding the .json file to the assets folder. Here's the link that finally got me immediate success. Hope that helps someone else keep their hair in tact. :-)
I've been asked to add code snippet, but not really too much to add, so I created a StackBlitz example that can be viewed, if desired. However, basically it all boils down to this: in StackBlitz when you're loading a local .json file, you do the same thing you normally would...except you ABSOLUTELY put that .json file in the "assets" folder (if you don't have one, create one)
this.http.get('/assets/user.json')
I added a StackBlitz example here

Categories

Resources