nevada_scout
nevada_scout

Reputation: 983

How to translate a key inside another translation in ngx-translate

I have a translation JSON file and I want to translate another translation inside the value of a different translation.

{
    "COMPANY_NAME": "Apple",
    "WELCOME_TEXT": "{{ COMPANY_NAME }} welcomes you to California!"
}

I can't see how to do this using ngx-translate in Angular 9, can anyone give me a pointer?

Upvotes: 4

Views: 3635

Answers (2)

Mustafah
Mustafah

Reputation: 4487

I created and using this decorator, which enable parameterized translation keys ! https://github.com/mustafah/translations#-parameterized-translations

Upvotes: 0

nevada_scout
nevada_scout

Reputation: 983

I managed to achieve this by implementing a custom TranslateCompiler as follows:

My app.module.ts:

// ...
imports: [
  TranslateModule.forRoot({
    compiler: { provide: TranslateCompiler, useClass: CustomTranslationCompiler }
  })
]
/// ...

My CustomTranslationCompiler.ts:

import { TranslateCompiler } from '@ngx-translate/core';

export class CustomTranslationCompiler implements TranslateCompiler {
  /**
   * This function is needed to implement the interface, but doesn't
   * actually seem to be used anywhere
   *
   * @param value The translation value
   * @param lang The current language
   */
  public compile(value: string, lang: string): string | Function {
    return value;
  }

  /**
   * Look at every translation and pre-translate any nested translation keys within them
   *
   * @param translations All of the translations for the app to be compiled
   * @param lang The current language
   */
  public compileTranslations(translations: any, lang: string): any {
    for (const key in translations) {
      if (translations.hasOwnProperty(key)) {
        translations[key] = this.translateNestedTranslation(translations[key], translations);
      }
    }

    return translations;
  }

  /**
   * Use a regex to search for and replace translations inside translations
   * with their translated value
   *
   * @param value The translation value
   * @param translations All of the translations for the app
   */
  private translateNestedTranslation(value: string, translations: Object): string {
    const searchRegex  = /{{\s([A-Z_:]*)\s?}}/g;
    const replaceRegex = /({{\s?[A-Z_:]*\s?}})/g;

    const matches = searchRegex.exec(value);
    if (matches && matches.length > 0) {
      const searchKey = matches[1];

      if (translations.hasOwnProperty(searchKey)) {
        // Replace the full translate syntax with the translated value
        value = value.replace(replaceRegex, translations[searchKey]);
      } else {
        // If we can't find the value, display only the missing key instead of the full translate syntax
        value = value.replace(replaceRegex, searchKey);
        console.error(`Error: Unable to find translation '${searchKey}'!`)
      }
    }

    return value;
  }
}

Some notes:

  • With this approach any translation parameters defined in the translation values must be in lowercase to not be matched by the search regex
  • The search and replacement regexes are different
  • I'm not sure why the compile() method is never called. My translations are arriving as an object so maybe that's why...

Upvotes: 1

Related Questions