Skip to content

Instantly share code, notes, and snippets.

@dscheerens
Created May 6, 2020 20:11
Show Gist options
  • Select an option

  • Save dscheerens/29fe42555a75fc626b6f6791d677dbe7 to your computer and use it in GitHub Desktop.

Select an option

Save dscheerens/29fe42555a75fc626b6f6791d677dbe7 to your computer and use it in GitHub Desktop.

Revisions

  1. dscheerens created this gist May 6, 2020.
    31 changes: 31 additions & 0 deletions define-translation-keys.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,31 @@
    const TRANSLATION_KEY_PLACEHOLDER = Symbol('TRANSLATION_KEY_PLACEHOLDER');
    type TranslationKeyPlaceholder = typeof TRANSLATION_KEY_PLACEHOLDER;

    export interface TranslationStructure {
    [key: string]: TranslationStructure | TranslationKeyPlaceholder;
    }

    export type TranslationKeysOf<T extends TranslationStructure> = {
    [P in keyof T]: T[P] extends TranslationStructure ? TranslationKeysOf<T[P]> : string
    };

    export function defineTranslationKeys<T extends TranslationStructure>(
    translationStructure: (t: TranslationKeyPlaceholder) => T
    ): TranslationKeysOf<T> {
    return generateTranslationKeys(translationStructure(TRANSLATION_KEY_PLACEHOLDER));
    }

    function generateTranslationKeys<U extends TranslationStructure>(structure: U, prefix?: string): TranslationKeysOf<U> {
    return Object.keys(structure).reduce<Partial<TranslationKeysOf<U>>>(
    (keys, key) => {
    const value = structure[key];
    const path = prefix === undefined ? key : `${prefix}.${key}`;

    return {
    ...keys,
    [key]: value === TRANSLATION_KEY_PLACEHOLDER ? path : generateTranslationKeys(value, path)
    };
    },
    {}
    ) as TranslationKeysOf<U>;
    }