Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to disable caching for i18next translation.json files?

I'm running a single page app on IIS and using i18next library for translations in my app. The problem is that sometimes when I add new keywords to my translation.json file and hit refresh, the browser still uses the old cached translation file and this results in user seeing the added keywords but not translations. E.g. if I add a keyword "somekey": "Some text here..." then somekey would be displayed instead of the specified text.

As my translation.json file is located in a folder called locales like this:

locales
    en
      translation.json

I tried adding following setting to web.config:

<location path="locales">
  <system.webServer>
    <staticContent>
      <clientCache cacheControlMode="DisableCache" />
    </staticContent>
  </system.webServer>
</location>

However, when I looked at the network traffic with Chrome developer tools, I noticed that translation.json file is still coming from cache and Cache-Control: no-cache header is missing. Why this does not work? What is right way to disable the caching of the file?

EDIT: Just checked the site again and it seems that translation.json file now has the Cache-Control: no-cache header and it is actually being retrieved from server every time I refresh the page. At this point I'm thinking that the issue might have had something to do with our release process and config changes not being applied. Not sure though.

like image 486
JZ555 Avatar asked Feb 17 '17 22:02

JZ555


3 Answers

This is actually more tricky than it seems. I assume you're using the angular translate module.

I did cache busting where it loads the json files:

$translateProvider.useLoader('$translatePartialLoader', {
        urlTemplate: 'AppScripts/i18n/{part}-{lang}.json' + '?cb=' + (new Date()).getTime()
    });

That way it will never cache the language files, and will load the new ones on every request (without refreshing the page or clearing the cache).

The web config setting gets completely ignored, I believe because the way the plugin loads the files with ajax calls. Also, the json files can't be minified with .net bundling because the keys will change when compressed, so instead of "MAIN.FIRSTNAME": "First Name" you'll have something like "abc": "First Name" and it won't work since the views have the original names.

You can also use the version if you keep one, to bust the cache only when you release a new version, something like

    + '?v=' + myVersionVar

instead of using current timestamp which will always load the files on every request.

like image 69
Alx Avatar answered Nov 11 '22 03:11

Alx


I've came across this same situation using the combo SPA + i18next + IIS, and noticed that sometimes the json files have not been updated.

The main reason why this becames weird at some point is that there is a big chance that you have changed the IIS's web.config settings AFTER the files have been already cached by Google Chrome, since the first time the file has been downloaded without any Cache-Control header.

Cause

The json files was not presenting the Cache-Control: no-cache header, so the after a 304 - Not Modified response, it started to use google chrome's local disk cache.

Solution

It was solved by

1) Cleaning the Google Chrome's cache at Network tab (clear all the cache also do the job)

enter image description here

2) Placing a web.config file at /locales/ folder with the following staticContent rules, and location without specify a path attribute:

<?xml version="1.0" encoding="utf-8"?>
    <configuration>
        <location>
            <system.webServer>
                <staticContent>
                    <clientCache cacheControlMode="DisableCache" />
                </staticContent>
            </system.webServer>
        </location>
    </configuration>

As stated at the docs about the <location> tag:

path attribute

Using <location> with a missing path attribute applies the configuration settings to the current directory and all child directories.


In this case I've applied the rule specifically in the /locales/ folder, aiming to not interfere in caching for other static contents across the website, such as Images, JavaScript files, etc. The expected behavior may vary accordingly to your solution's needs.

like image 44
Leonardo Baggio Avatar answered Nov 11 '22 04:11

Leonardo Baggio


I had a similar problem, I needed the translations file to be retrieved fresh after each build. A solution I found was to, first, add a plugin that allows the webpack build hash to be available on runtime (add this on the webpack.config.js file):

webpack.ExtendedAPIPlugin()

This will allow you to declare the hash anywhere on your app

const hash = __webpack_hash__;

Then, on your i18next.init(), on the backend section, I added the hash as a parameter to the request.

`/locales/.json/hash=${hash}`

This way, the hash will be different after each new build, and on the first request after the build the most recent translations file will be retrieved, preventing it from using the cache.

like image 2
ivandax Avatar answered Nov 11 '22 03:11

ivandax