diff --git a/.changeset/nasty-seahorses-confess.md b/.changeset/nasty-seahorses-confess.md new file mode 100644 index 00000000..180b85fe --- /dev/null +++ b/.changeset/nasty-seahorses-confess.md @@ -0,0 +1,15 @@ +--- +'@vocab/phrase': minor +'@vocab/core': minor +--- + +Vocab pull: support custom key + +```json +{ + "thanks": { + "message": "Thanks", + "global-key": "app.thanks.label" + } +} +``` diff --git a/fixtures/phrase/src/mytranslations.vocab/translations.json b/fixtures/phrase/src/mytranslations.vocab/translations.json index 2ce5817e..80a6f71b 100644 --- a/fixtures/phrase/src/mytranslations.vocab/translations.json +++ b/fixtures/phrase/src/mytranslations.vocab/translations.json @@ -9,8 +9,8 @@ "world": { "message": "world" }, - "profile": { - "message": "profile", - "global-key": "app.common.profile" + "thanks": { + "message": "Thanks", + "global-key": "app.thanks.label" } } diff --git a/packages/core/src/config.ts b/packages/core/src/config.ts index cfde48ab..594d505d 100644 --- a/packages/core/src/config.ts +++ b/packages/core/src/config.ts @@ -202,3 +202,5 @@ export function resolveConfigSync( return null; } + +export const GLOBAL_KEY = 'global-key'; diff --git a/packages/core/src/load-translations.ts b/packages/core/src/load-translations.ts index c1836694..6f697b48 100644 --- a/packages/core/src/load-translations.ts +++ b/packages/core/src/load-translations.ts @@ -21,6 +21,7 @@ import { getDevTranslationFileGlob, } from './utils'; import { generateLanguageFromTranslations } from './generate-language'; +import { GLOBAL_KEY } from './config'; export function getUniqueKey(key: string, namespace: string) { return `${key}.${namespace}`; @@ -410,6 +411,17 @@ export async function loadAllTranslations( ); } keys.add(uniqueKey); + + const globalKey = + loadedTranslation.languages[config.devLanguage][key][GLOBAL_KEY]; + if (globalKey) { + if (keys.has(globalKey)) { + throw new Error( + `Duplicate keys found. Global key ${key} was found multiple times`, + ); + } + keys.add(globalKey); + } } } return result; diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 4b62a75d..13129efa 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -134,10 +134,10 @@ export interface TranslationFileMetadata { } export interface TranslationData { - 'global-key'?: string; message: TranslationMessage; description?: string; tags?: Tags; + 'global-key'?: string; } export type TranslationsByKey = Record< diff --git a/packages/phrase/src/config.ts b/packages/phrase/src/config.ts new file mode 100644 index 00000000..4221b726 --- /dev/null +++ b/packages/phrase/src/config.ts @@ -0,0 +1 @@ +export const GLOBAL_KEY = 'global-key'; diff --git a/packages/phrase/src/index.ts b/packages/phrase/src/index.ts index e0eba2a9..9575d217 100644 --- a/packages/phrase/src/index.ts +++ b/packages/phrase/src/index.ts @@ -1,4 +1,2 @@ export { pull } from './pull-translations'; export { push } from './push-translations'; - -export const GLOBAL_KEY = 'global-key'; diff --git a/packages/phrase/src/pull-translations.test.ts b/packages/phrase/src/pull-translations.test.ts index 46975063..ed3238f0 100644 --- a/packages/phrase/src/pull-translations.test.ts +++ b/packages/phrase/src/pull-translations.test.ts @@ -41,11 +41,17 @@ describe('pull translations', () => { 'hello.mytranslations': { message: 'Hi there', }, + 'app.thanks.label': { + message: 'Thank you.', + }, }, fr: { 'hello.mytranslations': { message: 'merci', }, + 'app.thanks.label': { + message: 'Merci.', + }, }, }), ); @@ -98,6 +104,10 @@ describe('pull translations', () => { "greeting", ], }, + "thanks": { + "global-key": "app.thanks.label", + "message": "Thank you.", + }, "world": { "message": "world", }, @@ -106,6 +116,9 @@ describe('pull translations', () => { "hello": { "message": "merci", }, + "thanks": { + "message": "Merci.", + }, "world": { "message": "monde", }, @@ -182,6 +195,10 @@ describe('pull translations', () => { "greeting", ], }, + "thanks": { + "global-key": "app.thanks.label", + "message": "Thanks", + }, "world": { "message": "world", }, diff --git a/packages/phrase/src/pull-translations.ts b/packages/phrase/src/pull-translations.ts index 5fac3921..badb0c4b 100644 --- a/packages/phrase/src/pull-translations.ts +++ b/packages/phrase/src/pull-translations.ts @@ -11,6 +11,7 @@ import type { TranslationFileContents, UserConfig } from '@vocab/core'; import { pullAllTranslations, ensureBranch } from './phrase-api'; import { trace } from './logger'; +import { GLOBAL_KEY } from './config'; interface PullOptions { branch?: string; @@ -61,7 +62,8 @@ export async function pull( defaultValues[key] = { ...defaultValues[key], ...allPhraseTranslations[config.devLanguage][ - getUniqueKey(key, loadedTranslation.namespace) + defaultValues[key][GLOBAL_KEY] ?? + getUniqueKey(key, loadedTranslation.namespace) ], }; } @@ -85,7 +87,9 @@ export async function pull( allPhraseTranslations[alternativeLanguage]; for (const key of localKeys) { - const phraseKey = getUniqueKey(key, loadedTranslation.namespace); + const phraseKey = + defaultValues[key][GLOBAL_KEY] ?? + getUniqueKey(key, loadedTranslation.namespace); const phraseTranslationMessage = phraseAltTranslations[phraseKey]?.message; diff --git a/packages/phrase/src/push-translations.test.ts b/packages/phrase/src/push-translations.test.ts index bb13635d..7a604546 100644 --- a/packages/phrase/src/push-translations.test.ts +++ b/packages/phrase/src/push-translations.test.ts @@ -63,10 +63,11 @@ describe('push', () => { .toMatchInlineSnapshot(` { "en": { - "app.common.profile": { - "global-key": "app.common.profile", - "message": "profile", + "hello.mytranslations": { + "message": "Hello", "tags": [ + "only for this key", + "greeting", "every", "key", "gets", @@ -74,11 +75,10 @@ describe('push', () => { "tags", ], }, - "hello.mytranslations": { - "message": "Hello", + "thanks.mytranslations": { + "global-key": "app.thanks.label", + "message": "Thanks", "tags": [ - "only for this key", - "greeting", "every", "key", "gets", @@ -98,10 +98,6 @@ describe('push', () => { }, }, "fr": { - "app.common.profile": { - "description": undefined, - "message": "profil", - }, "hello.mytranslations": { "description": undefined, "message": "Bonjour", @@ -149,10 +145,11 @@ describe('push', () => { .toMatchInlineSnapshot(` { "en": { - "app.common.profile": { - "global-key": "app.common.profile", - "message": "profile", + "hello.mytranslations": { + "message": "Hello", "tags": [ + "only for this key", + "greeting", "every", "key", "gets", @@ -160,11 +157,10 @@ describe('push', () => { "tags", ], }, - "hello.mytranslations": { - "message": "Hello", + "thanks.mytranslations": { + "global-key": "app.thanks.label", + "message": "Thanks", "tags": [ - "only for this key", - "greeting", "every", "key", "gets", @@ -184,10 +180,6 @@ describe('push', () => { }, }, "fr": { - "app.common.profile": { - "description": undefined, - "message": "profil", - }, "hello.mytranslations": { "description": undefined, "message": "Bonjour", diff --git a/packages/phrase/src/push-translations.ts b/packages/phrase/src/push-translations.ts index 31aef9f0..67c206ee 100644 --- a/packages/phrase/src/push-translations.ts +++ b/packages/phrase/src/push-translations.ts @@ -10,8 +10,7 @@ import { pushTranslations, } from './phrase-api'; import { trace } from './logger'; -import { loadAllTranslations, getUniqueKey } from '@vocab/core'; -import { GLOBAL_KEY } from '.'; +import { loadAllTranslations, getUniqueKey, GLOBAL_KEY } from '@vocab/core'; interface PushOptions { branch: string;