Contentful logo

Contentful Community

Migrating values between locales

Hi

I need to add a new locale and initialize it for some fields with the value of an other locale.
Does the migration-cli (https://github.com/contentful/migration-cli) allow that ?
If yes, could you provide me an example ?

Thanks

Jerome

Why do you want to initialize the value of a field in a new locale with another locale?

Do you know about locale fallbacks? https://www.contentful.com/developers/docs/concepts/locales/ You could have your new locale fallback to the other locale and if the value of a certain field in the new locale doesn’t exist the API will provide the value of that field in the other locale in its place.

To answer your question about the migrations cli, you might use the migrations cli to change a non-localized field into a localized field or to generate the value of a new field from other existing fields for a particular locale but currently there’s not a way to transform an entry to generate the value of a field in one locale from the value of that field in a different locale

edit: @stephan.schneider is awesome!

I think it actually is possible, if you know the locale key up-front.

In the transformEntryForLocale method, you can access every locale within fromFields, like fromFields.author['en-US'].

Then you can check against currentLocale to be your target:

if (currentLocale === 'de-DE') {
  return fromFields.author['en-US'];
}

Hi @charlie

I know about locale fallbacks and that’s part of my issue in fact.
So far, we have a fallback for all our locales but in some cases, we have some default content that appears in a locale and we want to avoid that (some French content for i.e in a German content).
We had to do so because we have some common fields (date, author, assets…) that are contributed in the default fallback.
We’d like to set up a new locale for all those common fields and initialize them with the content of the actual default fallback.

Makes sense ?

Thanks

Jerome

Hi @stephan.schneider

Thanks ! Looks ok with text fields.
But I have errors with assets :
TypeError: Cannot read property ‘fr’ of undefined
at EntryTransformAction.transformEntryForLocale (/Volumes/Data/Users/jerome.hautecoeur/Projets/10-AtoutFrance/11-migrationCli/testImage.js:8:44)
at EntryTransformAction.applyTo (/usr/local/lib/node_modules/contentful-migration-cli/built/lib/action/entry-transform.js:23:58)
at
at process._tickCallback (internal/process/next_tick.js:160:7)

Any idea ?

Thanks
Jerome

Sadly assets are currently not part of the Migration CLI.

Do you derive the value for the asset from an entry? Then you might be able to use the contentful-management SDK as a workaround within the function.

The migration & transformEntryForLocale methods accepts returning a Promise, so you could manually set the new value for the asset via the SDK and then return the value for the entry.

// previously initialize the client with space & accesstoken (env/argv - consider yargs)

async function transformEntryForLocale (fields, locale) {
  const asset = await space.getAsset(fields.myAsset.sys.id)
  asset.fields.title[locale] = 'New Title'
  await asset.save()

  return fields[locale]
}

Would something like this be able to solve your usecase?

Hi @stephan.schneider

The issue appears on an entry in fact on which I have some assets.
The solution you gave would allow some transformation on assets themselves, right ?
What I would also need is to move the asset reference from a locale to an other.
Does the migration-cli allow that kind of transformation ?

Thanks

Jerome

Just tried it out with a single field having a single link to an asset and mutli field containing a list of links to assets. This is the migration that succeeded for me:

module.exports = function (migration) {
  migration.transformEntries({
    contentType: 'assetLink',
    from: ['single', 'multi'],
    to: ['single', 'multi'],
    transformEntryForLocale: function (fromFields, currentLocale) {
      if (currentLocale === 'de') {
        return {
          single: fromFields.single['en-US'],
          multi: fromFields.multi['en-US']
        };
      }

      return {
        single: fromFields.single[currentLocale],
        multi: fromFields.multi[currentLocale]
      };
    }
  });
};

That copied the references to assets from one locale to another - so effectively both locales contain the same values.

Hi @stephan.schneider

Yes, it works. The issues was on my side with some contents without assets.
I have to improve the error management in my script.

Thanks for helping !

Jerome