GENL / matice

Use your Laravel translations in JavaScript.
MIT License
99 stars 15 forks source link

Translation key with dot should works #3

Closed tortuetorche closed 4 years ago

tortuetorche commented 4 years ago

Expected behavior

Javascript running in the web console:

trans('Whoops! Something went wrong.'); // -> "Oups ! Un problème est survenu."

trans('Whoops!'); // -> "Oups !"

Current behavior

Javascript running in the web console:

// Error
trans('Whoops! Something went wrong.'); // -> Error:  Uncaught Translation key not found : "Whoops! Something went wrong." -> Exactly "Whoops! Something went wrong" not found

// OK
trans('Whoops!'); // -> "Oups !"

Versions

Translations

resources/lang/fr.json:

{
    "Whoops! Something went wrong." : "Oups ! Un problème est survenu.",
    "Whoops!" : "Oups !"
}

Comments

I think the root of this issue is here: https://github.com/GENL/matice/blob/50c08a0c12643bd8077e006e1aa9100e1445db87/src/js/Localization/core.ts#L195

Possible solution

With the help of a new boolean parameter (e.g splitKey or noSplit) for the Localization::findSentence() method, if an error occurs, we should fallback to const parts = [key] instead of const parts = key.split('.') via the splitKey or noSplit flag parameter.

Here a possible patch (need some tests) for the src/js/Localization/core.ts file:

class Localization {
 //...

 /**
   * Find the sentence using associated with the [key].
   * @param key
   * @param silentNotFoundError
   * @param locale
   * @param splitKey
   * @returns {string}
   * @private
   */
  private findSentence(key: string, silentNotFoundError: boolean, locale: string = MaticeLocalizationConfig.locale, splitKey: boolean = true): string {
    const translations: { [key: string]: any } = this.translations(locale)

    // At first [link] is a [Map<String, dynamic>] but at the end, it can be a [String],
    // the sentences.
    let link = translations

    const parts = splitKey ? key.split('.') : [key]

    for (const part of parts) {
      // Get the new json until we fall on the last key of
      // the array which should point to a String.
      try {
        // Make sure the _key exist.
        // If not this throws an error that is handled by the "catch" block
        // @ts-ignore
        assert(link[part])
        // @ts-ignore
        link = link[part]
      } catch (e) {
        // If key not found, try without splitting it.
        if (splitKey) {
          return this.findSentence(key, silentNotFoundError, locale, false)
        }

        // If key not found, try with the fallback locale.
        if (locale !== MaticeLocalizationConfig.fallbackLocale) {
          return this.findSentence(key, silentNotFoundError, MaticeLocalizationConfig.fallbackLocale, splitKey)
        }

        // If the key not found and the silent mode is on, return the key,
        if (silentNotFoundError) return key;

        // If key not found and the silent mode is off, throw error,
        throw `Translation key not found : "${key}" -> Exactly "${part}" not found`
      }
    }

    key.split('.').forEach((_key) => {

    });

    return link.toString();
  }
}
GENL commented 4 years ago

The dot in the key name is not yet supported. Thinking about the best way to implement it. This feature will be available soon,

tortuetorche commented 4 years ago

Alright, I'll send you a pull request of a possible solution, feel free to review it 👍

GENL commented 4 years ago

With pleasure,