Grav-plugin-admin: Translation overrides is not working

Created on 12 Feb 2016  路  13Comments  路  Source: getgrav/grav-plugin-admin

Using how-to about translation overrides maybe i found an issue. I created _/user/languages/cs.yaml_ with simple content:

PLUGIN_ADMIN.TITLE: my translation

but "my translation" will not replace the original translation even if i delete cache. In settings i have _cs_ used as default language.

bug

Most helpful comment

It seems counter-intuitive to me that the other language strings do not fallback to their original language files when a custom override/translation is made.

Seems unnecessary that in order to get, for example, the Maintenance page provided by the Maintenance plugin to say "Under Construction" instead of "Site Offline" that I have to copy the entire contents of the plugins languages.yaml file into my custom language file.

All 13 comments

PLUGIN_ADMIN:
  TITLE: 'my translation'

should work

Just tested, and I can confirm that PLUGIN_ADMIN.TITLE: does not work, while @flaviocopes 's fix does work.

I've fixed the docs to reflect this. Thanks.

Yes, its working this way, but if i create such file and insert translation, its translated but the rest of the admin falls back to english.

Recreated, looking to solve

I'm not sure we can really solve this. The thing is this is YAML, and if you define:

PLUGIN_ADMIN.TITLE: my translation

You are really saying this key is "PLUGIN_ADMIN.TITLE", however when you request this, the string is treated as a "dot-seperated" key, that means it's broken up into:

[PLUGIN_ADMIN][TITLE]

So a nested array, where it expects to find the value in YAML in this format:

PLUGIN_ADMIN:
  TITLE: 'my translation'

So you simply must nest your YAML and your keys can't have periods in them.

Yes, the problem is that you're overriding TITLE but all the other keys defined in the Admin language file are not untranslated:

screen shot 2016-06-02 at 12 15 26

so there is no way to override a single language string of a plugin, you need to copy them all into your custom lang file.

Should we reopen this?

It seems counter-intuitive to me that the other language strings do not fallback to their original language files when a custom override/translation is made.

Seems unnecessary that in order to get, for example, the Maintenance page provided by the Maintenance plugin to say "Under Construction" instead of "Site Offline" that I have to copy the entire contents of the plugins languages.yaml file into my custom language file.

Yes I agree

Been debugging this, in https://github.com/getgrav/grav/blob/develop/system/src/Grav/Common/Config/CompiledLanguages.php we have


    /**
     * Load single configuration file and append it to the correct position.
     *
     * @param  string  $name  Name of the position.
     * @param  string  $filename  File to be loaded.
     */
    protected function loadFile($name, $filename)
    {
        $file = CompiledYamlFile::instance($filename);
        if (preg_match('|languages\.yaml$|', $filename)) {
            $this->object->mergeRecursive($file->content());
        } else {
            $this->object->join($name, $file->content(), '/');
        }
        $file->free();
    }

The user language file goes through the else, so calls https://github.com/getgrav/grav/blob/develop/system/src/Grav/Common/Data/Data.php

    /**
     * Join nested values together by using blueprints.
     *
     * @param string  $name       Dot separated path to the requested value.
     * @param mixed   $value      Value to be joined.
     * @param string  $separator  Separator, defaults to '.'
     * @return $this
     * @throws \RuntimeException
     */
    public function join($name, $value, $separator = '.')
    {
        $old = $this->get($name, null, $separator);
        if ($old !== null) {
            if (!is_array($old)) {
                throw new \RuntimeException('Value ' . $old);
            }
            if (is_object($value)) {
                $value = (array) $value;
            } elseif (!is_array($value)) {
                throw new \RuntimeException('Value ' . $value);
            }
            $value = $this->blueprints()->mergeData($old, $value, $name, $separator);
        }

        $this->set($name, $value, $separator);

        return $this;
    }

The $value = $this->blueprints()->mergeData($old, $value, $name, $separator); is the key, if $old is for example

  PLUGIN_FORM:
    NOT_VALIDATED: "Form not validated. One or more required fields are missing."
    NONCE_NOT_VALIDATED: "Oops there was a problem, please check your input and submit the form again."
    FILES: "Files Upload"
    ALLOW_MULTIPLE: "Allow More than one file"
    ALLOW_MULTIPLE_HELP: "Allows to select more than one file for upload."
    DESTINATION: "Destination"
    DESTINATION_HELP: "The location where the files should be uploaded to"
    ACCEPT: "Allowed MIME Types"
    ACCEPT_HELP: "A list of MIME Types that are allowed for upload"
    ERROR_VALIDATING_CAPTCHA: "Error validating the Captcha"
    DATA_SUMMARY: "Here is the summary of what you wrote to us:"
    NO_FORM_DATA: "No form data available"
    RECAPTCHA: "ReCaptcha"
    RECAPTCHA_SITE_KEY: "Site key"
    RECAPTCHA_SITE_KEY_HELP: "For more info visit https://developers.google.com/recaptcha"
    RECAPTCHA_SECRET_KEY: "Secret key"
    RECAPTCHA_SECRET_KEY_HELP: "For more info visit https://developers.google.com/recaptcha"
    GENERAL: "General"
    USE_BUILT_IN_CSS: "Use built-in CSS"
    FILEUPLOAD_PREVENT_SELF: 'Cannot use "%s" outside of pages.'
    FILEUPLOAD_UNABLE_TO_UPLOAD: 'Unable to upload file %s: %s'
    FILEUPLOAD_UNABLE_TO_MOVE: 'Unable to move file %s to "%s"'
    DROPZONE_CANCEL_UPLOAD: 'Cancel upload'
    DROPZONE_CANCEL_UPLOAD_CONFIRMATION: 'Are you sure you want to cancel this upload?'
    DROPZONE_DEFAULT_MESSAGE: 'Drop your files here or <strong>click in this area</strong>'
    DROPZONE_FALLBACK_MESSAGE: 'Your browser does not support drag and drop file uploads.'
    DROPZONE_FALLBACK_TEXT: 'Please use the fallback form below to upload your files like in the olden days.'
    DROPZONE_FILE_TOO_BIG: 'File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.'
    DROPZONE_INVALID_FILE_TYPE: "You can't upload files of this type."
    DROPZONE_MAX_FILES_EXCEEDED: "You can not upload any more files."
    DROPZONE_REMOVE_FILE: "Remove file"
    DROPZONE_REMOVE_FILE_CONFIRMATION: 'Are you sure you want to delete this file?'
    DROPZONE_RESPONSE_ERROR: "Server responded with {{statusCode}} code."

and $new is

  PLUGIN_FORM:
    NOT_VALIDATED: "Form not validated. One or more required fields are missing."

the return value is

  PLUGIN_FORM:
    NOT_VALIDATED: "Form not validated. One or more required fields are missing."

so it's not actually merging the data, but putting $new instead of $old.

The actual inner workings are too abstract for me, maybe @mahagr has an idea.

I don't think that blueprint should be used for language files. They are meant to merge complex data, not just recursively add missing items (which blueprint doesn't do).

Maybe we could add support for multiple merge strategies to the blueprints..

I'm surely missing something, but couldn't the custom language files be made to use mergeRecursive() instead of join() like the plugin language files do? Since the files are located in (e.g.) user/languages/en.yaml, I'm guessing the preg_match in CompiledLanguages.php could be updated to also look for user/languages/*.yaml in the file path/name, making it a minimal code change?

Was this page helpful?
0 / 5 - 0 ratings