Problem/Motivation

Per Gabor in https://drupal.org/node/2272363#comment-8822223 I implemented translatable configuration in a way how it was not intended by the design. What a lot of people need is the ability to have configuration per language. As maintainer of a Google Analytics I thought this is the way how I can allow my users to use independent UA codes per language. We had this already implemented in D7 with variables module.

Proposed resolution

Allow definition of translatable settings, but also block POTX from extracting them as translatable string to l.d.o. We could add a new key like translation_export: false to help POTX.

    account:
      type: string
      label: 'Web Property ID'
      translatable: true
      translation_export: false

Remaining tasks

Write patch.

User interface changes

None

API changes

Maybe

Comments

tstoeckler’s picture

So over in #2144413: Config translation does not support text elements with a format were currently discussing the topic of config_translation vs. l.d.o/locale as well. The solution that we agreed upon there is that you could do the following:

  • Have a container that is explicitly marked as translatable.
  • Have none of the contained scalars be translatable.

That would allow to translate the entire container with config_translation, but locale module and l.d.o would completely ignore it.
Something like this:

ua_codes:
  type: mapping
  label: 'UA codes'
  translatable: true
  mapping:
    account:
      # string is not translatable!
      type: string
      label: account
    ...

Note that this currently does not work, but the patch in the referenced issue would make it so.
Would that be of any help?

hass’s picture

I'm not sure I fully understand you, but it sounds like I must restructure my modules variable names and the "tree". This sounds very bad to me as it is not flexible.

hass’s picture

We could also allow translatable_setting: true. This will disable potx extraction, but still allow settings to be translatable. Than we do not need two at the same time... Just one.

Gábor Hojtsy’s picture

@hass: I don't think your module would ship with default settings in those site specific items. potx will only export translatable things from default configuration (config files in config/install/* in your module). So not sure what are the settings affected. Eg. you would not ship with UA codes I think.

The larger problem with trying to use config translation as a generic system for per-language settings storage is with permissions and validation, that is mostly security. To access any of the settings forms only requires one flat permissions for ALL of them. If you have that permission, you can translate views, contact forms, etc. There is no built-in way to limit this for your "translation" form. And then widgets and validation. There is some support for shipping with your own widgets and validation but you need to implement them separate from your data entry form (or somehow figure out how to make them work for both the base settings form and the translation form). I believe your UA form element has a form item prefix, it has validation on length, etc. This is not possible with the text translation system. Some of the values you want to store per language need to have their own widgets, eg. a select box for an integer value with options that make sense for the user.

So I think at best you may need to override the route permissions checking for the translatable tab and subpages if you want more stricter permissions vs. the global flat permission for config translation and implement your own config translation widget/validation integration. This is probably much more and totally on your module to do than the potx extraction problem.

