Skip to content

Commit ffd8040

Browse files
committed
chore: changeset + test isolation for v2 translations manager
Adds a minor changeset for @blinkk/root and @blinkk/root-cms (noting the TranslationsDoc export removal), runs the admin-SDK emulator tests against a separate emulator project id so security.test.ts's clearFirestore() can't race them, and applies lint formatting. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pw4Wrj1oL9DuVbKoXasBTE
1 parent d9be7f6 commit ffd8040

6 files changed

Lines changed: 46 additions & 22 deletions

File tree

.changeset/lucky-poems-drive.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
'@blinkk/root': minor
3+
'@blinkk/root-cms': minor
4+
---
5+
6+
feat: v2 translations manager (behind `experiments.v2TranslationsManager`)
7+
8+
Wires up the v2 `TranslationsManager` end to end: a new `i18n.fallbacks`
9+
config for locale fallback chains, a translations manager UI at
10+
`/cms/translations` (list + editor) that replaces the v1 pages when the flag
11+
is on, publishing content docs now publishes their translations in the same
12+
write batch (plus a standalone per-doc Publish action), runtime reads in
13+
`createRoute()` and the missing-translations check use the v2 per-locale
14+
docs, and v1 translations are automatically copy-migrated (and published) on
15+
dev/build boot, leaving v1 data untouched as a backup.
16+
17+
BREAKING (experimental surface, no known callers): the unused
18+
`TranslationsDoc` interface and `RootCMSClient.dbTranslationsPath()`/
19+
`dbTranslationsRef()` helpers were removed, and `BatchRequest`/
20+
`BatchResponse.translations` now uses the per-locale doc schema
21+
(`Record<id, Record<locale, TranslationsLocaleDoc>>`).
22+
`BatchResponse.getTranslations()` accepts a locale or an explicit fallback
23+
chain and resolves `i18n.fallbacks`.

packages/root-cms/core/batch-request.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {Timestamp, getFirestore} from 'firebase-admin/firestore';
99
import {beforeEach, describe, expect, it} from 'vitest';
1010
import {RootCMSClient} from './client.js';
1111

12-
const FIREBASE_PROJECT_ID = 'rootjs-cms';
12+
const FIREBASE_PROJECT_ID = 'rootjs-cms-admin-tests';
1313

1414
function getTestApp() {
1515
const existing = getApps().find((app) => app.name === 'batch-test');

packages/root-cms/core/plugin.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -786,9 +786,8 @@ export function cmsPlugin(options: CMSPluginOptions): CMSPlugin {
786786
// translations before the build (SSG reads translations at build
787787
// time). A failure fails the build.
788788
if (options.experiments?.v2TranslationsManager) {
789-
const {migrateV1TranslationsIfNeeded} = await import(
790-
'./translations-migration.js'
791-
);
789+
const {migrateV1TranslationsIfNeeded} =
790+
await import('./translations-migration.js');
792791
const cmsClient = new RootCMSClient(rootConfig);
793792
try {
794793
await migrateV1TranslationsIfNeeded(cmsClient, {

packages/root-cms/core/publish-translations.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {beforeEach, describe, expect, it} from 'vitest';
1010
import {RootCMSClient} from './client.js';
1111
import {TranslationsLocaleDoc} from './translations-manager.js';
1212

13-
const FIREBASE_PROJECT_ID = 'rootjs-cms';
13+
const FIREBASE_PROJECT_ID = 'rootjs-cms-admin-tests';
1414

1515
function getTestApp() {
1616
const existing = getApps().find((app) => app.name === 'publish-test');

packages/root-cms/core/translations-manager.test.ts

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
translationsForLocaleV2,
1717
} from './translations-manager.js';
1818

19-
const FIREBASE_PROJECT_ID = 'rootjs-cms';
19+
const FIREBASE_PROJECT_ID = 'rootjs-cms-admin-tests';
2020

2121
function getTestApp() {
2222
const existing = getApps().find((app) => app.name === 'tm-test');
@@ -97,9 +97,7 @@ describe.skipIf(!process.env.FIRESTORE_EMULATOR_HOST)(
9797

9898
const dbPath = `Projects/${cmsClient.projectId}/TranslationsManager/draft/Translations`;
9999
// Slashes in the translations id are normalized to `--` in doc keys.
100-
const esDoc = await cmsClient.db
101-
.doc(`${dbPath}/Pages--index:es`)
102-
.get();
100+
const esDoc = await cmsClient.db.doc(`${dbPath}/Pages--index:es`).get();
103101
expect(esDoc.exists).toBe(true);
104102
const esData = esDoc.data() as TranslationsLocaleDoc;
105103
expect(esData.id).toBe('Pages/index');
@@ -115,9 +113,7 @@ describe.skipIf(!process.env.FIRESTORE_EMULATOR_HOST)(
115113
});
116114
expect(esData.sys.modifiedAt).toBeDefined();
117115

118-
const frDoc = await cmsClient.db
119-
.doc(`${dbPath}/Pages--index:fr`)
120-
.get();
116+
const frDoc = await cmsClient.db.doc(`${dbPath}/Pages--index:fr`).get();
121117
expect(frDoc.exists).toBe(true);
122118
expect((frDoc.data() as TranslationsLocaleDoc).strings).toEqual({
123119
[hashStr('one')]: {source: 'one', translation: 'un'},
@@ -160,12 +156,20 @@ describe.skipIf(!process.env.FIRESTORE_EMULATOR_HOST)(
160156

161157
it('loads translations by tags using array-contains-any', async () => {
162158
const tm = cmsClient.getTranslationsManager();
163-
await tm.saveTranslations('common', {hello: {es: 'hola'}}, {
164-
tags: ['common'],
165-
});
166-
await tm.saveTranslations('Pages/foo', {bye: {es: 'adios'}}, {
167-
tags: ['Pages/foo'],
168-
});
159+
await tm.saveTranslations(
160+
'common',
161+
{hello: {es: 'hola'}},
162+
{
163+
tags: ['common'],
164+
}
165+
);
166+
await tm.saveTranslations(
167+
'Pages/foo',
168+
{bye: {es: 'adios'}},
169+
{
170+
tags: ['Pages/foo'],
171+
}
172+
);
169173
const strings = await tm.loadTranslations({
170174
tags: ['common', 'other'],
171175
mode: 'draft',
@@ -303,9 +307,7 @@ describe.skipIf(!process.env.FIRESTORE_EMULATOR_HOST)(
303307
it('migrates the linked l10n sheet from the doc', async () => {
304308
await seedV1Translation('hello', {es: 'hola'}, ['Pages/index']);
305309
await cmsClient.db
306-
.doc(
307-
`Projects/${cmsClient.projectId}/Collections/Pages/Drafts/index`
308-
)
310+
.doc(`Projects/${cmsClient.projectId}/Collections/Pages/Drafts/index`)
309311
.set({
310312
id: 'Pages/index',
311313
collection: 'Pages',

packages/root-cms/core/translations-migration.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
migrateV1TranslationsIfNeeded,
1515
} from './translations-migration.js';
1616

17-
const FIREBASE_PROJECT_ID = 'rootjs-cms';
17+
const FIREBASE_PROJECT_ID = 'rootjs-cms-admin-tests';
1818

1919
function getTestApp() {
2020
const existing = getApps().find((app) => app.name === 'migration-test');

0 commit comments

Comments
 (0)