Unicode not translating correctly for Right-to-left languages (Hebrew and Arabic)

Viewed 97

The bigquery code below provided by Mikhail Berlyant (thank you again!) works well on left-to-right languages such as Russian. However, it fails on right-to-left languages such as Arabic and Hebrew whenever there is a double quotation mark <" "> inside the text to be translated. The expected result should show all input text-to-be-translated without unicode letters inside the translation. Thanks!

CREATE TEMP FUNCTION
  decode(word string) AS ((
    SELECT
    IF
      (STARTS_WITH(word, '&#x'),
        safe.code_points_to_STRING(ARRAY(
          SELECT
            ifnull(SAFE_CAST(value AS int64),
              ASCII(value))
          FROM
            UNNEST(SPLIT(REPLACE(word, '&#', '0'),';')) value
          WHERE
            NOT value = '' )),
        word) ));
WITH
  DATA AS (
  SELECT
    'Arabic' AS lang,
    `'https://www.bbc.com/arabic/vert-fut-57352011'` AS url,
    `'&#x647;&#x644; &#x642;&#x648;&#x627;&#x645; "&#x627;&#x644;&#x633;&#x627;&#x639;&#x629; &#x627;&#x644;&#x631;&#x645;&#x644;&#x64A;&#x629;" &#x64A;&#x643;&#x633;&#x628; &#x627;&#x644;&#x645;&#x631;&#x623;&#x629; &#x62C;&#x627;&#x630;&#x628;&#x64A;&#x629; &#x623;&#x643;&#x628;&#x631;&#x61F;'` AS title
  UNION ALL
  SELECT
    'Arabic',
    `'https://www.bbc.com/arabic/world-57356844'`,
    `'&#x627;&#x644;&#x643;&#x646;&#x64A;&#x633;&#x629; &#x627;&#x644;&#x643;&#x627;&#x62B;&#x648;&#x644;&#x64A;&#x643;&#x64A;&#x629;: &#x643;&#x627;&#x631;&#x62F;&#x64A;&#x646;&#x627;&#x644; &#x623;&#x644;&#x645;&#x627;&#x646;&#x64A; &#x64A;&#x642;&#x62F;&#x645; &#x627;&#x633;&#x62A;&#x642;&#x627;&#x644;&#x62A;&#x647; &#x644;&#x644;&#x628;&#x627;&#x628;&#x627; &#x641;&#x631;&#x627;&#x646;&#x633;&#x64A;&#x633; &#x628;&#x633;&#x628;&#x628; "&#x627;&#x644;&#x641;&#x634;&#x644;" &#x641;&#x64A; &#x627;&#x644;&#x62A;&#x635;&#x62F;&#x64A; &#x644;&#x644;&#x627;&#x646;&#x62A;&#x647;&#x627;&#x643;&#x627;&#x62A; &#x627;&#x644;&#x62C;&#x646;&#x633;&#x64A;&#x629; &#x628;&#x62D;&#x642; &#x627;&#x644;&#x623;&#x637;&#x641;&#x627;&#x644;'`
  UNION ALL
  SELECT
    'Arabic',
    `'https://arabic.cnn.com/world/article/2021/06/04/munich-cardinal-submits-resignation-pope'`,
    `'&#x643;&#x627;&#x631;&#x62F;&#x64A;&#x646;&#x627;&#x644; &#x645;&#x64A;&#x648;&#x646;&#x64A;&#x62E; &#x64A;&#x642;&#x62F;&#x645; &#x627;&#x633;&#x62A;&#x642;&#x627;&#x644;&#x62A;&#x647; &#x644;&#x628;&#x627;&#x628;&#x627; &#x627;&#x644;&#x641;&#x627;&#x62A;&#x64A;&#x643;&#x627;&#x646; &#x628;&#x633;&#x628;&#x628; "&#x643;&#x627;&#x631;&#x62B;&#x629; &#x627;&#x644;&#x627;&#x639;&#x62A;&#x62F;&#x627;&#x621; &#x627;&#x644;&#x62C;&#x646;&#x633;&#x64A;" &#x628;&#x627;&#x644;&#x643;&#x646;&#x64A;&#x633;&#x629; &#x627;&#x644;&#x643;&#x627;&#x62B;&#x648;&#x644;&#x64A;&#x643;&#x64A;&#x629;'`
  UNION ALL
  SELECT
    'Arabic',
    `'https://alghad.com/%D9%88%D8%AA%D8%AA%D8%AC%D8%AF%D8%AF-%D8%A7%D9%84%D8%A2%D9%85%D8%A7%D9%84-%D8%A8%D8%B1%D8%AD%D9%8A%D9%84-%D9%86%D8%AA%D9%86%D9%8A%D8%A7%D9%87%D9%88-%D8%A7%D9%84%D9%85%D8%B1%D8%AA%D9%82%D8%A8-%D9%84/'`,
    `'&#x648;&#x62A;&#x62A;&#x62C;&#x62F;&#x62F; &#x627;&#x644;&#x622;&#x645;&#x627;&#x644; &#x628;&#x631;&#x62D;&#x64A;&#x644; &#x646;&#x62A;&#x646;&#x64A;&#x627;&#x647;&#x648; &#x627;&#x644;&#x645;&#x631;&#x62A;&#x642;&#x628; &#x644;&#x643;&#x646; &#x628;&#x62D;&#x630;&#x631;'`
  UNION ALL
  SELECT
    'Arabic',
    `'https://alghad.com/%D9%81%D9%88%D8%A8%D9%8A%D8%A7-%D8%A7%D9%84%D8%A7%D8%B1%D8%AA%D8%A8%D8%A7%D8%B7-%D8%A7%D9%86%D8%B3%D8%AD%D8%A7%D8%A8-%D9%88%D9%87%D8%B1%D9%88%D8%A8-%D9%81%D9%8A-%D8%A7%D9%84%D9%84%D8%AD%D8%B8/'`,
    `'"&#x641;&#x648;&#x628;&#x64A;&#x627; &#x627;&#x644;&#x627;&#x631;&#x62A;&#x628;&#x627;&#x637;".. &#x627;&#x646;&#x633;&#x62D;&#x627;&#x628; &#x648;&#x647;&#x631;&#x648;&#x628; &#x641;&#x64A; &#x627;&#x644;&#x644;&#x62D;&#x638;&#x627;&#x62A; &#x627;&#x644;&#x623;&#x62E;&#x64A;&#x631;&#x629;'`
  UNION ALL
  SELECT
    'Hebrew',
    `'https://www.srugim.co.il/568917-%D7%9C%D7%99%D7%90%D7%95%D7%9F-%D7%91%D7%90%D7%96%D7%9B%D7%A8%D7%94-%D7%9C%D7%A8%D7%91-%D7%90%D7%9C%D7%99%D7%94%D7%95-%D7%AA%D7%95%D7%A8%D7%AA%D7%95-%D7%94%D7%99%D7%99%D7%AA%D7%94-%D7%9B%D7%95%D7%9C'`,
    `'&#x5DC;&#x5D9;&#x5D0;&#x5D5;&#x5DF; &#x5D1;&#x5D0;&#x5D6;&#x5DB;&#x5E8;&#x5D4; &#x5DC;&#x5E8;&#x5D1; &#x5D0;&#x5DC;&#x5D9;&#x5D4;&#x5D5;: "&#x5EA;&#x5D5;&#x5E8;&#x5EA;&#x5D5; &#x5D4;&#x5D9;&#x5D9;&#x5EA;&#x5D4; &#x5DB;&#x5D5;&#x5DC;&#x5D4; &#x5E9;&#x5DC; &#x5D9;-&#x5DD;"'`
  UNION ALL
  SELECT
    'Hebrew',
    `'https://celebs.walla.co.il/item/3439567'`,
    `'&#x5D4;&#x5DB;&#x5D5;&#x5DB;&#x5D1;&#x5EA; &#x5D4;&#x5E2;-&#x5E0;-&#x5E7;&#x5D9;&#x5EA; &#x5E9;&#x5E0;&#x5EA;&#x5E4;&#x5E1;&#x5D4; &#x5D1;&#x5E6;&#x5E2;&#x5D9;&#x5E8;&#x5D5;&#x5EA;&#x5D4; &#x5E2;&#x5DD; &#x5E1;&#x5DE;&#x5D9;&#x5DD;'`
  UNION ALL
  SELECT
    'Hebrew',
    `'https://www.srugim.co.il/568906-%D7%90%D7%9C%D7%A4%D7%99-%D7%9E%D7%A4%D7%92%D7%99%D7%A0%D7%99%D7%9D-%D7%9E%D7%95%D7%9C-%D7%91%D7%99%D7%AA%D7%94-%D7%A9%D7%9C-%D7%A9%D7%A7%D7%93-%D7%90%D7%9C-%D7%AA%D7%9C%D7%9B%D7%99-%D7%A0%D7%92'`,
    `'&#x5D0;&#x5DC;&#x5E4;&#x5D9; &#x5DE;&#x5E4;&#x5D2;&#x5D9;&#x5E0;&#x5D9;&#x5DD; &#x5DE;&#x5D5;&#x5DC; &#x5D1;&#x5D9;&#x5EA;&#x5D4; &#x5E9;&#x5DC; &#x5E9;&#x5E7;&#x5D3;: "&#x5D0;&#x5DC; &#x5EA;&#x5DC;&#x5DB;&#x5D9; &#x5E0;&#x5D2;&#x5D3; &#x5D9;&#x5E9;&#x5E8;&#x5D0;&#x5DC;"'`
  UNION ALL
  SELECT
    'Russian',
    `'https://tass.ru/kultura/11559939'`,
    `'&#x424;&#x435;&#x441;&#x442;&#x438;&#x432;&#x430;&#x43B;&#x44C; "Theatrum" &#x43E;&#x442;&#x43A;&#x440;&#x44B;&#x432;&#x430;&#x435;&#x442;&#x441;&#x44F; &#x432; &#x41D;&#x43E;&#x432;&#x43E;&#x43C; &#x41C;&#x430;&#x43D;&#x435;&#x436;&#x435; &#x432; &#x41C;&#x43E;&#x441;&#x43A;&#x432;&#x435;'`),
  data2 AS (
  SELECT
    (
    SELECT
      AS STRUCT url AS url,
      lang AS lang,
      STRING_AGG(decode(word), ' ') AS translation
    FROM
      UNNEST(SPLIT(title, ' ')) word ) AS Foreign_txt
  FROM
    DATA )
SELECT
  Foreign_txt.lang AS lang,
  Foreign_txt.translation AS translation,
  Foreign_txt.url AS url
FROM
  data2;
1 Answers

Consider below example

create temp function decode(word string) as ((
  select if(starts_with(word, '&#x'), 
    safe.code_points_to_string(array(
      select ifnull(safe_cast(value as int64), ascii(value))
      from unnest(split(replace(word, '&#', '0'),';')) value
      where not value = ''
    )), 
    word)
));
select id, lang,
  ( select string_agg(decode(chars), '' order by offset)
    from unnest(regexp_extract_all(title, r'(?:&#x.{3};)+|[^&]+')) chars with offset 
  ) as translate
from data     

if applied to sample data in your question - output is

enter image description here

Related