Sp-dev-docs: Localizing images (pictures) with SPFx web part

Created on 4 Dec 2020  路  12Comments  路  Source: SharePoint/sp-dev-docs

Category

  • [x] Question
  • [ ] Typo
  • [ ] Additional article idea

Question

How do you localize pictures (images) with SPFx framework?
For example, if I want to use picture-en-us.png for English, and picture-sv-se.png for Swedish (as an embedded resource/asset), so that in some component I could refer to it somewaht like this:

import * as strings from 'HelloWorldStrings';
<img src={strings.someImageInAssets} />

But this means, that both "picture-en-us.png" and "picture-sv-se.png" should be packed in assets, and switched dynamically with language change. Where do I include them?

I mean, you can switch asset files like en-us.js <=> sv-se.js using config, but how do you do the same thing for images?
This piece seems to address only texts? (it seems that it ignores the file it if I put ".png" file there as an entry 馃槃 )

  "localizedResources": {
    "VistoWebPartStrings": "lib/webparts/loc/{locale}.js",
    "ControlStrings": "node_modules/@pnp/spfx-controls-react/lib/loc/{locale}.js"
  }

I am talking here about physical image files to pack in (i.e. data: url can be probably used a workaround, but this is not the question). Please note that the same question actually applies to other file types (i.e non-text, binary resources). Maybe I need to do some additional webpack configuration (add a loader?), and then .png in config localizedResources will work?

Thank you in advance!

Environment details (development & target environment)

  • Your Developer Environment: [Windows 10]
  • Target Environment: [SharePoint Online, SharePoint 2019]
  • Framework: [Node.js v10]
  • Tooling: [SPFx v1.11.0]
spfx-general answered question

All 12 comments

Thank you for reporting this issue. We will be triaging your incoming issue as soon as possible.

Couple things... you can include the images within the bundle you deploy, but since only some users will need some images, IMHO that's not a good approach because everyone would download all the images. Instead, I'd put them somewhere accessible to all users.

@nbelyh said:

I mean, you can switch asset files like en-us.js <=> sv-se.js using config, but how do you do the same thing for images?

You don't... not like that. This is something that's used by the SPFx runtime module loader... by the time your code runs, that's already happened so you can't hoot into it. Plus, that's for strings... you want to reference an image, which is going to be an additional request, not a string.

What I'd do is use the context.pageContext.cultureInfo.currentUICultureName to determine the current page's 2-character locale setting and use that to dynamically build the URL to your localized image.

@andrewconnell Thank you for the answer!
Can I bother you with a follow-up question... If I would still want to include the images in the package (.sppkg), (considering on-premise scenario for example), how do I properly make URLs to those? I mean, I would be happy to host images outside, but if I do need to pack them in, and deploy together with the app, how do I build urls to these for example (considering webpack)?

Do I need to do something like this for every single image and every single language?

const img1_en = require('image.en-us.png');
const img1_se = require('image.sv-se.png');
... repeat for each image and each langauge...

const img1 = ... (select at runtime appropriate img1_xx depending on locale)
<img src={img1} />

I was hoping for something better than that 馃槃

Is it possible to tell the build to pack some stuff in, even though it is not explicitly required() by the web part, like it is done for strings? In case of localization, this thing probably needs to be sort of "parametric", so that you don't duplicate the same thing over and over again...

@andrewconnell The link suggests i userequire() and let webpack do it, like it is shown in the example in the comment just above yours... My concern is, this would requie duplicating the require for all languages. So this does not seem to be very pactical for the localization scenario. I was hoping that there is a better way (similar to what has been done for strings)?

Same concept... just make the string for the image filename dynamic in the require statement.

@andrewconnell
But if i make string in the require a variable, webpack will not pack the image file in, it will just say "file no found"?

Ah... good point. Then just list them as separate require statements. Since you won't have a lot, not a big deal. If you do have a lot, then this is a bad approach as you're back to my point above about inflating the bundle.

Another approach you could consider is modifying the webpack config & package to include images in the SPPKG so you aren't putting the images in the bundle, rather you're just putting them in the package. This way they are deployed alongside your bundle & other assets and you can just dynamically reference the CDN location of the file. If this works, it would be preferred... just requires some webpack config work... but you'd have to test this approach out. In theory, it would work... but not sure if it's possible.

@andrewconnell Thanks! Will try! Sounds interesting. Maybe extending "config"'s localizedResources to somehow support binary things could be a good thing to consider in the future? 馃槃 Please note that this not necessarily about images, it can also be about other files, like text or binary (regarding CDN, there can be a requirement that everything is hosted internally in the company for example).

@andrewconnell Looks like I was mistaking. Webpack has a special feature to support this scenario, so variables actually are working. I mean, the following require will actually pack all "matching by wildcard" files into bundle for example! Webpack is really awesome 馃槃

require('raw-loader!webparts/loc/email-template.' + context.pageContext.cultureInfo.currentUICultureName + '.txt');

Require with expression:
https://webpack.js.org/guides/dependency-management/#require-with-expression

Whoa... wasn't aware of that. Nice find!

Issues that have been closed & had no follow-up activity for at least 7 days are automatically locked. Please refer to our wiki for more details, including how to remediate this action if you feel this was done prematurely or in error: Issue List: Our approach to locked issues

Was this page helpful?
0 / 5 - 0 ratings