Once again locale/potx only deals with default shipped configuration that is in your config/install/* directory in your modules/projects. Unless those have non-universal data (which I doubt), marking them translatable should not be an issue. However I think what you would want to use is not even translatable, but your own property that your widget can respond and provide your custom translation UI, so all you reuse from config translation would be the standard tabs, summary and overview implementation and the shell of the translation form.

Does that make sense?

Gábor Hojtsy’s picture

Title: Per language settings may be exported to l.d.o » Per language settings (vs translated settings) are not directly supported
Gábor Hojtsy’s picture

To elaborate on #4 with concrete info:

  1. You would define your own named type (eg. type: google_analytics_settings) for the part of the config translation stuff that you want covered (it would be a container type as per #1 so definitely ignored by locale/localize.drupal.org).
  2. Then use hook_config_translation_type_alter to alter the form class for your type.
  3. Implement your form element class according to ElementInterface.

I don't think we even explored/thought about how this may work, so you are on uncharted territory. This may let you integrate your translation with your own form element set that can then use whatever widgets you want with whatever validation and still store the settings as a language config override. Sounds like fun to try, ha? :)

hass’s picture

Well, I do not know how to implement all these details. Missing validation and permission check sounds like problems I cannot accept myself and haven't tested yet. I'm not deep enough in D8 to implement all this stuff. One of my concerns is that we should keep the settings in the existing config files. I'm sure we do not like to re-invent the storage wheel again.

Gábor Hojtsy’s picture

@hass: well, it may be problematic but as said you are trying to use this system for something it was not designed for... I think its a triumph that (if) it is even possible to do :D Also I think we may have crossposted. You can try the custom type/widget stuff and see if that works in some way for you and then delve into permissions.

hass’s picture

Some time passed away now. Has this feature implemented in a generic way in core that contrib can just re-use or may has someone started a contrib project that allows per language settings?

tstoeckler’s picture

@hass: The issue referenced in #1 has been committed in the meantime. So it is now possible to mark container elements as translatable. The POTX integration can be controlled, by marking (or not-marking) the leaf elements of a container as translatable, similar to what I mentioned in #1.

What specifically is needed on top of that?

hass’s picture

I do not understand #1. can you explain it with a simplier example, please? I only want to allow people to translate a string variable if they have a need for it. If not needed it should use the untranslated value. It need to work like variables module with i18n under D7.

On top we need variables per domain. Same reasons for people with domain access modules. E.g. One google Analytics account per domain.

penyaskito’s picture

@hass: If I understood #1 correctly, that is the config schema:

ua_codes:
  type: mapping
  label: 'UA codes'
  translatable: true
  mapping:
    account:
      # string is not translatable!
      type: string
      label: account

So your config object should look like:

ua_codes:
    account: 'ua-whatever'

This, together with that schema, would make your config objects translatable, but not visible in the locale translation form or l.d.o. Does this make sense to both of you?

hass’s picture

The schema is at http://cgit.drupalcode.org/google_analytics/tree/config/schema/google_an...

It sounds like I'm not able to limit translatability to only some setting values this way.

How is this different to #2276343: Re-implement per language settings in D8?

hass’s picture

I need to ask again with a concrete example code. I'd like to allow account variable value to be configurable per language. These are variables that are individual to every site and language and must never extracted by potx as translatable string.

Is this possible with config objects? It would also not hurt if users are able to configure all values per language.

google_analytics.settings:
  type: mapping
  label: 'Google Analytics settings'
  mapping:
    account:
      type: string
      label: 'Web Property ID'
      translatable: true
    domain_mode:
      type: integer
      label: 'What are you tracking?'
    cross_domains:
      type: string
      label: 'List of top-level domains'
    visibility:
      type: mapping
      label: 'Visibility'
      mapping:
        pages_enabled:
          type: integer
          label: 'Add tracking to specific pages'
        pages:
          type: string
          label: 'Pages by their paths'
        roles_enabled:
          type: integer
          label: 'Add tracking for specific roles'
        roles:
          type: sequence
          label: 'Roles'
          sequence:
            type: string
            label: 'Role'
        custom:
          type: integer
          label: 'Allow users to customize tracking on their account page'
    track:
      type: mapping
      label: 'Links and downloads'
      mapping:
        outbound:
          type: boolean
          label: 'Track clicks on outbound links'
        mailto:
          type: boolean
          label: 'Track clicks on mailto links'
        files:
          type: boolean
          label: 'Track downloads'
        files_extensions:
          type: string
          label: 'File extension list'
        linkid:
          type: boolean
          label: 'Enable enhanced link attribution'
        urlfragments:
          type: boolean
          label: 'Track changing URL fragments as pageviews'
        userid:
          type: boolean
          label: 'Track User ID'
        messages:
          type: sequence
          label: 'Track messages of type'
          sequence:
            type: string
            label: 'Message type'
        site_search:
          type: boolean
          label: 'Track internal search'
        adsense:
          type: boolean
          label: 'Track AdSense ads'
        displayfeatures:
          type: boolean
          label: 'Track display features'
    privacy:
      type: mapping
      label: 'Privacy'
      mapping:
        anonymizeip:
          type: boolean
          label: 'Anonymize visitors IP address'
        donottrack:
          type: boolean
          label: 'Universal web tracking opt-out'
    custom:
      type: mapping
      label: 'Custom variables'
      mapping:
        dimension:
          type: sequence
          label: 'Custom dimensions'
          sequence:
            type: mapping
            label: 'Dimension'
            mapping:
              index:
                type: integer
                label: Index
              value:
                type: string
                label: Value
        metric:
          type: sequence
          label: 'Custom metrics'
          sequence:
            type: mapping
            label: 'Metric'
            mapping:
              index:
                type: integer
                label: Index
              value:
                type: string
                label: Value
    codesnippet:
      type: mapping
      label: 'Custom code snippets'
      mapping:
        create:
          type: sequence
          label: 'Create only fields'
          sequence:
            type: ignore
            label: 'Create field'
        before:
          type: string
          label: 'Code snippet (before)'
        after:
          type: string
          label: 'Code snippet (after)'
    translation_set:
      type: boolean
      label: 'Track translation sets as one unit'
    cache:
      type: boolean
      label: 'Locally cache tracking code file'
    debug:
      type: boolean
      label: 'Load debugging code of Google Universal Analytics'

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Berdir’s picture

Bump :)

I think the most obvious use case for this in core would be the frontpage/404/403 pages, where you might want to have different things per language. And I think the initial suggestion here (didn't really read past that) wouldn't really work as we can't change the structure of that anymore.

http://drupal.stackexchange.com/questions/222750/different-front-page-pe... for one person asking for that.

tijsdeboeck’s picture

Thanks Berdir for bumping this, and refering to my question on Stackexchange.

I'd really appreciate a solution for this, especially for the front-, 404 & 403 pages like you said. I was very supprised when I found out it wasn't possible in D8, and can't imagine that I would be the onlyone with this question...

Gábor Hojtsy’s picture

Once again core assumes that whatever is translatable in config is interface text and is not different values per language but is something that a translator could pre-translate to a different value without knowing the site/use case. So all the translatable configs are extracted for translation to localize.drupal.org. Swapping values per language is a different question and is not supported by config translation. That said, the config override system supports overriding arbitrary values by arbitrary criteria, so it should be relatively easy to write a contributed module to do that.

Berdir’s picture

@Gabor: Why can't we introduce a new type or something for string-that-might-be-localized and allow to translate it without triggering the locale sync?

Gábor Hojtsy’s picture

I think we can if there are people interested in / have time to work on it.

andypost’s picture

I think a case of 403/404 is not good example here, because 404 in case of domain module could cause wrong language negotiation

btw this should be done on top of config overrides, probably a contrib module makes sense

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

asgorobets’s picture

Here is an attempt to add support for this in contrib: #2914987: Language-specific overrides support
But I feel like having the system in core and potentially reusing the same UI that config_translation has would be way better than asking people to mess with yml files.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.