Calling translation of modal

For Workes & Pages, what is the name of the domain?

a-hr.xyz

What is the error number?

n/a

What is the error message?

n/a

What is the issue or error you’re encountering

Zaraz Consent is calling tranlated version only based on browser language

What are the steps to reproduce the issue?

As far as I understood, in the default set up Zaraz Consent is calling a translated version based on the user browser language.
However, in our case this is a problem as the law in Ukraine demands to display Ukrainian text by default (later the user can select English if they wish to).

We got this sorted for the pages (using CF worker), but I’m struggling to find a way to change the default approach set in Zaraz.

What we are trying to achieve: if the user lands on the Ukrainian page for the first time (the worker makes this happen even if an English version of this page was requested) the consent modal has to be displayed in Ukrainian (regardless of the browser language).
What tools are available:

  • pll_language cookie set by Polylang plugin (default value=“ua” on the pages in Ukrainian)
  • html lang=“ua” in the page source code

@yoav_zaraz I hope you can suggest if/how we can force the translation to be called as described above.

Since it’s relevant to the topic, I also would like to implement the removal of the value for pll_language cookie if the user selects “reject all” (currently, the value remains stored in the cookie based on the page language).

Many thanks in advance,
Igor

A couple of additional questions, hope you can point me in the right direction

  1. Re Polylang language cookie - in the case when the user rejects all cookies, something like define( ‘pll_language’, false ) should be implemented. How can I do this with Zaraz Consent?

  2. The auto-generated list of consents contains items irrelevant to our site (as we don’t use ads) - is there a way not to show them?

  3. The quality of the translation for the list of consents to Ukrainian is far from perfect. Is there any chance to influence/modify this from our end?

Please ignore questions related to Polylang language cookie - I found evidence, that language cookies treated as an exempt by EC law

Dear @yoav_zaraz, I hope you can find a spare minute to advise on our issues:

  • how we call a translated consent banner based on geo-IP, html lang=“ua” in the page code or value of the pll_language cookie, maybe there are other possibilities we are not aware of?
  • remove irrelevant lines from the auto-generated list of consents,
  • improve the quality of translations in the modal.

We always use Zaraz wherever possible and hope to implement consent management on it

Thanks,
Igor

Hey Igor,
We do not currently offer a way to control the language of the modal. You could however configure multiple languages (e.g. English and Ukrainain) to be de facto Ukrainian, and then users that have English or Ukrainian set as their language will both see Ukrainian. I will check with the team if we have other ideas for how to allow setting the language.

I’m not sure what you mean by “remove irrelevant lines”. Which lines are irelevant? If you enable TCF IAB compliance, you don’t have much control over the content of the modal. If you disable it, you can choose which purposes to present.

As for “improve the quality of translations in the modal” - what quality issue are you seeing with the current translations?

1 Like

Hey @yoav_zaraz, many thanks for your response!

You could however configure multiple languages (e.g. English and Ukrainain) to be de facto Ukrainian, and then users that have English or Ukrainian set as their language will both see Ukrainian

It would be lovely to hear back from you if your team can provide alternative ways to set the modal language (as the suggested approach would not be user-friendly for non-Ukrainian website visitors).
I’m wondering if you/we can use cf-ipcountry header for this purpose.

Re “remove irrelevant lines” - we don’t use ads, so I was wondering if there is a way to exclude them?

