Tailwind Logo

sxastarter サンプルを多言語サイトで利用できるように調整する - その3 RichText

XM CloudHeadless SXA

公開日: 2024-09-20

今回は多言語サイトで利用をするリッチテキストエディタに関しての動きを確認していきます。まず最初にリッチテキストエディタを利用してリンクを記載した場合の動作から確認をしていきます。

リッチテキストの動作

まず最初に、シンプルなリッチテキストのアイテムを配置します。そこにはリンクを追加している形です。

richtextlink01.png

この場合、HTML を参照すると以下のようなコードが設定されています。

HTML
<h1>Heading 1</h1>
<p>This is a test of the <a href="~/link.aspx?_id=90BA748D013345A1B948CD71E5EA940C&amp;_z=z">Global Menu 1</a></p>

リンクの設定の際に、パスではなくアイテムの ID が記載されています。これにより、対象となるアイテムが別のパスに移動した場合でもリンクを維持することが可能となっています。

プレビューモードに切り替えると、パスを利用した URL が設定されているのを確認することができます。

richtextlink02.png

それでは日本語のリソースを用意します。同じアイテムに対して日本語のデータを設定します。

richtextlink03.png

日本語に翻訳をしていますが、リンク先は先ほどと同じアイテムを指定しています。では URL はどういう風に表示されるでしょうか?

richtextlink04.png

このようにアイテムを指定している場合、ロケールが自動的に付与されるわけではないため、このままでは英語のコンテンツに対してリンクが張られる形となります。

リンクを調整する

まず RichText コンポーネントのコードに関しては、非常にシンプルな形となっています。

TypeScript
import React from 'react';
import { Field, RichText as JssRichText } from '@sitecore-jss/sitecore-jss-nextjs';

interface Fields {
  Text: Field<string>;
}

export type RichTextProps = {
  params: { [key: string]: string };
  fields: Fields;
};

export const Default = (props: RichTextProps): JSX.Element => {
  const text = props.fields ? (
    <JssRichText field={props.fields.Text} />
  ) : (
    <span className="is-empty-hint">Rich text</span>
  );
  const id = props.params.RenderingIdentifier;

  return (
    <div
      className={`component rich-text ${props.params.styles.trimEnd()}`}
      id={id ? id : undefined}
    >
      <div className="component-content">{text}</div>
    </div>
  );
};

前回の Link List と同様にロケールをベースとした URL を作成します。

TypeScript
const getLocale = function (props: SitecoreContextValue): string {
  let locale;

  if (!props.language || props.language === process.env.DEFAULT_LANGUAGE) {
    locale = '';
  } else {
    locale = '/' + props.language;
  }

  return locale;
};

export const Default = (props: RichTextProps): JSX.Element => {
  const { sitecoreContext } = useSitecoreContext();

  const contentLocale = getLocale(sitecoreContext);

  console.log(contentLocale);

今回はコンポーネントでロケールを正しく取得できているかを確認するために、一度 console.log で contentLocale を出力してみます。日本語のコンテンツを表示したときには ja-JP を、そうではない場合は値がないことを確認することができます。

richtextlink05.png

リッチテキストのデータがある場合、以下コードで結果を表示している形です。

TypeScript
  const text = props.fields ? (
    <JssRichText field={props.fields.Text} />
  ) : (
    <span className="is-empty-hint">Rich text</span>
  );

それでは props.fields.Text にはどのようなデータが入っているのでしょうか?これを日本語の時に確認をするために、改めて console.log を利用してデータを確認します。結果としては、以下の Json のデータが返ってきました。

JSON
{
  value: '<h1>見出し1</h1>\n' +
    '<p>これはテストです <a href="/Global-Menu-1?sc_site=Tailwindcss">グローバルメニュー 1</a></p>'
}

上記の URL に対してロケールを追加することで対応ができます。この際注意点としては以下の2つがあります。

  • 編集モードで返ってくるデータは ~/link.aspx?_ で始まる URL となる
  • 外部のリンクに関しては https:// という形で始まる

このため、 href に対して最初に / で始まる場合にロケールの処理をするのが良いとなります。

今回は以下のように変更をしていきます。

TypeScript
type RichTextValue = {
  value: string;
};

const addLocaleToUrls = (json: RichTextValue, locale: string): RichTextValue => {
  const urlRegex = /href="\/(?!\/)([^"]*)"/g;
  const updatedValue = json.value.replace(urlRegex, (_, url) => {
    return `href="${locale}/${url}"`;
  });

  return { value: updatedValue };
};

export const Default = (props: RichTextProps): JSX.Element => {
  const { sitecoreContext } = useSitecoreContext();

  const contentLocale = getLocale(sitecoreContext);
  const updatedJsonData = addLocaleToUrls(props.fields.Text, contentLocale);

  const text = props.fields ? (
    <JssRichText field={updatedJsonData} />
  ) : (
    <span className="is-empty-hint">Rich text</span>
  );

リッチテキストのコードの中にある URL に関して正規表現を利用して locale を追加していく形です。結果、日本語のリッチテキストの URL に対して locale を追加することができました。

richtextlink06.png

まとめ

今回は RichText のようにリンク情報だけではない場合に、URL の調整をする方法を確認していきました。基本的には結果として返ってくる Json のデータをどのように出力するのか、がポイントなるため、今回のように一度 Json のデータを取得して、何を変換するのが良いかを確認ができれば、調整は簡単です。

なお、リッチテキストコンポーネント以外にも、JssRichText を利用している sxastarter のコンポーネントは PageContent.tsx および Promo.tsx の2つがあります。必要に応じて同様の処理を各コンポーネントには追加してください。

関連タグ