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.
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.
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.
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.
It was solved by
1) Cleaning the Google Chrome's cache at Network tab (clear all the cache also do the job)
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
attributeUsing
<location>
with a missingpath
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With