Re “improve the quality of translations in the modal” - at the moment the Google analytics translations use a call to action in an indefinite time (the direct translations would be “(you) save and/or access the data on the device”) instead of continuous time ("(to) save and/or access the data on the device).
I can help you with all Ukrainian translations should you agree to amend them.

Cheers,
Igor

We have added a way to override the language of the modal. It is currently being released, but you should soon be able to do something like this for example: zaraz.set("__zarazConsentLanguage", "pl-PL") to set force the modal language to Polish. You will probably want to create some kind of UI to allow users to switch languages, with which you can set a new language and reload the page, like this: zaraz.set("__zarazConsentLanguage", "en-US"); location.reload().

Your two other points are about TCF IAB support. Unfortunately this system is much more restricted and not in our control, things like the translations for example are not coming from Zaraz at all - they are automatically fetched from the TCF framework. I will make sure to report this issue upstream.

1 Like

Hi @yoav_zaraz, many thanks for your response.

Do I understand correctly that the suggested approach implements a change of modal language on the client side? Not sure if I understand where this should be included, please elaborate.

On a side note, have you considered using cf-ipcountry header to set the default language for the modal?

Cheers,
Igor

Yes, you should include

<script>zaraz.set("__zarazConsentLanguage", "en-US")</script>

in the <body> of your HTML to force the language, for example, to English. You can use it to force the language to anything else. You can then your HTML also include buttons or links that change the language, for example like this:

    <button onclick="zaraz.set('__zarazConsentLanguage', 'pl-PL'); location.reload();">
        Change Language to Polish
    </button>

We do not think that using the cf-ipcountry is viable solution as many countries have more than one official language.

2 Likes

Thanks @yoav_zaraz

True, that might be the case

However, in our situation this could be a way to go - please advise if we can somehow use this header to set a default language for users in Ukraine?

No, you cannot. But you can use the solution I mentioned earlier however, using zaraz.set('__zarazConsentLanguage', 'uk-UA'); (I believe this is the code for Ukranian), I’m not sure what is the issue with it?

Because all users will see the Ukrainian modal by default, instead of targeting this to Ukraine-based users only

Ah, that makes sense. I guess you’ll need to include this snippet only if the incoming request is from Ukraine (based on IP). You can use Workers (with HTMLRewriter) to do it, though I’m sure that there’s some WordPress plugin that will let you do it too.

Alternatively, you can use the Zaraz Context Enricher. You will have access to the country there, and you can set the __zarazConsentLanguage programmatically if the country is indeed Ukraine.

1 Like

Hi @yoav_zaraz
Happy New Year!

Could you please clarify if the enrichment worker kicks in before or after the routing worker (which we currently use)

the law in Ukraine demands to display Ukrainian text by default (later the user can select English if they wish to). We got this sorted for the pages (using CF routing worker)

Hello @yoav_zaraz

We’ve done some testing and need your help to proceed further

1. Accessing the country
Option 1. Using CF-IPCountry - with the following code in the Enricher:

export default {
  async fetch(request, env, ctx) {
    console.log("Worker is running! Processing request.");
    const countryCode = request.headers.get("CF-IPCountry");
    console.log(`CF-IPCountry Header: ${countryCode}`);
    return new Response(
      JSON.stringify({}),
      {
         headers: {
           "content-type": "application/json",
         },
      }
    );
  },
};

we get the following in the Enricher log:

“message”: [
“CF-IPCountry Header: null”
],

Option 2. Using request.cf.country - with the following code in the Enricher:

export default {
    async fetch(request, env, ctx) {
      console.log("Worker is running! Processing request.");
      const countryCode = request.cf.country;
      console.log(`CF-IPCountry Header: ${countryCode}`);
      return new Response(
        JSON.stringify({}),
        {
           headers: {
             "content-type": "application/json",
           },
        }
      );
    },
  }; 

we also can’t get the country code in the Enricher log:

Option 3, Using system.device.location - with the following code in the Enricher:

export default {
  async fetch(request, env, ctx) {
    console.log("Worker is running! Processing request.");
    const { system } = await request.json();
    console.log(`System Device Location: ${JSON.stringify(system?.device?.location)}`);
      return new Response(
        JSON.stringify({}),
        {
         headers: {
          "content-type": "application/json",
           },
        }
      );
  },
};

we get the following in the Enricher log:

“message”: [
“System Device Location: {"city":"Kensington","region":"England","regionCode":"ENG","isEUCountry":null,"country":"GB","continent":"EU","timezone":"Europe/London"}”
],

So we’ve managed to get country only using system.device.location, but does it depend on user consent to share the location or not?

2. set the __zarazConsentLanguage
I’ve added the code

<script>zaraz.set('__zarazConsentLanguage', 'uk-UA')</script>

to the page https://a-hr.xyz/blog/festive2025/ and I can see this script in the page source code
However, the banner is still displayed in English, not in Ukrainian
However, if I refresh the page, the correct language is applied - how can we achive this without refresh?

I also tried the following gpt-driven Enricher:

export default {
  async fetch(request, env, ctx) {
    console.log("Worker is running! Processing request.");
    const { system } = await request.json();

    // Log location and cookie data
    console.log(`System Device Location: ${JSON.stringify(system?.device?.location)}`);
    console.log(`PLL Language Cookie: ${system?.cookies?.pll_language}`);

    let events = [];

    // Check for location
    const country = system?.device?.location?.country;
    const pllCookie = system?.cookies?.pll_language;

      if ((country === "GB" || country === "UA") && pllCookie !== "en") {
           console.log("Applying uk-UA language setting");
              events = [
                  {
                       type: "code",
                       code: {
                            source: "inline",
                            code: `zaraz.set('__zarazConsentLanguage', 'uk-UA');`,
                            },
                  },
               ];
      } else {
        console.log("No language change needed");
      }

    return new Response(
        JSON.stringify({
            events: events,
        }),
        {
            headers: {
                "content-type": "application/json",
            },
        }
    );
  },
};

I’m getting the banner in English and see the following in the Enricher log:

{
“truncated”: false,
“executionModel”: “stateless”,
“outcome”: “ok”,
“scriptVersion”: {
“id”: “525205f0-662e-4a26-be9f-479973603555”
},
“scriptName”: “context-enricher”,
“diagnosticsChannelEvents”: ,
“exceptions”: ,
“logs”: [
{
“message”: [
“Worker is running! Processing request.”
],
“level”: “log”,
“timestamp”: 1737590475832
},
{
“message”: [
“System Device Location: {"city":"Willesden","region":"England","regionCode":"ENG","isEUCountry":null,"country":"GB","continent":"EU","timezone":"Europe/London"}”
],
“level”: “log”,
“timestamp”: 1737590475832
},
{
“message”: [
“PLL Language Cookie: undefined”
],
“level”: “log”,
“timestamp”: 1737590475832
},
{
“message”: [
“Applying uk-UA language setting”
],
“level”: “log”,
“timestamp”: 1737590475832
}
],
“eventTimestamp”: 1737590475824,
“event”: {
“request”: {
“url”: “https://a-hr.xyz/”,
“method”: “POST”,
“headers”: {
“content-type”: “application/json”
}
},
“response”: {
“status”: 200
}
},
“id”: 4
}

Could you please advise what do we do wrong and how we can achieve the desired behaviour:
If the end user is in Ukraine they see the consent banner in Ukrainian (regardless of their browser language locale and the language of the URL requested?

Which part of the enrichment context is responsible for consent plugin display language and how it should be set using the context enrichment worker?

As Yoav has been away for quite a while, maybe someone else from Cloudflare team can find a spare minute to assist please?

I’m struggling to understand which part of the enrichment context is responsible for consent modal display language and how we can set it using the context enrichment worker?

The following syntax does what I was looking for:

export default {
  async fetch(request, env, ctx) {
      console.log("Worker is running! Processing request.");
      const {
          system,
          client
      } = await request.json();

      // Log location and cookie data
      console.log(`System Device Location: ${JSON.stringify(system.device.location)}`);
      console.log(`PLL Language Cookie: ${system.cookies.pll_language}`);

      // Check for location
      const country = system.device.location.country;
      const pllCookie = system.cookies.pll_language;

      if (country === "UA") {
          if (pllCookie != "en") {
              console.log("Setting __zarazConsentLanguage in context");
              client.__zarazConsentLanguage = 'uk-UA';
          } else {
              console.log("No language change needed (cookie)");
          }
      } else {
          console.log("No language change needed (country)");
      }
      return new Response(
        JSON.stringify({system, client}));
  }
}