Public Access
fix(ui): stop old translations and page shrink on Android
The translation files get a content version in their URL, so a browser that cached an old file loads the new one. On touch screens the scroll lock of menus and selects no longer adds a right margin: Android Chrome reported one and the whole page became narrower.
This commit is contained in:
1 parent
6edb53162e
commit
25d2f0d0bd
4 files changed
+49
-1
No files matched your search
+2
-1
@@ -9,7 +9,8 @@ i18n.use(HttpBackend)
|
||||
lng: 'de',
|
||||
fallbackLng: 'en',
|
||||
backend: {
|
||||
loadPath: '/i18n/{{lng}}.json',
|
||||
// A browser kept an old file without its Cache-Control and showed raw keys; a new URL per version avoids that.
|
||||
loadPath: `/i18n/{{lng}}.json?v=${__TRANSLATIONS_VERSION__}`,
|
||||
},
|
||||
interpolation: {
|
||||
escapeValue: false
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import {createHash} from 'node:crypto';
|
||||
import {readdirSync, readFileSync} from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import {describe, expect, it, vi} from 'vitest';
|
||||
|
||||
vi.mock('i18next-http-backend', () => ({
|
||||
default: {type: 'backend', init() {}, read(language, namespace, callback) { callback(null, {}); }},
|
||||
}));
|
||||
|
||||
describe('translation files', () => {
|
||||
it('are loaded under a URL that changes with their content, so no browser keeps an old copy', async () => {
|
||||
const {default: i18n} = await import('./i18n.js');
|
||||
const loadPath = i18n.options.backend.loadPath;
|
||||
|
||||
const dir = path.resolve(import.meta.dirname, '../public/i18n');
|
||||
const hash = createHash('sha256');
|
||||
for (const file of readdirSync(dir).filter((name) => name.endsWith('.json')).sort()) {
|
||||
hash.update(readFileSync(path.join(dir, file)));
|
||||
}
|
||||
expect(loadPath).toBe(`/i18n/{{lng}}.json?v=${hash.digest('hex').slice(0, 12)}`);
|
||||
});
|
||||
});
|
||||
@@ -191,3 +191,12 @@
|
||||
@apply bg-background text-foreground antialiased;
|
||||
}
|
||||
}
|
||||
|
||||
/* Radix menus and selects lock the page scroll and add a right margin as wide as the scrollbar, measured as
|
||||
innerWidth minus the page width. Android Chrome can report a larger innerWidth, and then the whole page shrinks.
|
||||
Touch screens have no scrollbar to make room for. */
|
||||
@media (pointer: coarse) {
|
||||
html body[data-scroll-locked] {
|
||||
margin-right: 0 !important;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,29 @@
|
||||
import {createHash} from 'node:crypto';
|
||||
import {readdirSync, readFileSync} from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
import tailwindcss from '@tailwindcss/vite';
|
||||
|
||||
const translationsDir = path.resolve(import.meta.dirname, 'public/i18n');
|
||||
|
||||
// Changes whenever a translation changes, so the browser loads the new file under a new URL.
|
||||
const translationsVersion = () => {
|
||||
const hash = createHash('sha256');
|
||||
for (const file of readdirSync(translationsDir).filter((name) => name.endsWith('.json')).sort()) {
|
||||
hash.update(readFileSync(path.join(translationsDir, file)));
|
||||
}
|
||||
return hash.digest('hex').slice(0, 12);
|
||||
};
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
react(),
|
||||
tailwindcss(),
|
||||
],
|
||||
define: {
|
||||
__TRANSLATIONS_VERSION__: JSON.stringify(translationsVersion()),
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': path.resolve(import.meta.dirname, './src'),
|
||||
|
||||
Reference in new issue
Block a user