fix: load translations from API instead of static CDN files
Some checks failed
CI / API Lint (push) Has been cancelled
CI / Admin UI Tests (push) Has been cancelled
CI / Admin UI Build (push) Has been cancelled
CI / Detect changes (push) Has been cancelled
CI / API Tests (push) Has been cancelled
CI / Scanner Lint (push) Has been cancelled
CI / Scanner Tests (push) Has been cancelled
CI / Banner Lint & Typecheck (push) Has been cancelled
CI / Banner Tests (push) Has been cancelled
CI / Banner Build (push) Has been cancelled
CI / Admin UI Typecheck (push) Has been cancelled
Some checks failed
CI / API Lint (push) Has been cancelled
CI / Admin UI Tests (push) Has been cancelled
CI / Admin UI Build (push) Has been cancelled
CI / Detect changes (push) Has been cancelled
CI / API Tests (push) Has been cancelled
CI / Scanner Lint (push) Has been cancelled
CI / Scanner Tests (push) Has been cancelled
CI / Banner Lint & Typecheck (push) Has been cancelled
CI / Banner Tests (push) Has been cancelled
CI / Banner Build (push) Has been cancelled
CI / Admin UI Typecheck (push) Has been cancelled
The banner was fetching /translations-{locale}.json from the CDN as
static files, but translations are stored in the DB and served via
the public /api/v1/translations/{siteId}/{locale} endpoint.
Fixes:
- fetchTranslations() now calls the public API endpoint
- loadTranslations() takes (apiBase, siteId, locale)
- banner.ts passes apiBase and siteId to loadTranslations()
- i18n.test.ts updated to match new signature
This commit is contained in:
5
apps/banner/package-lock.json
generated
5
apps/banner/package-lock.json
generated
@@ -1,12 +1,13 @@
|
||||
{
|
||||
"name": "@cmp/banner",
|
||||
"name": "@consentos/banner",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@cmp/banner",
|
||||
"name": "@consentos/banner",
|
||||
"version": "0.1.0",
|
||||
"license": "Elastic-2.0",
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-terser": "^0.4.4",
|
||||
"@rollup/plugin-typescript": "^12.1.2",
|
||||
|
||||
@@ -135,7 +135,7 @@ describe('i18n', () => {
|
||||
|
||||
describe('loadTranslations', () => {
|
||||
it('should return defaults for English locale', async () => {
|
||||
const t = await loadTranslations('https://cdn.example.com', 'en');
|
||||
const t = await loadTranslations('https://api.example.com', 'site-123', 'en');
|
||||
expect(t.title).toBe(DEFAULT_TRANSLATIONS.title);
|
||||
expect(t.acceptAll).toBe(DEFAULT_TRANSLATIONS.acceptAll);
|
||||
});
|
||||
@@ -143,10 +143,10 @@ describe('i18n', () => {
|
||||
it('should merge remote translations over defaults', async () => {
|
||||
vi.stubGlobal('fetch', vi.fn().mockResolvedValue({
|
||||
ok: true,
|
||||
json: () => Promise.resolve({ title: 'Wir verwenden Cookies', acceptAll: 'Alle akzeptieren' }),
|
||||
json: () => Promise.resolve({ strings: { title: 'Wir verwenden Cookies', acceptAll: 'Alle akzeptieren' } }),
|
||||
}));
|
||||
|
||||
const t = await loadTranslations('https://cdn.example.com', 'de');
|
||||
const t = await loadTranslations('https://api.example.com', 'site-123', 'de');
|
||||
|
||||
expect(t.title).toBe('Wir verwenden Cookies');
|
||||
expect(t.acceptAll).toBe('Alle akzeptieren');
|
||||
@@ -159,7 +159,7 @@ describe('i18n', () => {
|
||||
it('should fall back to defaults when fetch fails', async () => {
|
||||
vi.stubGlobal('fetch', vi.fn().mockRejectedValue(new Error('fail')));
|
||||
|
||||
const t = await loadTranslations('https://cdn.example.com', 'fr');
|
||||
const t = await loadTranslations('https://api.example.com', 'site-123', 'fr');
|
||||
expect(t.title).toBe(DEFAULT_TRANSLATIONS.title);
|
||||
|
||||
vi.unstubAllGlobals();
|
||||
|
||||
@@ -222,7 +222,7 @@ async function init(): Promise<void> {
|
||||
// Load translations
|
||||
// Use site-configured default_language if set, otherwise auto-detect
|
||||
const locale = config.default_language ?? detectLocale();
|
||||
const t = await loadTranslations(cdnBase, locale);
|
||||
const t = await loadTranslations(apiBase, siteId, locale);
|
||||
|
||||
// Capture a closure that re-opens the banner with current consent
|
||||
// pre-filled. Called from the floating button and from
|
||||
|
||||
@@ -84,34 +84,38 @@ export function normaliseLocale(locale: string): string {
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch translations for a locale from the CDN.
|
||||
* Fetch translations for a locale from the public API endpoint.
|
||||
* Returns null if not found or on error.
|
||||
*/
|
||||
export async function fetchTranslations(
|
||||
cdnBase: string,
|
||||
apiBase: string,
|
||||
siteId: string,
|
||||
locale: string,
|
||||
): Promise<Partial<TranslationStrings> | null> {
|
||||
try {
|
||||
const resp = await fetch(`${cdnBase}/translations-${locale}.json`);
|
||||
const resp = await fetch(`${apiBase}/api/v1/translations/${siteId}/${locale}`);
|
||||
if (!resp.ok) return null;
|
||||
return (await resp.json()) as Partial<TranslationStrings>;
|
||||
// API returns { strings: { ... } }
|
||||
const data = (await resp.json()) as { strings?: Partial<TranslationStrings> };
|
||||
return data.strings ?? null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load translations: try fetching from CDN, fall back to defaults.
|
||||
* Load translations: try fetching from API, fall back to defaults.
|
||||
*/
|
||||
export async function loadTranslations(
|
||||
cdnBase: string,
|
||||
apiBase: string,
|
||||
siteId: string,
|
||||
locale: string,
|
||||
): Promise<TranslationStrings> {
|
||||
if (locale === 'en') {
|
||||
return { ...DEFAULT_TRANSLATIONS };
|
||||
}
|
||||
|
||||
const remote = await fetchTranslations(cdnBase, locale);
|
||||
const remote = await fetchTranslations(apiBase, siteId, locale);
|
||||
if (!remote) {
|
||||
return { ...DEFAULT_TRANSLATIONS };
|
||||
}
|
||||
|
||||
6
package-lock.json
generated
Normal file
6
package-lock.json
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "consentos",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {}
|
||||
}
|
||||
Reference in New Issue
Block a user