I'm trying to enable i18n json files with SSR on assets folder following this docs:
https://sap.github.io/spartacus-docs/i18n/
But when enabled, all files in PT folder results 404 error.
Here's my provideConfig on spartacus-configuration.module.ts file:
and my assets folder:
Thanks for your time, have a nice day!
Looks like it's trying to load a bunch of json files that aren't in your directories.
What I did on mine was I provided original Spartacus translations then I added mine below that:
provideConfig(<I18nConfig>{
i18n: {
resources: translations,
chunks: translationChunksConfig,
fallbackLang: 'en'
},
}),
provideConfig(<I18nConfig>{
i18n: {
backend: {
loadPath: 'assets/i18n-assets/{{lng}}/{{ns}}.json',
chunks: {
footer: ['footer']
}
}
},
})
otherwise, you can try to add those files its complaining about (orderApproval.json, savedCart.json, etc) to your 'pt' folder (not sure what language that is but perhaps Spartacus doesn't come with translations for it)
Related
I dont get how namespaces work in SAP Commerce. (https://sap.github.io/spartacus-docs/1.x/i18n/)
How i think it works is as follows:
Add the HTML {{ 'updatePasswordForm.oldPassword.placeholder' | cxTranslate }}
add that in your translation.ts
updatePasswordForm:{
oldPassword:{
placeholder: "Old password"
}
},
Config of chunks and namespaces mapping
with the last part i have my problem. I don't know where to put it and my project just uses the default one. How do do i find that?
I recommend using translation chunks as described there:
https://sap.github.io/spartacus-docs/i18n/#configuring-chunks-and-namespace-mapping
Working solution.
In app.module.ts in providers provide this config:
provideConfig({
i18n: {
backend: {
loadPath: 'assets/i18n-assets/{{lng}}/{{ns}}.json',
},
chunks: {
'forms': ['updatePasswordForm'],
},
},
}),
Afterwards, we can create a json file in src/assets/i18n-assets/en/forms.json and inside this file add the following lines:
{
"updatePasswordForm": {
"oldPassword": {
"placeholder": "Old password"
}
}
}
Explanation
loadPath defines the place where the translation chunks will be located.
{{lng}} defines a folder for translations language, e.g., en, de etc.
{{ns}} is placeholder for chunks.
In chunks we defined 'forms' field which corresponds to our translations file - forms.json.
Also, we have to map translations to namespaces - we have defined that our forms.json file contains namespaces ['updatePasswordForm'], so when translations will be needed for namespaces that starts with updatePasswordForm, the forms.json file will be loaded.
I've set up an alias for my public folder where I've placed my images.
So they are inside public/images. I have a subfolder for certain types of images - in this case, card brands.
They're in public/images/card-brands
Here is my alias config:
mix.webpackConfig({
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'#': __dirname + '/resources/js',
'#public' : __dirname + '/public'
},
},
})
I'm importing the images in my vue component file:
import amex from '#public/images/card-brands/amex.svg'
import discover from '#public/images/card-brands/discover.svg'
import visa from '#public/images/card-brands/visa.svg'
import mastercard from '#public/images/card-brands/mastercard.svg'
Then using it inside my components data like so:
export default {
name: 'PaymentMethod',
data() {
return {
...
visaSvg: visa,
mastercardSvg: mastercard,
discoverSvg: discover,
amexSvg: amex,
currentCardBrand: this.initialCurrentCardBrand
...
}
},
props: {
...
initialCurrentCardBrand: String,
...
}
computed: {
getCurrentCardBrandSvg() {
switch (this.currentCardBrand) {
case 'mastercard':
return this.mastercardSvg;
break;
case 'visa':
return this.visaSvg;
break;
case 'amex':
return this.amexSvg;
break;
case 'discover':
return this.discoverSvg;
break;
}
}
}
...
Finally, I'm using it on my template as and image src: <img class="w-10" :src="getCurrentCardBrandSvg">
Now, even though the images and my import path are using the card-brands subfolder, the URL that is generated ignores this and just looks for the images in the root images folder.
It should be:
/public/images/card-brands/visa.svg
but it's generating as
/public/images/visa.svg
How can I get it to keep my subfolder?
try this instead {{ asset('/images/card-brands/mastercard.svg')) }}
I faced a similar issue in laravel. I used the above format.Please correct me if Im wrong.
Edit: This could be slightly wrong. It works correctly for importing images via javascript, but I think grabbing images via laravel in blade templates still needs the images in the public folder.
The issue was not knowing that I was supposed to put my images folder inside the resources folder rather than public.
Laravel Mix will compile the images like it does the JS and SCSS and place it in public automatically.
So I created an images folder in resources, deleted my manually made images folder in public, and made an alias:
alias: {
'#images': __dirname + '/resources/images'
}
and now I can link to that inside my vue component.
import amex from '#images/card-brands/amex.svg'
import discover from '#images/card-brands/discover.svg'
import visa from '#images/card-brands/visa.svg'
import mastercard from '#images/card-brands/mastercard.svg'
The generated images will automatically be placed in public on the root level once I run npm run dev or npm run prod
It looks as though if you put your jsx files in the 'pages' folder of most gatsby starters, the urls follow the directory structure out of the box, so you can implement whatever urls you need (http://blah.com/foo/post1, http://blah.com/bar/post2) just by nesting folders in the source tree (pages/foo/post.jsx, pages/bar/post2.jsx).
The issue
I used the gatsby advanced starter (https://github.com/Vagr9K/gatsby-advanced-starter). It puts all content files not in pages/, but in a top-level content/ folder and I can't figure out the wiring to replicate foo/xxx, bar/xxx urls even after creating content/foo/post1.md, content/bar/post2.md folders.
It does have a siteconfig.js that sets a single path prefix, but I want two different prefixes for the 2 different sections of the site, so I just set it to "/" for now (builds seem to ignore whatever value I set for this config param anyway, so... shrug).
What I tried
I tried adding path to the frontmatter of the .md files and set it to the parent foldername. This was completely ignored (in any case I don't think that's what I want... I'd like to keep the generated slug as part of the url).
Separated use of gatsby-source-filesystem one for each subfolder hoping it would change graphql graph to recognize 2 separate data sources but it made no difference.
What am I doing wrong?
It looks as though if you put your jsx files in the 'pages' folder of most gatsby starters, the urls follow the directory structure out of the box [...]
That's not specific to Gatsby starters, that's Gatsby's default behaviour. Every js/jsx file in src/pages will be a page.
but in a top-level content/ folder
It still has the src/pages folder for normal pages. But the content folder holds the files will be transformed with the src/templates in gatsby-node.js to pages. Or in other words: The contents of the content folder get programmatically created with the defined template in gatsby-node.js (and the template lies in src/templates).
The path/url get's defined in the createPage function here: gatsby-nodeL144. This line is referencing the edge.node.fields.slug which gets queried in the GraphQL above here. The field gets added in the onCreateNode function. More specificially the slug field in the onCreateNodeField function. There you see that it gets passed a slug that gets defined above.
Create two folders in your src/content folder, e.g. blog and projects. Make sure that you have both of them defined in your gatsby-config.js:
{
resolve: 'gatsby-source-filesystem',
options: {
name: 'blog',
path: `${__dirname}/content/blog`,
},
},
{
resolve: 'gatsby-source-filesystem',
options: {
name: 'projects',
path: `${__dirname}/content/projects`,
},
},
In your gatsby-node.js add after the fileNode definition the line:
const pathPrefix = fileNode.sourceInstanceName
The sourceInstanceName is that what we defined as the name in gatsby-config entries.
Then you can alter the line to:
createNodeField({ node, name: "slug", value: `/${pathPrefix}${slug}` });
createNodeField({ node, name: 'sourceInstanceName', value: pathPrefix });
The second line is helpful if you then want to query only for one of the two folders, e.g.:
export const pageQuery = graphql`
query BlogQuery {
allMarkdownRemark(filter: { fields: { sourceInstanceName: { eq: "blog } } }
) {
edges {
node {
... etc
}
}
}
}
`
I'm new to bundlers and am currently learning about Fusebox. I really like it so far except that I can't figure out how to use it for a multi-page project. So far I've only been able to find a tutorial on how to do this using webpack, not for fusebox.
Input files in src folder:
index.html
index2.html
index.ts
Desired output in dist folder:
app.js
vendor.js
index.html
index2.html
Actual output in dist folder:
app.js
vendor.js
index.html
Here is my config in the fuse.js file:
Sparky.task("config", () => {
fuse = FuseBox.init({
homeDir: "src",
output: "dist/$name.js",
hash: isProduction,
sourceMaps: !isProduction,
plugins: [
[SassPlugin(), CSSPlugin()],
CSSPlugin(),
WebIndexPlugin({
title: "Welcome to FuseBox index",
template: "src/index.html"
},
WebIndexPlugin({
title: "Welcome to FuseBox index2",
template: "src/index2.html"
},
isProduction && UglifyJSPlugin()
]
});
// vendor should come first
vendor = fuse.bundle("vendor")
.instructions("~ index.ts");
// out main bundle
app = fuse.bundle("app")
.instructions(`!> [index.ts]`);
if (!isProduction) {
fuse.dev();
}
});
Setting WebIndexPlugin twice within plugins doesn't work. What is the correct way to set up a multi-html page project with fusebox?
The WebIndexPlugin can not be configured, to output more than one html file.
But if you don't use a hash for the generated bundles (e.g.: output: "dist/$name.$hash.js"), you don't need the WebIndexPlugin -- you can remove it completly from the plugins option. Because you already know the names of the generated bundles (vendor.js and app.js) you can just include the following lines
<script src="vendor.js"></script>
<script src="app.js"></script>
instead of the placeholder $bundles.
If you want, that both html files are copied from your src directory into your dist directory, you can add the following lines to your fuse.js script:
const fs = require('fs-extra');
fs.copySync('src/index.html', 'dist/index.html');
fs.copySync('src/index2.html', 'dist/index2.html');
Note: Don't forget to add fs-extra:^5.0.0 to your package.json
Might not been the case when the question was asked, but WebIndexPlugin now can be specified multiple times and also takes optional bundles parameter where list of bundles to be included in html can be specified (all bundles are included by default).
For example 2 html files (app1.html, app2.html) where each includes a common library (vendor.js), and different entry points (app1.js and app2.js)
app1.html
vendor.js
app1.js
app2.html
vendor.js
app2.js
Config would look like this:
const fuse = FuseBox.init({
homeDir : "src",
target : 'browser#es6',
output : "dist/$name.js",
plugins: [
WebIndexPlugin({
target: 'app1.html',
bundles:['vendor', 'app1']
}),
WebIndexPlugin({
target: 'app2.html',
bundles:['vendor', 'app2']
})
]
})
// vendor bundle, extracts dependencies from index1 and index2:
fuse.bundle("vendor").instructions("~[index1.ts,index2.ts]")
// app1 and app2, bundled separately without dependencies:
fuse.bundle("app1").instructions("!>index1.ts")
fuse.bundle("app2").instructions("!>index2.ts")
I am quite new at coding so please be indulgent... I searched a lot and I don't manage to get my issue fixed :(
I would like to get my images rendered through and html img tag. I saw that the best way in react is to import my images. Like this :
import avatar from './avatar.png';
export default class Connection extends React.Component {
render () {
return (
<div>
{this.props.user.firstname} {this.props.user.lastname}
<img src={avatar} className='img-circle' />
<a href='#' onClick={this.props.logout}>Déconnexion</a>
</div>
);
}
}
I use the following webpack config to load these images :
module: {
loaders: [
{ test: /\.jsx?$/, exclude: [/node_modules/], loader: 'babel' },
{ test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss-loader') },
{ test: /\.(png|gif|jpe?g|svg|jpg)$/i, loader: 'file-loader?hash=sha512&digest=hex&name=[path][name]-[hash].[ext]' },
{ test: /\.(png|gif|jpe?g|svg|jpg)$/i, loader: 'url-loader?limit=10000' }
]
}
I see that webpack manage to load the jpg or png files but when it comes to display it, it seems that the file generated/copied is not available (ex: /MyApp/avatar-50b93a2df8aec266d7c8c1c0f5719d1b.png is not available).
I use the webpack dev server so I don't see my files bundled and the dist or build folder created.
Any idea of solving my issue ?
Thanks,
When using the require within the img tag I get the following error :
Module not found: Error: Cannot resolve 'file' or 'directory' ./avatar
I tried to get the extension in the webpack config but it does not solve anything :(
Here is my public path config in my webpack config :
output: {
path: path.join(__dirname, '/build'),
publicPath: '/',
filename: 'bundle.js'
}
To load images with Webpack you need to do:
<img src={require('./avatar.jpg'})/>
Webpack crawls through your application codebase, code gets bundled into a single file however files are not kept in the same structure, by calling require Webpack will do dependency management for you, in this case the file will move around and code will be injected so it is pointing to it's bundled location.
You can take a look at this article from SurviveJS Book. Load Images Chapter